10

So I have a fairly simple stack I'm trying to setup consisting of a single Lambda function subscribed to an SNS topic. I'd like to use CodePipeline with three stages: Source (GitHub) -> Build (CodeBuild) -> Deploy (CloudFormation).

I managed to cobble together a template and buildspec file that that work, except I'm lost on how I'm supposed to reference the output artifact that CodeBuild makes in the CloudFormation template; right now I just have placeholder inline code.

Basically, what am I supposed to put in the Code: property of the Lambda function in order 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/*
mth
  • 436
  • 4
  • 8
  • I am missing your `AWS::CodePipeline::Pipeline` and `AWS::CodeBuild::Project` resources in your CloudFormation template. – MaiKaY Jul 04 '17 at 06:22
  • I'm not controlling them with CloudFormation; still learning CF, so trying to start out very simple. – mth Jul 04 '17 at 22:12

3 Answers3

14

Finally found a solution to this thanks to AWS support. First, I placed this JSON in the Parameter Overrides in the CloudFormation deployment step in CodePipeline:

{
  "buildBucketName" : { "Fn::GetArtifactAtt" : ["MyAppBuild", "BucketName"]},
  "buildObjectKey" : { "Fn::GetArtifactAtt" : ["MyAppBuild", "ObjectKey"]}
}

Then changed my CF template like so:

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 bucket name and object key that CodeBuild outputs as parameters to CF, so that it can dynamically grab the output artifact location in S3 without having to hardcode anything, making the template way more portable.

mth
  • 436
  • 4
  • 8
2

Your CodeBuild should be dropping your zip file to an S3 bucket. So in the Code section of your LambdaFunction resource you point to it.

Code:
   S3Bucket: the_bucket_where_CodeBuild_dropped_your_zip
   S3Key: the_name_of_the_zip_file_dropped

You don't need 'ZipFile: '

Alex Nelson
  • 976
  • 8
  • 17
  • That'd be one way to do it, but my goal was to avoid specifying any values "manually" (i.e. hardcoding a location for my Lambda deployment package). Ended up solving it a different way. – mth Jul 11 '17 at 20:15
0

I realize this question is old, but thought I'd answer it with respect to SAM

project_root/
  template.yaml
  buildspec.yaml
  my_lambda/
    my_lambda.py
    requirements.txt

template.yaml:

Transform: AWS::Serverless-2016-10-31

Resources:
  MyLambda:
    Type: AWS::Serverless::Function
    Properties:
      Handler: my_lambda.lambda_handler
      CodeUri: my_lambda/
      Runtime: python3.8

buildspec.yaml:

version: 0.2

phases:
  install:
    runtime-versions:
      python: 3.8
    commands:
      - pip install aws-sam-cli
  build:
    commands:
      - sam build
      - sam package --s3-bucket mybucket --s3-prefix sam | sam deploy -t /dev/stdin --stack-name FOOSTACK --capabilities CAPABILITY_IAM

Notes:

  1. sam build will pip install your lambda requirements.txt
  2. sam package will zip your lambda, and name it with the md5 of its contents and upload to S3 for you (only if it has changed)
  3. sam deploy will create a CloudFormation changeset and run it for you
Neil McGuigan
  • 41,314
  • 10
  • 106
  • 137