How do I use the CodeBuild output artifact in CloudFormation?
So, I have a pretty simple stack that I'm trying to set up, consisting of a single Lambda function subscribed to the SNS topic. I would like to use CodePipeline with three steps: Source (GitHub) -> Build (CodeBuild) -> Deploy (CloudFormation).
I was able to put together a template and buildspec file that works, except I lost track of how I should be referencing the output artifact that CodeBuild creates in the CloudFormation template; right now I only have the placeholder code inline.
Basically, what should I put in a property Code:
of a Lambda function to get the CodeBuild files (which is my output artifact in CodePipeline)?
template.yml:
AWSTemplateFormatVersion: 2010-09-09
Resources:
SNSTopic:
Type: 'AWS::SNS::Topic'
Properties:
Subscription:
- Endpoint: !GetAtt
- LambdaFunction
- Arn
Protocol: lambda
LambdaFunction:
Type: 'AWS::Lambda::Function'
Properties:
Runtime: python3.6
Handler: main.lamda_handler
Timeout: '10'
Role: !GetAtt
- LambdaExecutionRole
- Arn
Code:
ZipFile: >
def lambda_handler(event, context):
print(event)
return 'Hello, world!'
LambdaExecutionRole:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
LambdaInvokePermission:
Type: 'AWS::Lambda::Permission'
Properties:
FunctionName: !GetAtt
- LambdaFunction
- Arn
Action: 'lambda:InvokeFunction'
Principal: sns.amazonaws.com
SourceArn: !Ref SNSTopic
buildspec.yml:
version: 0.2
phases:
install:
commands:
- pip install -r requirements.txt -t libs
artifacts:
type: zip
files:
- template.yml
- main.py
- lib/*
source to share
Finally found a solution for this thanks to AWS support. First, I put this JSON in the parameter overrides during the CloudFormation deployment phase in CodePipeline:
{
"buildBucketName" : { "Fn::GetArtifactAtt" : ["MyAppBuild", "BucketName"]},
"buildObjectKey" : { "Fn::GetArtifactAtt" : ["MyAppBuild", "ObjectKey"]}
}
Then changed my CF template like this:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
buildBucketName:
Type: String
buildObjectKey:
Type: String
Resources:
...
LambdaFunction:
...
Code:
S3Bucket: !Ref buildBucketName
S3Key: !Ref buildObjectKey
This passes the output artifact byte name and the object key that CodeBuild outputs as parameters to CF, so that it can dynamically grab the output artifact location in S3 without the need for hard code, making the template more portable.
source to share