Моя цель — упаковать мой лямбда-код, который вызывается при каждой загрузке изображения в корзину, в шаблон CloudFormation. До сих пор я добился создания новых ресурсов и запуска с нуля, но у меня есть существующая корзина, в которую мне нужно добавить триггер и получить ошибки в 2 случаях:
При создании этого набора изменений произошла ошибка.
Вы изменили ресурсы [ScaleImages, ScaleImagesRole] в своем шаблоне, которые не импортируются. Операции обновления, создания или удаления не могут выполняться во время операций импорта.
Мои шаблоны выглядят так:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"ScaleImages": {
"Type": "AWS::Lambda::Function",
"DeletionPolicy": "Retain",
"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",
"DeletionPolicy": "Retain",
"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": "*"
}
]
}
},
{
"PolicyName": "AmazonS3FullAccess",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::example-test",
"arn:aws:s3:::example-test/*",
"arn:aws:s3:::example-test-output",
"arn:aws:s3:::example-test-output/*"
]
}
]
}
}
]
}
}
}
}
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"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"
]
}
}
]
}
}
}
}
}
В последнем я также пробовал "Function": "ScaleImages", но в обоих случаях у меня была одна и та же ошибка:
измененные ресурсы [ScaleImages, ScaleImagesRole] в вашем шаблоне
Может кто-нибудь пролить свет на то, что я делаю неправильно?





Делать это нужно поэтапно:
Пока нет ведра, просто сложите с вашей функцией и лямбда-разрешениями, которых вам не хватает.
{
"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"
}
}
}
}
}
Используйте опцию Import resources into stack и загрузите стек, используя этот шаблон. Он добавляет ведро, но пока нет уведомлений
{
"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"
}
}
}
}
Обновите стек, добавив уведомления в корзину. Используйте следующий шаблон:
{
"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"
]
}
}
]
}
}
}
}
}
@ГарионС. Без проблем. Рад, что это работает. Одна мысль, которую я забыл написать, заключается в том, что определение корзины на шаге 2 должно максимально точно соответствовать существующей корзине. Например, если у вас включено управление версиями, определение должно отражать это.
Немного другой подход, который позволяет вам работать одним выстрелом, не выполняя 3 шага. У меня были трудные времена при импорте существующих ресурсов в Cloudformation, я бы справился со сложностью лямбда-выражения через пользовательский ресурс.
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 Repo на github . Изначально исходил от бессерверных людей
Спасибо! Это очень хорошо объясненное решение, и теперь оно работает как шарм.