/blueprint-serverless-golang

AWS CDK template for serverless Golang

Primary LanguageGoMIT LicenseMIT

Blueprint: Serverless Golang

Skeleton of Golang serverless application built with AWS CDK


This project crafts a fully functional blueprint of Golang serverless RESTful application for Amazon Web Services. The blueprint is a hybrid solution, composed of pure "application logic" and Infrastructure as a Code implemented on top of AWS CDK, both developed with Golang.

Inspiration

AWS CDK is amazing technology to automate the development and operation of application into one process and one codebase.

However, seeding of new repository for development of Golang serverless application requires a boilerplate code. This blueprint helps you to focus on the application development than waste a time with establish project layout, configure AWS CDK, setting up CI/CD and figuring out how to testing the application. All these issues are resolved within this blueprint.

Installation

The blueprint is fully functional application (Pet Store) that delivers a skeleton for Golang serverless development with AWS CDK. Clone the repository and follow Getting started instructions to evaluate its applicability for your purposes. It should take less than 5 minutes to build and deploy this blueprint to AWS.

go get github.com/fogfish/blueprint-serverless-golang

See Getting Started and Customize Blueprint chapters for details.

Install from GitHub

Use this template

Create a new GitHub repository from this blueprint.

Upgrade the template

Use git features to update the blueprint from upstream

git remote add blueprint https://github.com/fogfish/blueprint-serverless-golang
git fetch blueprint
git merge blueprint/main --allow-unrelated-histories --squash

Requirements

Before Getting started, you have to ensure

  • Golang development environment v1.16 or later
  • assay-it utility for testing cloud apps in production
  • AWS CDK for deployment of serverless application using infrastructure as a code
  • GitHub account for managing source code and running CI/CD pipelines as GitHub Actions
  • Account on Amazon Web Services for running the application in production

Getting started

Let's have a look on the repository structure

The structure resembles the mixture of Standard package layout and Hexagonal architecture. The proposed structure is better version of Hexagonal architecture that follows Golang best practices:

  1. the root is aws cdk application

  2. Sub-packages to isolate dependencies to external technologies so that they act as bridge between your domain and technology adaptation. internal holds sub-packages internal to applications. pkg are sharable clients

  3. cmd contains main packages that build lambda functions and ties everything together.

github.com/.../the-beautiful-app
├─ petshop.go                  // aws cdk main application  
|
├─ internal/awspetshop         // IaC, aws cdk application
|
├─ internal/core               // the root defines domain types, unit test 
|  |                           // "algebra" of your application. contains core
|  |                           // types to describe domain of your application.
|  |                           // It contains simple types that has no dependency
|  |                           // to technology but their implements core logic
|  |                           // and use-cases.
|  |
|  └─ storage.go               // defines capability requires to store core
|                              // objects at the external storage, hex-arch
|                              // use "port" concept to depict it          
|
├─ internal/storage            // sub-package for dependency/technology ...
|                              // it follows the standard package layout to 
|                              // adapt domain/implementation/dependency.
|                              // in this example storage implements in-memory
|                              // database for all domain objects.  
|
├─ internal/services           // entry point to the core, implement app logic
|  └─ pets                     // entire logic about pets domain
|     ├─ fetcher.go            // fetch and enrich pets objects 
|     └─ creator.go            // create pets objects
|
├─ internal/mock               // shared mock
|
├─ internal/http               // public REST API exposed by application.
|  ├─ petshop.go               // collection of petshop endpoints impl. by app
|  |                           // endpoints consumer services using ports    
|  | 
|  └─ suites                   // testing suites for api endpoint(s)
|
├─ cmd                         // executables of the project
|  ├─ lambda                   // aws lambda's are main packages
|  |  ├─ petshop               // each lambda stays at own executable
|  |  |  └─ main.go            // single lambda pattern is not recommended
|  | ...
|  └─ server                   // run application as standalone server 
|     └─ main.go
|
├─ pkg/api                     // public domain objects used by application
|                              // client library
|
└─ .github                     // CI/CD with GitHub Actions
    └─ ...                   

Development workflows

unit testing

Test the Golang application and its cloud infrastructure

go test ./...

local testing

Run application locally

go run cmd/server/main.go
assay-it test --target http://127.1:8080

build

Build entire application (both Golang and its AWS infrastructure). It should compile Golang code, assemble binaries for AWS Lambda and produce AWS CloudFormation template

cdk synth

deploy

Deploy an application to AWS account, it requires a valid AWS credentials either access keys or assumed roles.

cdk deploy

In few seconds, the application becomes available at

curl https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/api

The write path of api is protected by AWS IAM, request has to be signed. Either use example client cmd/petshop-cli or curl directly

curl $BLUEPRINT/petshop/pets \
  -XGET \
  -H "Accept: application/json" \
  --aws-sigv4 "aws:amz:eu-west-1:execute-api" \
  --user "$AWS_ACCESS_KEY_ID":"$AWS_SECRET_ACCESS_KEY"

See all available endpoints.

test in production

assay-it test --target https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/api

destroy

Destroy the application and remove all its resource from AWS account

cdk destroy

Continuos Delivery

Continuos Integration and Delivery is implemented using GitHub Actions. It consists of multiple .github/workflows.

AWS_ACCESS_KEY and AWS_SECRET_ACCESS_KEY are required to enable deployment by GitHub Actions. Store these credentials to secret key vault at your fork settings (Your Fork > Settings > Secrets).

Check quality of Pull Request

The quality checks are executed every time a new change is proposed via Pull Request:

  • checks (check-code.yml) evaluates a quality of source code and reviews proposed changes (pull requests) using static code analysis.
  • tests (check-test.yml) the quality of software assets with scope on unit tests only and measures the test coverage.
  • spawns (check-spawn.yml) a sandbox(ed) deployment of the application to target AWS account for continuous integrations (optionally executed if pull request is marked with [@] deploy label);
  • cleans (check-clean.yml) sandbox environment after Pull Request is either merged or closed.

Check quality of main branch

The quality checks are executed every time a pull request is merged into pipeline:

  • tests (check-test.yml) the quality of software assets with scope on unit tests only and measures the test coverage.
  • builds (build.yml) validates quality of main branch once Pull Request is merge by deploying changes to the development environment at target AWS account;

Release of main branch

The quality checks are executed every time a new release is created:

  • carries (carry.yml) "immutable" application snapshot to production environment when GitHub release is published;

Customize Blueprint

  • rebuild go.mod and go.sum for your application
  • add RESTful api endpoints to http package
  • add Lambda functions to aws/lambda package
  • set the name of your stack at cloud/blueprint.go and enhance the infrastructure
stackID := fmt.Sprintf("blueprint-golang-%s", vsn(app))
stack := awscdk.NewStack(app, jsii.String(stackID), config)
strategy:
      matrix:
        stack: [blueprint-golang]
  • setup access to AWS account for CI/CD
  • integrate api testing
  • tune CI/CD pipeline according to purpose of your application either removing or commenting out blocks

How To Contribute

The blueprint is MIT licensed and accepts contributions via GitHub pull requests:

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Added some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

commit message

The commit message helps us to write a good release note, speed-up review process. The message should address two question what changed and why. The project follows the template defined by chapter Contributing to a Project of Git book.

bugs

If you experience any issues with the library, please let us know via GitHub issues. We appreciate detailed and accurate reports that help us to identity and replicate the issue.

License

See LICENSE