AWS - 使用 CloudFormation 将数据从一个 S3 存储桶移动到另一个存储桶

sem*_*ous 6 amazon-s3 amazon-web-services aws-cloudformation aws-lambda

我正在尝试使用 CloudFormation 创建一个堆栈。堆栈需要从中央 S3 存储桶中获取一些数据文件,并将它们复制到它自己的“本地”存储桶中。

我已经编写了一个 lambda 函数来执行此操作,当我在带有测试事件的 Lambda 控制台中运行它时它可以工作(测试事件使用真正的中央存储库并成功地将文件复制到指定的存储库)。

我当前的 CloudFormation 脚本执行以下操作:

  1. 创建“本地”S3 存储桶
  2. 创建 Lambda 函数可用于访问存储桶的角色
  3. 定义 Lambda 函数以将指定文件移动到“本地”存储桶
  4. 定义一些自定义资源来调用 Lambda 函数。

它在第 4 步开始出错 - Cloudformation 执行似乎在此处冻结 ( CREATE_IN_PROGESS)。此外,当我尝试删除堆栈时,它似乎只是卡住了DELETE_IN_PROGRESS。

下面是我在 CloudFormation 脚本中调用 Lambda 函数的方法:

"DataSync": {
    "Type": "Custom::S3DataSync",
    "Properties": {
        "ServiceToken": { "Fn::GetAtt" : [ "S3DataSync", "Arn" ] },
        "InputFile": "data/provided-as-ip-v6.json",
        "OutputFile": "data/data.json"
    }
},
"KeySync1": {
    "Type": "Custom::S3DataSync",
    "Properties": {
        "ServiceToken": { "Fn::GetAtt" : [ "S3DataSync", "Arn" ] },
        "InputFile": "keys/1/public_key.pem"
    }
},
"KeySync2": {
    "Type": "Custom::S3DataSync",
    "Properties": {
        "ServiceToken": { "Fn::GetAtt" : [ "S3DataSync", "Arn" ] },
        "InputFile": "keys/2/public_key.pem"
    }
}
Run Code Online (Sandbox Code Playgroud)

Lambda 函数本身:

exports.handler = function(event, context) {
    var buckets = {};
    buckets.in = {
        "Bucket":"central-data-repository",
        "Key":"sandbox" + "/" + event.ResourceProperties.InputFile
    };   
    buckets.out = {       
        "Bucket":"sandbox-data",       
        "Key":event.ResourceProperties.OutputFile || event.ResourceProperties.InputFile   
    };   

    var AWS = require('aws-sdk');   
    var S3 = new AWS.S3();   

    S3.getObject(buckets.in, function(err, data) {       
        if (err) {           
            console.log("Couldn't get file " + buckets.in.Key);           
            context.fail("Error getting file: " + err)       
        }       
        else {           
            buckets.out.Body = data.Body;           
            S3.putObject(buckets.out, function(err, data) {               
                if (err) {                   
                    console.log("Couln't write to S3 bucket " + buckets.out.Bucket);                   
                    context.fail("Error writing file: " + err);               
                }               
                else {                   
                    console.log("Successfully copied " + buckets.in.Key + " to " + buckets.out.Bucket + " at " + buckets.out.Key);                   
                    context.succeed();               
                }           
            });       
        }   
    });
}
Run Code Online (Sandbox Code Playgroud)

Jam*_*mes 4

您的自定义资源函数需要将信号发送回 CloudFormation 以指示完成、状态和任何返回值。您将在 CloudFormation 中看到 CREATE_IN_PROGRESS 状态,直到您通知它您的函数已完成。

向 CloudFormation 发送信号的通用方式是发布对预签名 S3 URL 的响应。但有一个cfn-response模块可以使 Lambda 函数中的操作变得更容易。有趣的是,为 Lambda 支持的自定义资源提供的两个示例使用不同的方法: