My team is using Azure Devops pipelines to deploy Cloudformation stacks to AWS. We have common Cloudformation templates that we are reusing (e.g. a single Lambda.yml Cloudformation template that is reused to deploy multiple Lambda functions).
Along with this I am setting up a step function to orchestrate logical flows. The step function steps need to reference the ARNs of the various parts of the infrastructure (for this example, focus on the lambda functions).
Since the Lambda.yml is reused, the output variables are overwritten each time a task reuses the template to deploy a new lambda. I'd like to capture the output after each task in a variable or parameter in Azure Devops. I've looked at numerous examples and the documentation on variables, and I have been unable to get it to work. The relevant parts of the Cloudformation template and the deployment script are listed here (YAML format).
Lambda.yml (Cloudformation template)
AWSTemplateFormatVersion: '2010-09-09'
Description: Template for Lambda function.
Parameters:
FunctionName:
Description: The name of the Lambda function
Type: String
Resources:
LambdaFunction:
Type: AWS::Lambda::Function
Properties:
FunctionName: !Ref FunctionName
.....
Outputs:
LambdaFunctionName:
Description: Lambda function name
Value: !Ref LambdaFunction
LambdaFunctionARN:
Description: Lambda ARN
Value:
Fn::GetAtt:
- LambdaFunction
- Arn
Deploy.yml (Azure Devops pipeline deployment)
# Deploy.yml is a series of deployment tasks called from a job/stage defined in another.yml file
# LambdaFunctionNumber1
- task: AmazonWebServices.aws-vsts-tools.CloudFormationCreateOrUpdateStack.CloudFormationCreateOrUpdateStack@1
displayName: 'Stack: LambdaFunctionNumber1'
inputs:
templateSource: s3
s3BucketName: ${{ parameters.azdoS3ArtifactBucket }}
s3ObjectKey: '${{ parameters.azdoS3ArtifactPrefix }}/cfn/Lambda.yml'
templateParametersSource: inline
templateParameters: |
-
ParameterKey: FunctionName
ParameterValue: LambdaFunctionNumber1
....
captureStackOutputs: asVariables
# I would like to capture Cloudformation output variables here for use in other tasks
# variables lambdaNumberOneFunctionName and lambdaNumberOneFunctionArn are defined as variables by the job triggering these deployment tasks, and initialized to empty strings
- bash:
echo "##vso[task.setvariable variable=lambdaNumbertOneFunctionName;isOutput=true]$LAMBDAFUNCTIONNAME"
echo "##vso[task.setvariable variable=lambdaNumberOneFunctionArn;isOutput=true]$LAMBDAFUNCTIONARN"
# LambdaFunctionNumber2
- task: AmazonWebServices.aws-vsts-tools.CloudFormationCreateOrUpdateStack.CloudFormationCreateOrUpdateStack@1
displayName: 'Stack: LambdaFunctionNumber2'
inputs:
templateSource: s3
s3BucketName: ${{ parameters.azdoS3ArtifactBucket }}
s3ObjectKey: '${{ parameters.azdoS3ArtifactPrefix }}/cfn/Lambda.yml'
templateParametersSource: inline
templateParameters: |
-
ParameterKey: FunctionName
ParameterValue: LambdaFunctionNumber2
....
captureStackOutputs: asVariables
# At this point the $(LambdaFunctionARN) output variable is set from Cloudformation of LambdaFunctionNumber2.
# The ARN from LambdaFunctionNumber1 is lost unless I capture it somehow.
# I need multiple ARNs to provide as input to the Step Function that gets deployed here
- task: AmazonWebServices.aws-vsts-tools.CloudFormationCreateOrUpdateStack.CloudFormationCreateOrUpdateStack@1
displayName: 'Stack: Step Function'
inputs:
stackName:step-function
templateSource: s3
s3BucketName: ${{ parameters.azdoS3ArtifactBucket }}
s3ObjectKey: '${{ parameters.azdoS3ArtifactPrefix }}/cfn/StepFunction.yml'
....
templateParametersSource: inline
templateParameters: |
-
ParameterKey: StateMachineName
ParameterValue: orchestration-step-function
-
# This doesn't work
ParameterKey: State1LambdaArn
ParameterValue: $[lambdaNumberOneFunctionArn]
-
# This works but only allows capturing the most recent output variable
ParameterKey: State2LambdaArn
ParameterValue: $(LambdaFunctionARN)