Question:
My goal is to pack my lambda code which is invoked on each image upload to bucket, into CloudFormation template. I achieved so far to create new resources, and trigger from scratch, but I have existing bucket to which I need to add trigger and get errors in 2 cases:
- when I put creation of lambda and trigger configuration in one template and try to create stack as new resources – it says that bucket already exists
- when I move trigger to new file – and first create new resources like in 1., then I import existing resources into the stack – I get:
There was an error creating this change set
You have modified resources [ScaleImages, ScaleImagesRole] in your template that are not being imported. Update, create or delete operations cannot be executed during import operations.
My templates looks like:
- lambda creation – new lambda and role – create stack with new resources
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
{ "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/*" ] } ] } } ] } } } } |
- adding trigger – bucket exists – Import resources
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
{ "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" ] } } ] } } } } } |
In last one I tried also "Function": "ScaleImages"
, but in both cases I had same error about:
modified resources [ScaleImages, ScaleImagesRole] in your template
Can somebody shed some light on what I’m doing wrong?
Answer:
You have to do it in stages:
1. Create new stack
No bucket yet, just stack with your function and lambda permissions which you are missing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
{ "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. Import bucket to existing stack
Use Import resources into stack
option and upload stack using this template. It adds bucket, but no notifications yet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
{ "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. Update stack
Update stack by adding notifications to the bucket. Use the following template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
{ "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" ] } } ] } } } } } |