Description:
The auto generation of Logical Resource Ids for AWS::Lambda::Version resources created do not take into account the Value of Parameters Ref'd within the Environment Variables block, but rather the Ref block configuration itself (e.g. {"Environment":{"Variables":{"MyEnv":"MyNewValue"}}}. The end result being that a new Version is not created and the AutoPublishAlias feature does not update the alias for the function to the new version that is created, and only the unqualified function version has its configuration updated.
The example below is shortened, but once DeploymentPreferences are introduced this can result in very unexpected behaviour whereby you think your code is updated to new configuration, but all existing usage of the alias will not be invoking the newly configured function. The only solution outside of this would be to simply no longer use Environment Variables for passing through parameterised configuration, but rather use SSM or AppConfig and write code to utilise these instead from within the Lambda implementation, or to increment or add another hardcoded value within every variable block to force an update.
Environment variables are simply not usable for passing through parameterised configuration (that's expected to be able to change) to lambdas when using AutoPublishAlias opening up the use of DeploymentPreferences
Steps to reproduce the issue:
# template.yml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Parameters:
MyParam:
Type: String
Default: MyDefaultValue
Resources:
Function:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./
Handler: index.handler
Runtime: nodejs12.x
AutoPublishAlias: live
Environment:
Variables:
MyEnv: !Ref MyParam
// index.js
export const handler = event => {
console.log('MyEnv', process.env.MyEnv)
}
--parameter-overrides MyParam=MyNewValueObserved result:
$LATEST unqualified version has environment variable MyEnv=MyNewValuelive Alias'd version not updated and has environment variable MyEnv=MyDefaultValueExpected result:
$LATEST unqualified version has environment variable MyEnv=MyNewValuelive Alias'd version updated and has environment variable MyEnv=MyNewValueThis also include's usage of CloudFormation SSM Parameter types:
e.g.
Parameters:
MyParam:
Type: AWS::SSM::Parameter::Value<String>
Default: /my/ssm/parameter/name
meaning that any deployment after a value is changed will not pick up the new value, defeating the object of using this format vs {{resolve:ssm...} syntax, and again AppConfig might be the only option and fully adopting a split between configuration deployments and code deployments wholesale for all SAM projects that may want to use this type of feature
I have run into this, or something like it, except in my experience $LATEST isn't updated either. So if I took your template, deployed it once, then I updated the template by changing MyParam to the following:
MyParam:
Type: String
Default: TotallyNewValue
I then performed a sam build and sam deploy and the environment variable was not updated in either $LATEST or live.
I have run into this, or something like it, except in my experience $LATEST isn't updated either. So if I took your template, deployed it once, then I updated the template by changing
MyParamto the following:MyParam: Type: String Default: TotallyNewValueI then performed a
sam buildandsam deployand the environment variable was not updated in either$LATESTorlive.
that is the correct behaviour – Default does not change an existing value, it only populates when either the parameter or stack is new and no parameter override was provided at that time
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html
A value of the appropriate type for the template to use if no value is specified when a stack is created.
I'm incredibly surprised this isn't being noticed by a lot more people – I'm fairly confident that this bug has gone under the radar for a lot of people and their aliases have not been updated the way they expect and are still using old versions.
Either that or a lot of people simply aren't using deployment preferences yet due to the barrier to entry being pretty confusing – for example having to have CodeDeployHook_ as the prefix for your traffic hook name or else code deploy can't call your function which is difficult to find out
I'm incredibly surprised this isn't being noticed by a lot more people – I'm fairly confident that this issue has gone under the radar for a lot of people and their aliases have not been updated the way they expect and are still using old versions.
Either that or a lot of people simply aren't using deployment preferences with SAM yet due to the barrier to entry being pretty confusing – for example having to have CodeDeployHook_ as the prefix for your traffic hook name or else code deploy can't call your function which is difficult to find out amongst other nuances
Most helpful comment
that is the correct behaviour –
Defaultdoes not change an existing value, it only populates when either the parameter or stack is new and no parameter override was provided at that timehttps://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/parameters-section-structure.html