aws-cdk: [aws-codepipeline] Parameter overrides cannot use Fn::GetArtifactAtt

I have been trying to create a deployment pipeline for Lambda function using CodePipeline. During development I noticed there is weird issue which does not allow me to use Fn::GetArtifactAtt in the parameterOverrides (1), because default JSON serializer forces to use Fn::Join which does not accept Fn::GetArtifactAtt.

(1): https://github.com/awslabs/aws-cdk/blob/4af7c0d97b17820a41ef9d611ed6768f62d64a6c/packages/%40aws-cdk/aws-cloudformation/lib/pipeline-actions.ts#L189

I see it was noticed in #566, but for 0.22.0 (build 644ebf5) version it does not work for me.

import iam = require('@aws-cdk/aws-iam');
import codepipeline = require('@aws-cdk/aws-codepipeline');
import cloudformation = require('@aws-cdk/aws-cloudformation');
import codepipelineapi = require('@aws-cdk/aws-codepipeline-api');

const addDeployPrepareAction = (
    id: string,
    buildArtifact:  codepipelineapi.Artifact,
    props: {
        stage: codepipeline.Stage,
        stackName: string,
        region: string,
        changeSetName: string,
        role: iam.Role
    }
) => {
    const { stackName, stage, region, changeSetName, role } = props

    new cloudformation.PipelineCreateReplaceChangeSetAction(stage, id, {
        stackName,
        stage,
        region,
        role,
        changeSetName,
        runOrder: 1,
        adminPermissions: false,
        capabilities: cloudformation.CloudFormationCapabilities.NamedIAM,
        parameterOverrides: {
            'LambdaCodeZip': buildArtifact.objectKey,
            'LambdaCodeBucket': buildArtifact.bucketName,
        },
    })
}

Expected (one of the possible solution):

ParameterOverrides: !Sub |
  {
    "LambdaCodeZip" : { "Fn::GetArtifactAtt" : [ "BuildOutput", "ObjectKey" ] },
    "LambdaCodeBucket": { "Fn::GetArtifactAtt" : [ "BuildOutput", "BucketName" ] }
  }

Actual:

ParameterOverrides:
  Fn::Join:
    - ""
    - - '{"LambdaCodeZip":"'
      - Fn::GetArtifactAtt:
          - BuildOutput
          - ObjectKey
      - '","LambdaCodeBucket":"'
      - Fn::GetArtifactAtt:
          - BuildOutput
          - BucketName
      - '"}'

Error:

aws cloudformation validate-template --template-body file://pipeline.json

An error occurred (ValidationError) when calling the ValidateTemplate operation: Template Error: Encountered unsupported function: Fn::GetArtifactAtt Supported functions are: [Fn::Base64, Fn::GetAtt, Fn::GetAZs, Fn::ImportValue, Fn::Join, Fn::Split, Fn::FindInMap, Fn::Select, Ref, Fn::Equals, Fn::If, Fn::Not, Condition, Fn::And, Fn::Or, Fn::Contains, Fn::EachMemberEquals, Fn::EachMemberIn, Fn::ValueOf, Fn::ValueOfAll, Fn::RefAll, Fn::Sub, Fn::Cidr]

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (9 by maintainers)

Commits related to this issue

Most upvoted comments

I figured out what the issue is. I submitted a PR with the fix here.

A couple of things about that:

  1. The names you have there, LambdaSourceBucketNameParameter and LambdaSourceObjectKeyParameter, are just the defaults. You can create your own:
lambda.Code.fromCfnParameters({
  bucketNameParam: new CfnParameter(this, 'A'),
  objectKeyParam: new CfnParameter(this, 'B'),
});
  1. Are you using the default Artifact names? Because you can always name them explicitly, thus saving a lot of characters:
const sourceOutput = new codepipeline.Artifact('S');

Hope this helps!

Adam

I don’t think this issue is solved. I’m facing it just right now.

This is how my code looks like:

from aws_cdk import (
    core,
    aws_s3 as s3,
    aws_ssm as ssm,
    aws_codepipeline as codepipeline,
    aws_codepipeline_actions as actions,
)

from typing import Dict


class PipelineTest(core.Stack):
    def __init__(self, app: core.App, id: str, props: Dict, **kwargs) -> None:
        super().__init__(app, id, **kwargs)

        source_output = codepipeline.Artifact(artifact_name='source')
        build_output = codepipeline.Artifact(artifact_name='build')

        core.CfnOutput(
            self, "Outpu1t",
            value=build_output.s3_location.bucket_name
        )

        core.CfnOutput(
            self, "Output2",
            value=build_output.s3_location.object_key
        )

This is the output when I run cdk deploy '*':

failed: Error [ValidationError]: Template Error: Encountered unsupported function: Fn::GetArtifactAtt Supported functions are: [Fn::Base64, Fn::GetAtt, Fn::GetAZs, Fn::ImportValue, Fn::Join, Fn::Split, Fn::FindInMap, Fn::Select, Ref, Fn::Equals, Fn::If, Fn::Not, Condition, Fn::And, Fn::Or, Fn::Contains, Fn::EachMemberEquals, Fn::EachMemberIn, Fn::ValueOf, Fn::ValueOfAll, Fn::RefAll, Fn::Sub, Fn::Cidr]
    at Request.extractError (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/protocol/query.js:50:29)
    at Request.callListeners (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:106:20)
    at Request.emit (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
    at Request.emit (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:688:14)
    at Request.transition (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:22:10)
    at AcceptorStateMachine.runTo (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:14:12)
    at /usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:26:10
    at Request.<anonymous> (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:38:9)
    at Request.<anonymous> (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:690:12)
    at Request.callListeners (/usr/local/lib/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:116:18) {
  code: 'ValidationError',
  time: 2021-04-09T11:13:12.367Z,
  requestId: 'b26864df-a3de-4c2b-82b6-a2ac9bcf164b',
  statusCode: 400,
  retryable: false,
  retryDelay: 577.931740145933
}
Template Error: Encountered unsupported function: Fn::GetArtifactAtt Supported functions are: [Fn::Base64, Fn::GetAtt, Fn::GetAZs, Fn::ImportValue, Fn::Join, Fn::Split, Fn::FindInMap, Fn::Select, Ref, Fn::Equals, Fn::If, Fn::Not, Condition, Fn::And, Fn::Or, Fn::Contains, Fn::EachMemberEquals, Fn::EachMemberIn, Fn::ValueOf, Fn::ValueOfAll, Fn::RefAll, Fn::Sub, Fn::Cidr]

This is how the outputs from template looks like:

"Outputs": {
    "Output": {
      "Value": {
        "Fn::GetArtifactAtt": [
          "build",
          "BucketName"
        ]
      }
    },
    "Output2": {
      "Value": {
        "Fn::GetArtifactAtt": [
          "build",
          "ObjectKey"
        ]
      }
    }
  }

CDK version: 1.87.1 (build 9eeaa93) OS system: macOS Catalina 10.15.5