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.
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.
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.
Create a new GitHub repository from this blueprint.
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
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
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:
-
the root package 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.
-
Use sub-packages to isolate dependencies to external technologies so that they act as bridge between your domain and technology adaptation.
-
Main packages build lambda functions and ties everything together.
github.com/.../the-beautiful-app
├─ pet.go // the root defines domain types, unit test
├─ ... // "algebra" of your application
|
├─ 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
|
├─ http // public REST API exposed by application.
| ├─ petshop.go // collection of petshop endpoints impl. by app
| | // endpoints consumer services using ports
| |
| ├─ api // public objects used by API
| | └─ pet.go
| ├─ curl // client library
| | └─ petshop.go
| └─ 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
|
├─ cloud // IaC, aws cdk application
| └─ ... // orchestrate ops model
|
└─ .github // CI/CD with GitHub Actions
└─ ...
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 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"
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 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).
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.
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 ofmain
branch once Pull Request is merge by deploying changes to the development environment at target AWS account;
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;
- 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)
- update the target stack name at CI/CD workflows check-spawn.yml, build.yml, carry.yml and check-clean.yml
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
The blueprint is MIT licensed and accepts contributions via GitHub pull requests:
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
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.
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.