Serverless-application-model: Change in Ref'd Parameter Values do not trigger Function Alias update via AutoPublishAlias

Created on 1 Jul 2020  Â·  5Comments  Â·  Source: aws/serverless-application-model

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:

  1. Deploy a stack with the following template
# 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)
}
  1. Deploy for a 2nd time with added parameter overrides --parameter-overrides MyParam=MyNewValue

Observed result:

  • $LATEST unqualified version has environment variable MyEnv=MyNewValue
  • live Alias'd version not updated and has environment variable MyEnv=MyDefaultValue

Expected result:

  • $LATEST unqualified version has environment variable MyEnv=MyNewValue
  • live Alias'd version updated and has environment variable MyEnv=MyNewValue
areserverless-function typbug

Most helpful comment

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.

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.

All 5 comments

This 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 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.

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

Was this page helpful?
0 / 5 - 0 ratings