2016-03-31 48 views
10

我們正在使用CloudFormation模板創建S3存儲桶。無論何時將文件添加到S3存儲桶,我都希望關聯(向S3存儲桶添加事件)Lambda函數。使用雲形成爲S3存儲桶啓用Lambda函數

通過CloudFormation模板怎麼可能? CloudFormation中需要使用哪些屬性。

+0

你想創建一個水桶當一個lambda觸發或當物體(PutObject)在桶中產生的? – helloV

回答

5

您需要在CloudFormation模板中使用NotificationConfiguration屬性。不幸的是,它似乎要求存儲桶已經存在。爲了解決這個問題,你可以創建一個初始堆棧,然後用NotificationConfiguration對其進行更新。例如:

// template1.json 
{ 
    "AWSTemplateFormatVersion": "2010-09-09", 
    "Parameters": { 
    "mylambda": { 
     "Type": "String" 
    } 
    }, 
    "Resources": { 
    "bucketperm": { 
     "Type": "AWS::Lambda::Permission", 
     "Properties" : { 
     "Action": "lambda:InvokeFunction", 
     "FunctionName": {"Ref": "mylambda"}, 
     "Principal": "s3.amazonaws.com", 
     "SourceAccount": {"Ref": "AWS::AccountId"}, 
     "SourceArn": { "Fn::Join": [":", [ 
      "arn", "aws", "s3", "" , "", {"Ref" : "mybucket"}]] 
     } 
     } 
    }, 
    "mybucket": { 
     "Type": "AWS::S3::Bucket" 
    } 
    } 
} 

// template2.json -- adds the ConfigurationNotification 
{ 
    "AWSTemplateFormatVersion": "2010-09-09", 
    "Parameters": { 
    "mylambda": { 
     "Type": "String" 
    } 
    }, 
    "Resources": { 
    "bucketperm": { 
     "Type": "AWS::Lambda::Permission", 
     "Properties" : { 
     "Action": "lambda:InvokeFunction", 
     "FunctionName": {"Ref": "mylambda"}, 
     "Principal": "s3.amazonaws.com", 
     "SourceAccount": {"Ref": "AWS::AccountId"}, 
     "SourceArn": { "Fn::Join": [":", [ 
      "arn", "aws", "s3", "" , "", {"Ref" : "mybucket"}]] 
     } 
     } 
    }, 
    "mybucket": { 
     "Type": "AWS::S3::Bucket", 
     "Properties": { 
     "NotificationConfiguration": { 
      "LambdaConfigurations": [ 
      { 
       "Event" : "s3:ObjectCreated:*", 
       "Function" : {"Ref": "mylambda"} 
      } 
      ] 
     } 
     } 
    } 
    } 
} 

您可以使用AWS CLI工具創建堆棧是這樣的:

$ aws cloudformation create-stack --stack-name mystack --template-body file://template1.json --parameters ParameterKey=mylambda,ParameterValue=<lambda arn> 
# wait until stack is created 
$ aws cloudformation update-stack --stack-name mystack --template-body file://template2.json --parameters ParameterKey=mylambda,ParameterValue=<lambda arn> 
+0

我們是否需要在CFT的資源部分爲lambda編寫代碼?你指的是mylambda? – shiv455

+0

問題是如何在創建桶時觸發lambda而不是在將新文​​件添加到存儲桶時觸發lambda。 – helloV

+0

lambda不必在同一個模板中定義。桶配置只需要lambda ARN。如果您的lambda設置在其他地方,只需將ARN作爲模板參數傳遞即可。 – ataylor

1

低於鬥燙我已經添加在cloudformation notificationconfiguration這是用來創建S3桶沿。 。有效 !!

"bucketperm": { 
      "Type": "AWS::Lambda::Permission", 
      "Properties": { 
       "Action": "lambda:invokeFunction", 
       "FunctionName": "<arnvalue>", 
       "Principal": "s3.amazonaws.com" 
      } 
} 
12

以下是一個演示如何觸發一個lambda函數,只要將文件添加到S3存儲一個完整的,自包含的CloudFormation模板:

Launch Stack

Description: Upload an object to an S3 bucket, triggering a Lambda event, returning the object key as a Stack Output. 
Parameters: 
    Key: 
    Description: S3 Object key 
    Type: String 
    Default: test 
    Body: 
    Description: S3 Object body content 
    Type: String 
    Default: TEST CONTENT 
    BucketName: 
    Description: S3 Bucket name 
    Type: String 
Resources: 
    Bucket: 
    Type: AWS::S3::Bucket 
    DependsOn: BucketPermission 
    Properties: 
     BucketName: !Ref BucketName 
     NotificationConfiguration: 
     LambdaConfigurations: 
     - Event: 's3:ObjectCreated:*' 
      Function: !GetAtt BucketWatcher.Arn 
    BucketPermission: 
    Type: AWS::Lambda::Permission 
    Properties: 
     Action: 'lambda:InvokeFunction' 
     FunctionName: !Ref BucketWatcher 
     Principal: s3.amazonaws.com 
     SourceAccount: !Ref "AWS::AccountId" 
     SourceArn: !Sub "arn:aws:s3:::${BucketName}" 
    BucketWatcher: 
    Type: AWS::Lambda::Function 
    Properties: 
     Description: Sends a Wait Condition signal to Handle when invoked 
     Handler: index.handler 
     Role: !GetAtt LambdaExecutionRole.Arn 
     Code: 
     ZipFile: !Sub | 
      exports.handler = function(event, context) { 
      console.log("Request received:\n", JSON.stringify(event)); 
      var responseBody = JSON.stringify({ 
       "Status" : "SUCCESS", 
       "UniqueId" : "Key", 
       "Data" : event.Records[0].s3.object.key, 
       "Reason" : "" 
      }); 
      var https = require("https"); 
      var url = require("url"); 
      var parsedUrl = url.parse('${Handle}'); 
      var options = { 
       hostname: parsedUrl.hostname, 
       port: 443, 
       path: parsedUrl.path, 
       method: "PUT", 
       headers: { 
        "content-type": "", 
        "content-length": responseBody.length 
       } 
      }; 
      var request = https.request(options, function(response) { 
       console.log("Status code: " + response.statusCode); 
       console.log("Status message: " + response.statusMessage); 
       context.done(); 
      }); 
      request.on("error", function(error) { 
       console.log("send(..) failed executing https.request(..): " + error); 
       context.done(); 
      }); 
      request.write(responseBody); 
      request.end(); 
      }; 
     Timeout: 30 
     Runtime: nodejs4.3 
    Handle: 
    Type: AWS::CloudFormation::WaitConditionHandle 
    Wait: 
    Type: AWS::CloudFormation::WaitCondition 
    Properties: 
     Handle: !Ref Handle 
     Timeout: 300 
    S3Object: 
    Type: Custom::S3Object 
    Properties: 
     ServiceToken: !GetAtt S3ObjectFunction.Arn 
     Bucket: !Ref Bucket 
     Key: !Ref Key 
     Body: !Ref Body 
    S3ObjectFunction: 
    Type: AWS::Lambda::Function 
    Properties: 
     Description: S3 Object Custom Resource 
     Handler: index.handler 
     Role: !GetAtt LambdaExecutionRole.Arn 
     Code: 
     ZipFile: !Sub | 
      var response = require('cfn-response'); 
      var AWS = require('aws-sdk'); 
      var s3 = new AWS.S3(); 
      exports.handler = function(event, context) { 
      console.log("Request received:\n", JSON.stringify(event)); 
      var responseData = {}; 
      if (event.RequestType == 'Create') { 
       var params = { 
       Bucket: event.ResourceProperties.Bucket, 
       Key: event.ResourceProperties.Key, 
       Body: event.ResourceProperties.Body 
       }; 
       s3.putObject(params).promise().then(function(data) { 
       response.send(event, context, response.SUCCESS, responseData); 
       }).catch(function(err) { 
       console.log(JSON.stringify(err)); 
       response.send(event, context, response.FAILED, responseData); 
       }); 
      } else if (event.RequestType == 'Delete') { 
       var deleteParams = { 
       Bucket: event.ResourceProperties.Bucket, 
       Key: event.ResourceProperties.Key 
       }; 
       s3.deleteObject(deleteParams).promise().then(function(data) { 
       response.send(event, context, response.SUCCESS, responseData); 
       }).catch(function(err) { 
       console.log(JSON.stringify(err)); 
       response.send(event, context, response.FAILED, responseData); 
       }); 
      } else { 
       response.send(event, context, response.SUCCESS, responseData); 
      } 
      }; 
     Timeout: 30 
     Runtime: nodejs4.3 
    LambdaExecutionRole: 
    Type: AWS::IAM::Role 
    Properties: 
     AssumeRolePolicyDocument: 
     Version: '2012-10-17' 
     Statement: 
     - Effect: Allow 
      Principal: {Service: [lambda.amazonaws.com]} 
      Action: ['sts:AssumeRole'] 
     Path:/
     ManagedPolicyArns: 
     - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" 
     Policies: 
     - PolicyName: S3Policy 
     PolicyDocument: 
      Version: '2012-10-17' 
      Statement: 
      - Effect: Allow 
       Action: 
       - 's3:PutObject' 
       - 'S3:DeleteObject' 
       Resource: !Sub "arn:aws:s3:::${BucketName}/${Key}" 
Outputs: 
    Result: 
    Value: !GetAtt Wait.Data 
+0

非常感謝您的工作示例。它節省了很多時間!但是,你能告訴我爲什麼在該模板中有'S3Object'?我沒有看到它在任何地方? – Cherry

+0

@Cherry'S3Object'和'S3ObjectFunction'自動在S3存儲桶中創建一個對象來觸發Lambda函數,僅用於測試。通常這會由您手動上傳的對象觸發,所以在您自己的實現中不需要它。 – wjordan

0

是的,這是可能的通過Cloudformation,你需要配置的是:

1)AWS::S3::Bucket資源和,

2)NotificationConfiguration配置(在這種情況下使用LambdaConfigurations)爲上面的s3資源。

相關文檔,您需要:

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html#cfn-s3-bucket-notification

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-notificationconfig.html