I'm trying to create a new version of a Lambda function using CloudFormation.
I want to have multiple versions of the same Lambda function so that I can (a) point aliases at different versions - like DEV and PROD - and (b) be able to roll back to an earlier version
This is the definition of my Lambda version:
LambdaVersion:
Type: AWS::Lambda::Version
Properties:
FunctionName:
Ref: LambdaFunction
A version gets created when running "aws cloudformation create-stack" but the subsequent "aws cloudformation update-stack" commands don't do anything. There are no new Lambda versions created.
I'm trying to get a new version of the Lambda function created after I upload new zip file to S3 and then run "update-stack". Can I do it with CloudFormation? Is AWS::Lambda::Version really broken (as mentioned here https://github.com/hashicorp/terraform/issues/6067#issuecomment-211708071) or am I just not getting something?
Update 1/11/17 Official reply from Amazon support: "...for any new version to be published you need to define an addition (sic) AWS::Lambda::Version resource..."
AWS CloudFormation/Lambda team, if you're reading this - this is unacceptable. Fix it.
AWS::Lambda::Version
is not useful. You have to add a new resource for every Lambda version. If you want to publish a new version for every Cloudformation update, you have to hack the system.
I solved this issue creating a Lambda backed custom resource which is triggered for every deployment. Inside this Lambda, I am creating a new version for the Lambda function given in parameter.
For the Lambda's source you can check http://serverless-arch-eu-west-1.s3.amazonaws.com/serverless.zip
Here is the example Cloudformation using this Deployment Lambda function (You might need some modification):
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"DeploymentTime": {
"Type": "String",
"Description": "It is a timestamp value which shows the deployment time. Used to rotate sources."
}
},
"Resources": {
"LambdaFunctionToBeVersioned": {
"Type": "AWS::Lambda::Function",
## HERE DEFINE YOUR LAMBDA AS USUAL ##
},
"DeploymentLambdaRole": {
"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/AWSLambdaVPCAccessExecutionRole"
],
"Policies": [
{
"PolicyName": "LambdaExecutionPolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:PublishVersion"
],
"Resource": [
"*"
]
}
]
}
}
]
}
},
"DeploymentLambda": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Role": {
"Fn::GetAtt": [
"DeploymentLambdaRole",
"Arn"
]
},
"Handler": "serverless.handler",
"Runtime": "nodejs4.3",
"Code": {
"S3Bucket": {
"Fn::Sub": "serverless-arch-${AWS::Region}"
},
"S3Key": "serverless.zip"
}
}
},
"LambdaVersion": {
"Type": "Custom::LambdaVersion",
"Properties": {
"ServiceToken": {
"Fn::GetAtt": [
"DeploymentLambda",
"Arn"
]
},
"FunctionName": {
"Ref": "LambdaFunctionToBeVersioned"
},
"DeploymentTime": {
"Ref": "DeploymentTime"
}
}
}
}
}
(Disclaimer: This code is a part of my book, for more information about Lambda & API Gateway you can check: https://www.amazon.com/Building-Serverless-Architectures-Cagatay-Gurturk/dp/1787129195)