Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Hands-On Serverless Applications with Go

You're reading from   Hands-On Serverless Applications with Go Build real-world, production-ready applications with AWS Lambda

Arrow left icon
Product type Paperback
Published in Aug 2018
Publisher Packt
ISBN-13 9781789134612
Length 416 pages
Edition 1st Edition
Languages
Tools
Concepts
Arrow right icon
Author (1):
Arrow left icon
Mohamed Labouardy Mohamed Labouardy
Author Profile Icon Mohamed Labouardy
Mohamed Labouardy
Arrow right icon
View More author details
Toc

Table of Contents (22) Chapters Close

Title Page
Copyright and Credits
Packt Upsell
Contributors
Preface
1. Go Serverless FREE CHAPTER 2. Getting Started with AWS Lambda 3. Developing a Serverless Function with Lambda 4. Setting up API Endpoints with API Gateway 5. Managing Data Persistence with DynamoDB 6. Deploying Your Serverless Application 7. Implementing a CI/CD Pipeline 8. Scaling Up Your Application 9. Building the Frontend with S3 10. Testing Your Serverless Application 11. Monitoring and Troubleshooting 12. Securing Your Serverless Application 13. Designing Cost-Effective Applications 14. Infrastructure as Code 1. Assessments 2. Other Books You May Enjoy Index

Chapter 7: Implementing a CI/CD Pipeline


  1. Implement a CI/CD pipeline for other Lambda functions with CodeBuild and CodePipeline.

Answer: The CI/CD pipeline for FindAllMovies Lambda function can be implemented as follows:

version: 0.2
env:
  variables:
    S3_BUCKET: "movies-api-deployment-packages"
    PACKAGE: "github.com/mlabouardy/lambda-codepipeline"

phases:
  install:
    commands:
      - mkdir -p "/go/src/$(dirname ${PACKAGE})"
      - ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"
      - go get -u github.com/golang/lint/golint

  pre_build:
    commands:
      - cd "/go/src/${PACKAGE}"
      - go get -t ./...
      - golint -set_exit_status
      - go vet .
      - go test .

  build:
    commands:
      - GOOS=linux go build -o main
      - zip $CODEBUILD_RESOLVED_SOURCE_VERSION.zip main
      - aws s3 cp $CODEBUILD_RESOLVED_SOURCE_VERSION.zip s3://$S3_BUCKET/

  post_build:
    commands:
      - aws lambda update-function-code --function-name FindAllMovies --s3-bucket $S3_BUCKET --s3-key $CODEBUILD_RESOLVED_SOURCE_VERSION.zip

The CI/CD pipeline for InsertMovie Lambda function can be implemented as follows:

version: 0.2
env:
  variables:
    S3_BUCKET: "movies-api-deployment-packages"
    PACKAGE: "github.com/mlabouardy/lambda-codepipeline"

phases:
  install:
    commands:
      - mkdir -p "/go/src/$(dirname ${PACKAGE})"
      - ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"
      - go get -u github.com/golang/lint/golint

  pre_build:
    commands:
      - cd "/go/src/${PACKAGE}"
      - go get -t ./...
      - golint -set_exit_status
      - go vet .
      - go test .

  build:
    commands:
      - GOOS=linux go build -o main
      - zip $CODEBUILD_RESOLVED_SOURCE_VERSION.zip main
      - aws s3 cp $CODEBUILD_RESOLVED_SOURCE_VERSION.zip s3://$S3_BUCKET/

  post_build:
    commands:
      - aws lambda update-function-code --function-name InsertMovie --s3-bucket $S3_BUCKET --s3-key $CODEBUILD_RESOLVED_SOURCE_VERSION.zip

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The CI/CD pipeline for Updatemovie Lambda function can be implemented as follows:

version: 0.2
env:
  variables:
    S3_BUCKET: "movies-api-deployment-packages"
    PACKAGE: "github.com/mlabouardy/lambda-codepipeline"

phases:
  install:
    commands:
      - mkdir -p "/go/src/$(dirname ${PACKAGE})"
      - ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"
      - go get -u github.com/golang/lint/golint

  pre_build:
    commands:
      - cd "/go/src/${PACKAGE}"
      - go get -t ./...
      - golint -set_exit_status
      - go vet .
      - go test .

  build:
    commands:
      - GOOS=linux go build -o main
      - zip $CODEBUILD_RESOLVED_SOURCE_VERSION.zip main
      - aws s3 cp $CODEBUILD_RESOLVED_SOURCE_VERSION.zip s3://$S3_BUCKET/

  post_build:
    commands:
      - aws lambda update-function-code --function-name UpdateMovie --s3-bucket $S3_BUCKET --s3-key $CODEBUILD_RESOLVED_SOURCE_VERSION.zip

The CI/CD pipeline for DeleteMovie Lambda function can be implemented as follows:

version: 0.2
env:
  variables:
    S3_BUCKET: "movies-api-deployment-packages"
    PACKAGE: "github.com/mlabouardy/lambda-codepipeline"

phases:
  install:
    commands:
      - mkdir -p "/go/src/$(dirname ${PACKAGE})"
      - ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"
      - go get -u github.com/golang/lint/golint

  pre_build:
    commands:
      - cd "/go/src/${PACKAGE}"
      - go get -t ./...
      - golint -set_exit_status
      - go vet .
      - go test .

  build:
    commands:
      - GOOS=linux go build -o main
      - zip $CODEBUILD_RESOLVED_SOURCE_VERSION.zip main
      - aws s3 cp $CODEBUILD_RESOLVED_SOURCE_VERSION.zip s3://$S3_BUCKET/

  post_build:
    commands:
      - aws lambda update-function-code --function-name DeleteMovie --s3-bucket $S3_BUCKET --s3-key $CODEBUILD_RESOLVED_SOURCE_VERSION.zip
  1. Implement a similar workflow using Jenkins Pipeline.

Answer: We can use Jenkins parallel stages feature to run chunks of code in parallel as follows:

def bucket = 'movies-api-deployment-packages'

node('slave-golang'){
    stage('Checkout'){
        checkout scm
        sh 'go get -u github.com/golang/lint/golint'
        sh 'go get -t ./...'
    }

    stage('Test'){
        parallel {
            stage('FindAllMovies') {
                sh 'cd findAll'
                sh 'golint -set_exit_status'
                sh 'go vet .'
                sh 'go test .'
            }
            stage('DeleteMovie') {
                sh 'cd delete'
                sh 'golint -set_exit_status'
                sh 'go vet .'
                sh 'go test .'
            }
            stage('UpdateMovie') {
                sh 'cd update'
                sh 'golint -set_exit_status'
                sh 'go vet .'
                sh 'go test .'
            }
            stage('InsertMovie') {
                sh 'cd insert'
                sh 'golint -set_exit_status'
                sh 'go vet .'
                sh 'go test .'
            }
        }
    }

    stage('Build'){
        parallel {
            stage('FindAllMovies') {
                sh 'cd findAll'
                sh 'GOOS=linux go build -o main main.go'
                sh "zip findAll-${commitID()}.zip main"
            }
            stage('DeleteMovie') {
                sh 'cd delete'
                sh 'GOOS=linux go build -o main main.go'
                sh "zip delete-${commitID()}.zip main"
            }
            stage('UpdateMovie') {
                sh 'cd update'
                sh 'GOOS=linux go build -o main main.go'
                sh "zip update-${commitID()}.zip main"
            }
            stage('InsertMovie') {
                sh 'cd insert'
                sh 'GOOS=linux go build -o main main.go'
                sh "zip insert-${commitID()}.zip main"
            }
        }
    }

    stage('Push'){
        parallel {
            stage('FindAllMovies') {
                sh 'cd findAll'
                sh "aws s3 cp findAll-${commitID()}.zip s3://${bucket}"
            }
            stage('DeleteMovie') {
                sh 'cd delete'
                sh "aws s3 cp delete-${commitID()}.zip s3://${bucket}"
            }
            stage('UpdateMovie') {
                sh 'cd update'
                sh "aws s3 cp update-${commitID()}.zip s3://${bucket}"
            }
            stage('InsertMovie') {
                sh 'cd insert'
                sh "aws s3 cp insert-${commitID()}.zip s3://${bucket}"
            }
        }
    }

    stage('Deploy'){
        parallel {
            stage('FindAllMovies') {
                sh 'cd findAll'
                sh "aws lambda update-function-code --function-name FindAllMovies \
                --s3-bucket ${bucket} \
                --s3-key findAll-${commitID()}.zip \
                --region us-east-1"
            }
            stage('DeleteMovie') {
                sh 'cd delete'
                sh "aws lambda update-function-code --function-name DeleteMovie \
                --s3-bucket ${bucket} \
                --s3-key delete-${commitID()}.zip \
                --region us-east-1"
            }
            stage('UpdateMovie') {
                sh 'cd update'
                sh "aws lambda update-function-code --function-name UpdateMovie \
                --s3-bucket ${bucket} \
                --s3-key update-${commitID()}.zip \
                --region us-east-1"
            }
            stage('InsertMovie') {
                sh 'cd insert'
                sh "aws lambda update-function-code --function-name InsertMovie \
                --s3-bucket ${bucket} \
                --s3-key insert-${commitID()}.zip \
                --region us-east-1"
            }
        }
    }
}

def commitID() {
    sh 'git rev-parse HEAD > .git/commitID'
    def commitID = readFile('.git/commitID').trim()
    sh 'rm .git/commitID'
    commitID
}
  1. Implement the same pipeline with CircleCI.

Answer: CircleCI workflow option can be used to define a collection of build jobs:

version: 2
jobs:
  build_findall:
    docker:
      - image: golang:1.8

    working_directory: /go/src/github.com/mlabouardy/lambda-circleci

    build_dir: findAll

    environment:
        S3_BUCKET: movies-api-deployment-packages

    steps:
      - checkout

      - run:
         name: Install AWS CLI & Zip
         command: |
          apt-get update
          apt-get install -y zip python-pip python-dev
          pip install awscli

      - run:
          name: Test
          command: |
           go get -u github.com/golang/lint/golint
           go get -t ./...
           golint -set_exit_status
           go vet .
           go test .

      - run:
         name: Build
         command: |
          GOOS=linux go build -o main main.go
          zip $CIRCLE_SHA1.zip main

      - run:
          name: Push
          command: aws s3 cp $CIRCLE_SHA1.zip s3://$S3_BUCKET

      - run:
          name: Deploy
          command: |
            aws lambda update-function-code --function-name FindAllMovies \
                --s3-bucket $S3_BUCKET \
                --s3-key $CIRCLE_SHA1.zip --region us-east-1

  build_insert:
    docker:
      - image: golang:1.8

    working_directory: /go/src/github.com/mlabouardy/lambda-circleci

    build_dir: insert

    environment:
        S3_BUCKET: movies-api-deployment-packages

    steps:
      - checkout

      - run:
         name: Install AWS CLI & Zip
         command: |
          apt-get update
          apt-get install -y zip python-pip python-dev
          pip install awscli

      - run:
          name: Test
          command: |
           go get -u github.com/golang/lint/golint
           go get -t ./...
           golint -set_exit_status
           go vet .
           go test .

      - run:
         name: Build
         command: |
          GOOS=linux go build -o main main.go
          zip $CIRCLE_SHA1.zip main

      - run:
          name: Push
          command: aws s3 cp $CIRCLE_SHA1.zip s3://$S3_BUCKET

      - run:
          name: Deploy
          command: |
            aws lambda update-function-code --function-name InsertMovie \
                --s3-bucket $S3_BUCKET \
                --s3-key $CIRCLE_SHA1.zip --region us-east-1

  build_update:
    ...

  build_delete:
    ...

workflows:
  version: 2
  build_api:
    jobs:
      - build_findall
      - build_insert
      - build_update
      - build_delete
  1. Add a new stage to the existing pipeline to publish a new version if the current git branch is the master.

Answer:

version: 2
jobs:
  build:
    docker:
      - image: golang:1.8

    working_directory: /go/src/github.com/mlabouardy/lambda-circleci

    environment:
        S3_BUCKET: movies-api-deployment-packages

    steps:
      - checkout

      - run:
         name: Install AWS CLI & Zip
         ...

      - run:
          name: Test
          ...

      - run:
         name: Build
         ...

      - run:
          name: Push
          ...

      - run:
          name: Deploy
          ...

      - run:
          name: Publish
          command: |
            if [ $CIRCLE_BRANCH = 'master' ]; then 
              aws lambda publish-version --function-name FindAllMovies \
                --description $GIT_COMMIT_DESC --region us-east-1
            fi
          environment:
            GIT_COMMIT_DESC: git log --format=%B -n 1 $CIRCLE_SHA1
  1. Configure the pipeline to send a notification on a Slack channel every time a new Lambda function is deployed or updated.

Answer: You can use the Slack API to post a message to a Slack channel at the end of the deployment step:

- run:
    name: Deploy
    command: |
      aws lambda update-function-code --function-name FindAllMovies \
          --s3-bucket $S3_BUCKET \
          --s3-key $CIRCLE_SHA1.zip --region us-east-1
      curl -X POST -d '{"token":"$TOKEN", "channel":"$CHANNEL", "text":"FindAllMovies has been updated"}' \
           http://slack.com/api/chat.postMessage
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime
Visually different images