Wednesday, 2 September 2020

Building a CI/CD pipeline for a SAM application written in Go

This tutorial shows how to build a CI/CD Pipeline for a SAM Application written in Go with CodeCommit, CodeBuild, CodePipeline, CloudFormation and the AWS CDK.

Prerequisites

You need to have an AWS account and installed and configured AWS CLI and Go.

Initialize The Hello World SAM project

  • Run sam init
  • Type 1 to select AWS Quick Start Templates
  • Choose go1.x for runtime
  • Leave default sam-app for project name
  • Type 1 to select the Hello World Example
  • Verify if sam-app have been created

When deploying this project, it will create an API Gateway, a Lambda function and a IAM Role. They are defined in template.yaml.

HelloWorldAPI:
    Description: "API Gateway endpoint URL for Prod environment for First Function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
    Description: "First Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

The Lambda function simply prints out Hello World.

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
    return events.APIGatewayProxyResponse{
        Body:       "Hello World!",
        StatusCode: 200,
    }, nil
}

Run SAM Application Locally

SAM allows your to run your serverless application locally for your development and testing by running the following command. The default local port number is 3000. If you are running your app on Cloud9 workspace, you need to override it with --port as Cloud 9 only support 8080, 8081 or 8082 in the local browser.

sam local start-api --port 8080

You should see

Mounting HelloWorldFunction at http://127.0.0.1:8080/hello [GET]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template
* Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)

Let's verify it

curl http://127.0.0.1:8080/hello 

You should see

Hello World

Deploy to AWS

Run sam build to build the project.

sam build

A hidden directory has been created by SAM

image

Run sam deploy to deploy your application. SAM will createa a CloudFormation stack and you can have a guided interactive mode by specifying --guided parameter.

sam deploy --guided

Configuring SAM deploy

Looking for samconfig.toml :  Not found

Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: 
AWS Region [us-east-1]: ap-southeast-1
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: Y
HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: Y
Save arguments to samconfig.toml [Y/n]: Y

Looking for resources needed for deployment: Not found.
Creating the required resources...

Successfully created!

Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-542w25h26du5
A different default S3 bucket can be set in samconfig.toml

Saved arguments to config file
Running 'sam deploy' for future deployments will use the parameters saved above.
The above parameters can be changed by modifying samconfig.toml
Learn more about samconfig.toml syntax at 
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

Uploading to sam-app/9a42d6084bb2aaa2f7eaf7b2201e115a  5094701 / 5094701.0  (100.00%)

Deploying with following values

Stack name                 : sam-app
Region                     : ap-southeast-1
Confirm changeset          : True
Deployment s3 bucket       : aws-sam-cli-managed-default-samclisourcebucket-542w25h26du5
Capabilities               : ["CAPABILITY_IAM"]
Parameter overrides        : {}

Initiating deployment

HelloWorldFunction may not have authorization defined.
Uploading to sam-app/21a49766581b625811536c904121d4ba.template  1154 / 1154.0  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                                                 LogicalResourceId                                         ResourceType                                            
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add                                                     HelloWorldFunctionCatchAllPermissionProd                  AWS::Lambda::Permission                                 
+ Add                                                     HelloWorldFunctionRole                                    AWS::IAM::Role                                          
+ Add                                                     HelloWorldFunction                                        AWS::Lambda::Function                                   
+ Add                                                     ServerlessRestApiDeployment47fc2d5f9d                     AWS::ApiGateway::Deployment                             
+ Add                                                     ServerlessRestApiProdStage                                AWS::ApiGateway::Stage                                  
+ Add                                                     ServerlessRestApi                                         AWS::ApiGateway::RestApi                                
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-southeast-1:XXXXXXXXXXX:changeSet/samcli-deploy1598436540/ea868c52-9c9a-4d27-a008-ef6157f65b9b

Previewing CloudFormation changeset before deployment

Deploy this changeset? [y/N]: y

2020-08-26 18:09:42 - Waiting for stack create/update to complete

CloudFormation events from changeset
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                              ResourceType                                LogicalResourceId                           ResourceStatusReason                      
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                          AWS::IAM::Role                              HelloWorldFunctionRole                      -                                         
CREATE_IN_PROGRESS                          AWS::IAM::Role                              HelloWorldFunctionRole                      Resource creation Initiated               
CREATE_COMPLETE                             AWS::IAM::Role                              HelloWorldFunctionRole                      -                                         
CREATE_IN_PROGRESS                          AWS::Lambda::Function                       HelloWorldFunction                          -                                         
CREATE_IN_PROGRESS                          AWS::Lambda::Function                       HelloWorldFunction                          Resource creation Initiated               
CREATE_COMPLETE                             AWS::Lambda::Function                       HelloWorldFunction                          -                                         
CREATE_IN_PROGRESS                          AWS::ApiGateway::RestApi                    ServerlessRestApi                           -                                         
CREATE_IN_PROGRESS                          AWS::ApiGateway::RestApi                    ServerlessRestApi                           Resource creation Initiated               
CREATE_COMPLETE                             AWS::ApiGateway::RestApi                    ServerlessRestApi                           -                                         
CREATE_IN_PROGRESS                          AWS::Lambda::Permission                     HelloWorldFunctionCatchAllPermissionProd    Resource creation Initiated               
CREATE_IN_PROGRESS                          AWS::ApiGateway::Deployment                 ServerlessRestApiDeployment47fc2d5f9d       -                                         
CREATE_IN_PROGRESS                          AWS::Lambda::Permission                     HelloWorldFunctionCatchAllPermissionProd    -                                         
CREATE_IN_PROGRESS                          AWS::ApiGateway::Deployment                 ServerlessRestApiDeployment47fc2d5f9d       Resource creation Initiated               
CREATE_COMPLETE                             AWS::ApiGateway::Deployment                 ServerlessRestApiDeployment47fc2d5f9d       -                                         
CREATE_IN_PROGRESS                          AWS::ApiGateway::Stage                      ServerlessRestApiProdStage                  -                                         
CREATE_IN_PROGRESS                          AWS::ApiGateway::Stage                      ServerlessRestApiProdStage                  Resource creation Initiated               
CREATE_COMPLETE                             AWS::ApiGateway::Stage                      ServerlessRestApiProdStage                  -                                         
CREATE_COMPLETE                             AWS::Lambda::Permission                     HelloWorldFunctionCatchAllPermissionProd    -                                         
CREATE_COMPLETE                             AWS::CloudFormation::Stack                  sam-app                                     -                                         
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                                                     
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                               
Description         Implicit IAM Role created for Hello World function                                                                                                      
Value               arn:aws:iam::XXXXXXXXXXX:role/sam-app-HelloWorldFunctionRole-CXSDBGUHPMFS                                                                              

Key                 HelloWorldAPI                                                                                                                                           
Description         API Gateway endpoint URL for Prod environment for First Function                                                                                        
Value               https://yh1q5tcsqg.execute-api.ap-southeast-1.amazonaws.com/Prod/hello/                                                                                 

Key                 HelloWorldFunction                                                                                                                                      
Description         First Lambda Function ARN                                                                                                                               
Value               arn:aws:lambda:ap-southeast-1:XXXXXXXXXXX:function:sam-app-HelloWorldFunction-13LO5HE0Y7BKS                                                            
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - sam-app in ap-southeast-1

image

To verifiy it, click the HelloWorldApi Value in sam-app Output.

image

Building the pipeline

With a continous delivery pipeline using AWS Code Pipeline, we can automate the build, package, and deploy commands. Other services will be used such as CodeCommit, CloudFormation and the AWS CDK.

The general flow would be like

Developer -- pushes changes --> Git Repository -- build --> deploy --> AWS

Setting up CodeCommit

Let's create a CodeCommit repository

aws codecommit create-repository --repository-name sam-app

You should see the following output

{
    "repositoryMetadata": {
        "accountId": "XXXXXXXXXXXX",
        "repositoryId": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
        "repositoryName": "sam-app",
        "lastModifiedDate": "2020-08-26T18:26:36.257000+08:00",
        "creationDate": "2020-08-26T18:26:36.257000+08:00",
        "cloneUrlHttp": "https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/sam-app",
        "cloneUrlSsh": "ssh://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/sam-app",
        "Arn": "arn:aws:codecommit:ap-southeast-1:XXXXXXXXXXXX:sam-app"
    }
}

To configurate git credentials

git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
git config --global user.name "wingkwong"
git config --global user.email "wingkwong.code@gmail.com"

Go to the root directory of your SAM project and run

cd ./sam-app
git init
git add .
git commit -m "Initial commit"

Setup Git origin

git remote add origin <replace_with_http_clone_url>

Push the code to origin

git push -u origin master

You should see

Counting objects: 17, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (13/13), done.
Writing objects: 100% (17/17), 4.86 MiB | 1.55 MiB/s, done.
Total 17 (delta 0), reused 0 (delta 0)
To https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/sam-app
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

Setting up CodePipline

We will use Amazon CDK to provision the pipeline.

Install CDK

npm install -g aws-cdk

Initialize the project

cdk init --language typescript

To bulid and deploy

npm run build
cdk deploy

You should see PipelineStack has been created

Go to AWS Console -> Developer Tools -> CodePipeline -> Pipelines

image

Clean up

cdk destroy PipelineStack 

``` Are you sure you want to delete: PipelineStack (y/n)? y PipelineStack: destroying... 11:21:26 PM | DELETE_IN_PROGRESS | AWS::CloudFormation::Stack | PipelineStack 11:22:34 PM | DELETE_IN_PROGRESS | AWS::IAM::Role | Pipeline/Dev/Creat...PipelineActionRole 11:22:34 PM | DELETE_IN_PROGRESS | AWS::IAM::Role | Pipeline/Build/Bui...PipelineActionRole 11:22:34 PM | DELETE_IN_PROGRESS | AWS::IAM::Role | Build/Role

✅ PipelineStack: destroyed ```

No comments:

Post a Comment

A Fun Problem - Math

# Problem Statement JATC's math teacher always gives the class some interesting math problems so that they don't get bored. Today t...