tipos que precios glacier ec2 capacidad aws almacenamiento amazon-web-services amazon-s3 amazon-cloudformation

amazon-web-services - que - ec2 vs s3



Habilitar la funciĆ³n Lambda a un cubo S3 usando la formaciĆ³n de nubes (5)

Estamos creando un cubo S3 utilizando una plantilla CloudFormation. Me gustaría asociar (Agregar un evento a un grupo de S3) una función Lambda cada vez que se agregue un archivo al grupo de S3.

¿Cómo es posible a través de las plantillas de CloudFormation. ¿Cuáles son las propiedades que deben usarse en CloudFormation?


Aquí hay una plantilla completa y autónoma de CloudFormation que muestra cómo activar una función Lambda cada vez que se agrega un archivo a un grupo de S3:

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


En los documentos de AWS se establece claramente que AWS :: S3 :: Bucket se utiliza para crear un recurso. Si ya tenemos un depósito, no podemos modificarlo para agregar NotificationConfiguration. Por lo tanto, el cubo S3 no debe existir para que la plantilla anterior funcione. Deje que CloudFormation cree todos los recursos, incluido el S3 bucket.


He agregado debajo de la permanente perm junto con la configuración de notificación en la nube que se usa para crear la cubeta S3 ... ¡funcionó!

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


Necesita una propiedad NotificationConfiguration en su plantilla de CloudFormation. Desafortunadamente, parece que el cubo ya existe. Para solucionar esto, puede crear una pila inicial y luego actualizarla con NotificationConfiguration. Por ejemplo:

// 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"} } ] } } } } }

Puede utilizar la herramienta aws CLI para crear la pila de esta manera:

$ 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>


Sí, es posible a través de Cloudformation, y lo que necesita configurar son:

1) AWS::S3::Bucket recurso AWS::S3::Bucket y,

2) Configuración de NotificationConfiguration (use LambdaConfigurations en este caso) para el recurso s3 anterior.

Documentación relacionada que necesita:

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