Amazon web services 为现有s3存储桶添加触发器
我的目标是将每次图像上传到bucket时调用的lambda代码打包到CloudFormation模板中。到目前为止,我实现了创建新资源和从头开始触发,但我有一个现有的bucket,我需要在其中添加触发器,并在两种情况下获得错误:Amazon web services 为现有s3存储桶添加触发器,amazon-web-services,amazon-s3,aws-lambda,amazon-cloudformation,Amazon Web Services,Amazon S3,Aws Lambda,Amazon Cloudformation,我的目标是将每次图像上传到bucket时调用的lambda代码打包到CloudFormation模板中。到目前为止,我实现了创建新资源和从头开始触发,但我有一个现有的bucket,我需要在其中添加触发器,并在两种情况下获得错误: 当我将lambda和触发器配置的创建放在一个模板中,并尝试将堆栈创建为新资源时,它表示bucket已经存在 当我将触发器移动到新文件时-首先创建新资源,如1中所示,然后将现有资源导入堆栈-我得到: 创建此更改集时出错 您在模板中修改了未导入的资源[ScaleImages
- lambda创建-新lambda和角色-使用新资源创建堆栈
- 正在添加触发器-存储桶存在-导入资源
“函数”:“ScaleImages”
,但在这两个示例中,我都遇到了相同的错误:
在模板中修改了资源[ScaleImages,ScaleImagesRole]
有人能解释一下我做错了什么吗?你必须分阶段做: 1.创建新堆栈 还没有bucket,只需使用您缺少的函数和lambda权限堆叠即可
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"ScaleImages": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "ScaleImages",
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"ScaleImagesRole",
"Arn"
]
},
"Code": {
"S3Bucket": "example-test",
"S3Key": "example-resize.zip"
},
"Runtime": "nodejs12.x",
"MemorySize": 1024,
"Timeout": 300
}
},
"ScaleImagesRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "ScaleImagesRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "AWSLambdaBasicExecutionRole",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:s3:::example-test",
"arn:aws:s3:::example-test/*",
"arn:aws:s3:::example-test-output",
"arn:aws:s3:::example-test-output/*"
]
}
]
}
},
{
"PolicyName": "AmazonS3FullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
}
]
}
},
"s3Permission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": {
"Fn::GetAtt": [
"ScaleImages",
"Arn"
]
},
"Action": "lambda:InvokeFunction",
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
}
}
}
}
}
2.将bucket导入现有堆栈
使用将资源导入堆栈
选项并使用此模板上载堆栈。它添加了bucket,但是还没有通知
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"ScaleImages": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "ScaleImages",
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"ScaleImagesRole",
"Arn"
]
},
"Code": {
"S3Bucket": "example-test",
"S3Key": "example-resize.zip"
},
"Runtime": "nodejs12.x",
"MemorySize": 1024,
"Timeout": 300
}
},
"ScaleImagesRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "ScaleImagesRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "AWSLambdaBasicExecutionRole",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:s3:::example-test",
"arn:aws:s3:::example-test/*",
"arn:aws:s3:::example-test-output",
"arn:aws:s3:::example-test-output/*"
]
}
]
}
},
{
"PolicyName": "AmazonS3FullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
}
]
}
},
"s3Permission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": {
"Fn::GetAtt": [
"ScaleImages",
"Arn"
]
},
"Action": "lambda:InvokeFunction",
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
}
}
}
,
"PutOriginalImage": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain",
"Properties": {
"BucketName": "example-test"
}
}
}
}
3.更新堆栈
通过向bucket添加通知来更新堆栈。使用以下模板:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"ScaleImages": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "ScaleImages",
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"ScaleImagesRole",
"Arn"
]
},
"Code": {
"S3Bucket": "example-test",
"S3Key": "example-resize.zip"
},
"Runtime": "nodejs12.x",
"MemorySize": 1024,
"Timeout": 300
}
},
"ScaleImagesRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "ScaleImagesRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "AWSLambdaBasicExecutionRole",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:s3:::example-test",
"arn:aws:s3:::example-test/*",
"arn:aws:s3:::example-test-output",
"arn:aws:s3:::example-test-output/*"
]
}
]
}
},
{
"PolicyName": "AmazonS3FullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
}
]
}
}
,
"s3Permission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": {
"Fn::GetAtt": [
"ScaleImages",
"Arn"
]
},
"Action": "lambda:InvokeFunction",
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
}
}
},
"PutOriginalImage": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain",
"Properties": {
"BucketName": "example-test",
"NotificationConfiguration": {
"LambdaConfigurations": [
{
"Event": "s3:ObjectCreated:Put",
"Filter": {
"S3Key": {
"Rules": [
{
"Name": "prefix",
"Value": "original2/"
}
]
}
},
"Function": {
"Fn::GetAtt": [
"ScaleImages",
"Arn"
]
}
}
]
}
}
}
}
}
这是一种稍有不同的方法,可以让您一次完成任务,而无需遵循3个步骤。在Cloudformation中导入现有资源时,我经历了一些困难时期,我将通过自定义资源处理lambda中的复杂性
s3 = boto3.resource('s3')
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
responseData={}
try:
if event['RequestType'] == 'Delete':
print("Request Type:",event['RequestType'])
Bucket=event['ResourceProperties']['Bucket']
delete_notification(Bucket)
print("Sending response to custom resource after Delete")
elif event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
print("Request Type:",event['RequestType'])
LambdaArn=event['ResourceProperties']['LambdaArn']
Bucket=event['ResourceProperties']['Bucket']
add_notification(LambdaArn, Bucket)
responseData={'Bucket':Bucket}
print("Sending response to custom resource")
responseStatus = 'SUCCESS'
except Exception as e:
print('Failed to process:', e)
responseStatus = 'FAILURE'
responseData = {'Failure': 'Something bad happened.'}
cfnresponse.send(event, context, responseStatus, responseData)
def add_notification(LambdaArn, Bucket):
bucket_notification = s3.BucketNotification(Bucket)
response = bucket_notification.put(
NotificationConfiguration={
'LambdaFunctionConfigurations': [
{
'LambdaFunctionArn': LambdaArn,
'Events': [
's3:ObjectCreated:*'
]
}
]
}
)
print("Put request completed....")
def delete_notification(Bucket):
bucket_notification = s3.BucketNotification(Bucket)
response = bucket_notification.put(
NotificationConfiguration={}
)
print("Delete request completed....")
可以找到完整的模板和解决方案
注:关于AWS CloudFormation还有一个未解决的问题。原来来自谢谢!这是一个解释得很好的解决方案,现在它的工作原理和GarionS一样。没问题。很高兴它起作用了。我忘记写的一个想法是,步骤2中的bucket定义应该尽可能地匹配现有的bucket。例如,如果启用了版本控制,则定义应反映这一点。
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"ScaleImages": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": "ScaleImages",
"Handler": "index.handler",
"Role": {
"Fn::GetAtt": [
"ScaleImagesRole",
"Arn"
]
},
"Code": {
"S3Bucket": "example-test",
"S3Key": "example-resize.zip"
},
"Runtime": "nodejs12.x",
"MemorySize": 1024,
"Timeout": 300
}
},
"ScaleImagesRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": "ScaleImagesRole",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}
]
},
"Path": "/",
"Policies": [
{
"PolicyName": "AWSLambdaBasicExecutionRole",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:s3:::example-test",
"arn:aws:s3:::example-test/*",
"arn:aws:s3:::example-test-output",
"arn:aws:s3:::example-test-output/*"
]
}
]
}
},
{
"PolicyName": "AmazonS3FullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": "*"
}
]
}
}
]
}
}
,
"s3Permission": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"FunctionName": {
"Fn::GetAtt": [
"ScaleImages",
"Arn"
]
},
"Action": "lambda:InvokeFunction",
"Principal": "s3.amazonaws.com",
"SourceAccount": {
"Ref": "AWS::AccountId"
}
}
},
"PutOriginalImage": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain",
"Properties": {
"BucketName": "example-test",
"NotificationConfiguration": {
"LambdaConfigurations": [
{
"Event": "s3:ObjectCreated:Put",
"Filter": {
"S3Key": {
"Rules": [
{
"Name": "prefix",
"Value": "original2/"
}
]
}
},
"Function": {
"Fn::GetAtt": [
"ScaleImages",
"Arn"
]
}
}
]
}
}
}
}
}
s3 = boto3.resource('s3')
def lambda_handler(event, context):
print("Received event: " + json.dumps(event, indent=2))
responseData={}
try:
if event['RequestType'] == 'Delete':
print("Request Type:",event['RequestType'])
Bucket=event['ResourceProperties']['Bucket']
delete_notification(Bucket)
print("Sending response to custom resource after Delete")
elif event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
print("Request Type:",event['RequestType'])
LambdaArn=event['ResourceProperties']['LambdaArn']
Bucket=event['ResourceProperties']['Bucket']
add_notification(LambdaArn, Bucket)
responseData={'Bucket':Bucket}
print("Sending response to custom resource")
responseStatus = 'SUCCESS'
except Exception as e:
print('Failed to process:', e)
responseStatus = 'FAILURE'
responseData = {'Failure': 'Something bad happened.'}
cfnresponse.send(event, context, responseStatus, responseData)
def add_notification(LambdaArn, Bucket):
bucket_notification = s3.BucketNotification(Bucket)
response = bucket_notification.put(
NotificationConfiguration={
'LambdaFunctionConfigurations': [
{
'LambdaFunctionArn': LambdaArn,
'Events': [
's3:ObjectCreated:*'
]
}
]
}
)
print("Put request completed....")
def delete_notification(Bucket):
bucket_notification = s3.BucketNotification(Bucket)
response = bucket_notification.put(
NotificationConfiguration={}
)
print("Delete request completed....")