दुर्भाग्य से, सरकारी AWS::CloudFormation
टेम्पलेट केवल आप माता-पिता AWS::S3::Bucket
संसाधन, जिसका अर्थ है कि आप किसी भी मौजूदा बाल्टी को यह विन्यास अनुलग्न नहीं कर सकते की एक NotificationConfiguration
property रूप Amazon S3 NotificationConfiguration
नियंत्रित करने देता है, तो आप एक के लिए इसे लागू करने के लिए है काम करने के लिए क्लाउडफॉर्मेशन-प्रबंधित बाल्टी।
जावास्क्रिप्ट एपीआई कॉल का उपयोग कर Lambda-backed Custom Resource के रूप में सीधे Lambda-backed Custom Resource के रूप में कॉल करने के लिए एक वर्कअराउंड है। हालांकि, क्योंकि एस 3 बाल्टी पर अधिसूचना कॉन्फ़िगरेशन को संशोधित करना बाल्टी के निर्माता तक ही सीमित है, आपको AWS::S3::BucketPolicy
संसाधन को s3:PutBucketNotification
क्रिया में अपना लैम्ब्डा फ़ंक्शन पहुंच प्रदान करने की आवश्यकता भी है।
यहाँ यह दर्शाता है कि कैसे एक लैम्ब्डा समारोह जब भी एक फ़ाइल एक मौजूदा S3 बाल्टी में जोड़ा जाता है को गति प्रदान करने बाल्टी अधिसूचना विन्यास स्थापित करने के लिए का उपयोग कर 2 लैम्डा-बैक्ड कस्टम संसाधन (BucketConfiguration
, एक पूर्ण, संयमी CloudFormation टेम्पलेट है, S3Object
बाल्टी पर ऑब्जेक्ट अपलोड करने के लिए) और बाल्टी पर ऑब्जेक्ट अपलोड होने पर प्रतीक्षा स्थिति को ट्रिगर करने के लिए एक तीसरा लैम्ब्डा फ़ंक्शन (BucketWatcher
)।
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 (must already exist)
Type: String
Resources:
BucketConfiguration:
Type: Custom::S3BucketConfiguration
DependsOn:
- BucketPermission
- NotificationBucketPolicy
Properties:
ServiceToken: !GetAtt S3BucketConfiguration.Arn
Bucket: !Ref BucketName
NotificationConfiguration:
LambdaFunctionConfigurations:
- Events: ['s3:ObjectCreated:*']
LambdaFunctionArn: !GetAtt BucketWatcher.Arn
S3BucketConfiguration:
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) {
var respond = (e) => response.send(event, context, e ? response.FAILED : response.SUCCESS, e ? e : {});
process.on('uncaughtException', e=>failed(e));
var params = event.ResourceProperties;
delete params.ServiceToken;
if (event.RequestType === 'Delete') {
params.NotificationConfiguration = {};
s3.putBucketNotificationConfiguration(params).promise()
.then((data)=>respond())
.catch((e)=>respond());
} else {
s3.putBucketNotificationConfiguration(params).promise()
.then((data)=>respond())
.catch((e)=>respond(e));
}
};
Timeout: 30
Runtime: nodejs4.3
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
DependsOn: BucketConfiguration
Properties:
ServiceToken: !GetAtt S3ObjectFunction.Arn
Bucket: !Ref BucketName
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) {
var respond = (e) => response.send(event, context, e ? response.FAILED : response.SUCCESS, e ? e : {});
var params = event.ResourceProperties;
delete params.ServiceToken;
if (event.RequestType == 'Create' || event.RequestType == 'Update') {
s3.putObject(params).promise()
.then((data)=>respond())
.catch((e)=>respond(e));
} else if (event.RequestType == 'Delete') {
delete params.Body;
s3.deleteObject(params).promise()
.then((data)=>respond())
.catch((e)=>respond(e));
} else {
respond({Error: 'Invalid request type'});
}
};
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}"
NotificationBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref BucketName
PolicyDocument:
Statement:
- Effect: "Allow"
Action:
- 's3:PutBucketNotification'
Resource: !Sub "arn:aws:s3:::${BucketName}"
Principal:
AWS: !GetAtt LambdaExecutionRole.Arn
Outputs:
Result:
Value: !GetAtt Wait.Data
मैं काफी हद तक निश्चित है कि जब बाल्टी का अस्तित्व है, यह टेम्पलेट के सृजन से पहले अस्तित्व में नहीं है हूँ। अधिसूचना कॉन्फ़िगरेशन के साथ बाल्टी बनाना और उसी टेम्पलेट में लैम्ब्डा फ़ंक्शन आपके उपयोग के मामले में फिट होगा? यदि ऐसा है, तो मौजूदा पद्धति को संशोधित करने से आपकी सहायता करने के लिए यह विधि बहुत आसान होगी। किसी भी तरह से कोई समाधान है, लेकिन एक बहुत सुंदर है –
जब आप कहते हैं कि 'एस 3 बाल्टी पहले से मौजूद है', तो क्या आप यह भी कह रहे हैं कि बाल्टी क्लाउडफॉर्मेशन के बाहर बनाई गई थी? – Aditya