Serverless-application-model: "AWS::NoValue" not work in Tags

Created on 8 Mar 2018  路  7Comments  路  Source: aws/serverless-application-model

I want to create Tag value in conditional.
But I use AWS::NoValue , then Cloud formation reports errors.

Conditions:
  IsPrewarmAuth: !Equals [ !Ref "AuthFunctionPrewarm", "true" ]

Resources:
  Auth:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: "lib/Auth"
      Handler: index.handler
      MemorySize: 512
      Runtime: nodejs6.10
      Timeout: 300
      Role: !GetAtt AuthFunctionRole.Arn
      Tags:
        prewarm:
          !If
            - IsPrewarmAuth
            - "true"
            - !Ref "AWS::NoValue"

CloudFormation stack events:

            "LogicalResourceId": "Auth",
            "ResourceType": "AWS::Lambda::Function",
            "ResourceStatus": "UPDATE_FAILED",
            "ResourceStatusReason": "An error occurred and the request cannot be processed.",
            "ResourceProperties": "{\"Role\":\"arn:aws:iam::999999999999:role/foo-server-Hoge-AuthFunctionRole-1DI3T9XLIM9EC\",\"FunctionName\":\"Auth-foo-Hoge\",\"MemorySize\":\"512\",\"Runtime\":\"nodejs6.10\",\"Timeout\":\"300\",\"Environment\":{\"Variables\":{\"NecReplyServiceURL\":\"https://0.0.0.0/reply\",\"NictRecognitionServiceURL\":\"https://0.0.0.0/nict\",\"SessionsTableName\":\"Sessions-foo-Hoge\"}},\"Handler\":\"index.handler\",\"Code\":{\"S3Bucket\":\"foo-server-pipeline-buildartifactsbucket-1orqu61oyfo3c\",\"S3Key\":\"df914a59c753816adbb13cc7d30195e2\"},\"Tags\":[{\"Value\":\"SAM\",\"Key\":\"lambda:createdBy\"},{\"Key\":\"prewarm\"}]}"
        },

I found probrem in ResourceProperties.

,\"Tags\":[{\"Value\":\"SAM\",\"Key\":\"lambda:createdBy\"},{\"Key\":\"prewarm\"}]

Last Tag has no value.

arecloudformation aretroubleshooting typquestion

All 7 comments

@monamu This is an issue with your template not SAM. SAM takes this dictionary you provide,

Tags:
  prewarm: 
    Ref: AWS::NoValue

and produces the tag dictionary:

Tags:
  - Key: prewarm
    Value:
      Ref: AWS::NoValue

This will tell CloudFormation to omit the Value Key, which makes the template invalid and causes the error you are seeing.

I ran a quick test to verify this as well and seems to be accurate (below is vanilla CloudFormation to show the Ref: AWS::NoValue is invalid). Is this not what you are seeing as well?

Template I ran:

AWSTemplateFormatVersion: 2010-09-09
Resources:
  LambdaTagsRole:
    Type: 'AWS::IAM::Role'
    Properties:
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
  LambdaTags:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        S3Bucket: <valid bucket>
        S3Key: LambdaTesting.zip
      Tags:
        - Value: SAM
          Key: 'lambda:createdBy'
        - Value: 
            Ref: 'AWS::NoValue'
          Key: prewarm
      MemorySize: 512
      Handler: lambda_handler.handler
      Role: !GetAtt 
        - LambdaTagsRole
        - Arn
      Timeout: 300
      Runtime: python3.6

@jfuss
Thanks.

Vanilla CloudFormation template (you presented) works fine.
and created Lambda function doesn't have 'prewarm' tag.(it's correct)

@monamu Could have sworn that didn't work early today. I must have done something else incorrect when trying to update a stack. I have a hunch what this could be. Let me try an reproduce what is going on again and go from there.

@monamu Maybe I am not crazy. I just updated the stack from early but now with this template:

AWSTemplateFormatVersion: 2010-09-09
Transform: 'AWS::Serverless-2016-10-31'
Resources:
  Auth:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: <valid s3 uri>
      Handler: index.handler
      MemorySize: 512
      Runtime: nodejs6.10
      Timeout: 300
      Tags:
        prewarm: 
          Ref: "AWS::NoValue"

And the stack deployed as expected. I wonder if there was a bad deployment on CloudFormation maybe? Can you rerun your template and see if you get the same results.

Note:
I tried updating with !Ref 'AWS::NoValue and got Error creating change set: No updates are to be performed.. Which is expected since it was an update on top of the first template I tried.

I found a pattern.

  1. create a new stack following command( There is no AWS::NoValue ):
aws cloudformation deploy --stack-name sam1 --template-file sam1-1.yaml
# sam1-1.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
  ServerlessFunctionTags:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: <code uri>
      Handler: index.handler
      Runtime: nodejs6.10
      Role: < role arn>
      Tags:
        prewarm: true

It works fine.

  1. Update with AWS::NoValue in Tags
aws cloudformation deploy --stack-name sam1 --template-file sam1-2.yaml
# sam1-2.yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
  ServerlessFunctionTags:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: <code uri>
      Handler: index.handler
      Runtime: nodejs6.10
      Role: < role arn>
      Tags:
        prewarm:
          Ref: "AWS::NoValue"

An error occured.

  1. But If template has AWS::NoValue when create. It works fine.

@monamu I was able to reproduce this but using vanilla CloudFormation (and the same steps you used to test on SAM above). So it doesn't seem like a bug directly in SAM itself. I reached out to the CloudFormation team and informed them of the bug/inconsistence you are seeing.

I will comment back once I have some information to share.

In the meantime, the only way I know around this would be to add a fake value (empty string?) instead of the AWS::NoValue. This will allow it to always work.

Here are the templates I used to test this in CloudFormation for reference:

NoValue tags

AWSTemplateFormatVersion: 2010-09-09
Resources:
  LambdaTagsRole:
    Type: 'AWS::IAM::Role'
    Properties:
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
  LambdaTags:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        S3Bucket: <valid s3 bucket>
        S3Key: LambdaTesting.zip
      Tags:
        - Value: SAM
          Key: 'lambda:createdBy'
        - Value: 
            Ref: 'AWS::NoValue'
          Key: prewarm
      MemorySize: 512
      Handler: lambda_handler.handler
      Role: !GetAtt 
        - LambdaTagsRole
        - Arn
      Timeout: 300
      Runtime: python3.6

Value with Value

AWSTemplateFormatVersion: 2010-09-09
Resources:
  LambdaTagsRole:
    Type: 'AWS::IAM::Role'
    Properties:
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - 'sts:AssumeRole'
            Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
  LambdaTags:
    Type: 'AWS::Lambda::Function'
    Properties:
      Code:
        S3Bucket: <valid s3 bucket>
        S3Key: LambdaTesting.zip
      Tags:
        - Value: SAM
          Key: 'lambda:createdBy'
        - Value: 'some value'
          Key: prewarm
      MemorySize: 512
      Handler: lambda_handler.handler
      Role: !GetAtt 
        - LambdaTagsRole
        - Arn
      Timeout: 300
      Runtime: python3.6

@jfuss
Thank you.
I use workaround you suggested.

Was this page helpful?
0 / 5 - 0 ratings