Skip to content

Commit

Permalink
Merge pull request #40 from fogfish/upgrade-version
Browse files Browse the repository at this point in the history
integrate api testing
  • Loading branch information
fogfish authored Mar 19, 2023
2 parents 681eeb6 + 4b0e0e0 commit 8ef1e72
Show file tree
Hide file tree
Showing 35 changed files with 1,060 additions and 193 deletions.
5 changes: 5 additions & 0 deletions .assay-it.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"suites": [
"http/suites/petshop.go"
]
}
10 changes: 8 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@ jobs:

- uses: actions/checkout@v2

- uses: fogfish/deploy-cdk-go@latest
- id: deploy
uses: fogfish/deploy-cdk-go@latest
with:
go-version: 1.18
go-version: "1.20"
stack: ${{ matrix.stack }}
version: latest
issue-to-create: ./.github/issue-spawn-latest.md
aws-access-key: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1

- uses: assay-it/github-actions-quality-check@latest
with:
install-go: false
system-under-test: ${{ steps.deploy.outputs.deployed-api }}
10 changes: 8 additions & 2 deletions .github/workflows/carry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ jobs:

- uses: actions/checkout@v2

- uses: fogfish/deploy-cdk-go@latest
- id: deploy
uses: fogfish/deploy-cdk-go@latest
with:
go-version: 1.18
go-version: "1.20"
stack: ${{ matrix.stack }}
version: ${{ github.event.release.name }}
issue-to-create: ./.github/issue-spawn-release.md
aws-access-key: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1

- uses: assay-it/github-actions-quality-check@latest
with:
install-go: false
system-under-test: ${{ steps.deploy.outputs.deployed-api }}
2 changes: 1 addition & 1 deletion .github/workflows/check-clean.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:

- uses: fogfish/deploy-cdk-go@latest
with:
go-version: 1.18
go-version: "1.20"
command: destroy
stack: ${{ matrix.stack }}
version: pr${{ github.event.number }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:

- uses: actions/setup-go@v3
with:
go-version: 1.18
go-version: "1.20"
cache: true

- uses: dominikh/staticcheck-action@v1.2.0
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/check-spawn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,22 @@ jobs:
steps:
- uses: actions/checkout@v2

- uses: fogfish/deploy-cdk-go@latest
- id: deploy
uses: fogfish/deploy-cdk-go@latest
with:
go-version: 1.18
go-version: "1.20"
stack: ${{ matrix.stack }}
version: pr${{ github.event.number }}
issue-to-comment: ${{ github.event.number }}
aws-access-key: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1

- uses: assay-it/github-actions-quality-check@latest
with:
install-go: false
system-under-test: ${{ steps.deploy.outputs.deployed-api }}

- uses: buildsville/add-remove-label@v1
if: always()
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/check-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:

- uses: actions/setup-go@v3
with:
go-version: 1.18
go-version: "1.20"
cache: true

- name: go build
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
node_modules/
.vscode/

suites/assay-it/
100 changes: 65 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ This project crafts a fully functional blueprint of Golang serverless RESTful ap

[AWS CDK](https://aws.amazon.com/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.
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 that delivers a skeleton for Golang serverless development with AWS CDK. Clone the repository and follow [Getting started](#getting-started) instructions to evaluate its applicability for your purposes. It should take less than 5 minutes to build and deploy the template in AWS.
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](#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
Expand Down Expand Up @@ -75,64 +76,86 @@ git merge blueprint/main --allow-unrelated-histories --squash
Before Getting started, you have to ensure

* [Golang](https://golang.org/dl/) development environment v1.16 or later
* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/work-with.html#work-with-prerequisites)
* Access to AWS Account
* [assay-it](https://assay.it) utility for testing cloud apps in production
* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/work-with.html#work-with-prerequisites) for deployment of serverless application using infrastructure as a code
* [GitHub](https://github.com) account for managing source code and running CI/CD pipelines as [GitHub Actions](https://docs.github.com/en/actions)
* Account on [Amazon Web Services](https://aws.amazon.com) for running the application in production


## Getting started

**Let's have a look on the repository structure**

The structure resembles the standard package layout proposed in [this blog post](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1):
The structure resembles the mixture of [Standard package layout](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1) and [Hexagonal architecture](https://medium.com/@matiasvarela/hexagonal-architecture-in-go-cfd4e436faa3). The proposed structure is better version of Hexagonal architecture that follows Golang best practices:

1. 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.

2. Use sub-packages to isolate dependencies to external technologies so that they act as bridge between your domain and technology adaptation.
2. Use sub-packages to isolate dependencies to external technologies so that they act as bridge between your domain and technology adaptation.

3. Main packages build lambda functions and ties everything together.

```
github.com/.../the-beautiful-app
├─ stub.go // domain types, unit test
├─ ... // "algebra" of your application
|
├─ http // RESTful API and HTTP protocol
| ├─ api.go // api endpoint(s), unit tests,
| └─ ... // other endpoints
|
├─ cmd // executables of the project
| └─ lambda // aws lambda's are main packages
| ├─ scud // each lambda stays at own executable
| | └─ main.go
| └─ ...
|
├─ cloud // IaC, aws cdk application
| └─ ... // orchestrate ops model
|
├─ .github // CI/CD with GitHub Actions
| └─ ...
|
└─ suite // API testing suite
├─ api.go // (disabled in this release)
└─ ...
├─ 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
| └─ 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
└─ ...
```

### Development workflows

**dependencies**
**unit testing**

The application requires 3rd party libraries for dev and opts. Fetch them with the following commands:
Test the Golang application and its cloud infrastructure

```bash
go get -d ./...
go test ./...
```

**unit testing**
**local testing**

Test the Golang application and its cloud infrastructure
Run application locally

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

**build**
Expand All @@ -154,9 +177,16 @@ cdk deploy
In few seconds, the application becomes available at

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

**test in production**

```bash
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
Expand Down
8 changes: 3 additions & 5 deletions cloud/blueprint.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"github.com/fogfish/scud"
)

//
func vsn(app awscdk.App) string {
switch val := app.Node().TryGetContext(jsii.String("vsn")).(type) {
case string:
Expand Down Expand Up @@ -44,20 +43,19 @@ func main() {
app.Synth(nil)
}

//
// NewBlueprint create example REST api
func NewBlueprint(scope constructs.Construct) {
gateway := scud.NewGateway(scope, jsii.String("Gateway"),
&awsapigateway.RestApiProps{
RestApiName: jsii.String("scud"),
RestApiName: jsii.String("petshop"),
},
)

myfun := scud.NewFunctionGo(scope, jsii.String("MyFun"),
&scud.FunctionGoProps{
SourceCodePackage: "github.com/fogfish/blueprint-serverless-golang",
SourceCodeLambda: "cmd/lambda/scud",
SourceCodeLambda: "cmd/lambda/petshop",
},
)
gateway.AddResource("scud", myfun)
gateway.AddResource("petshop", myfun)
}
2 changes: 1 addition & 1 deletion cloud/blueprint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestBlueprint(t *testing.T) {
jsii.String("Custom::LogRetention"): jsii.Number(1),
}

template := assertions.Template_FromStack(stack)
template := assertions.Template_FromStack(stack, nil)
for key, val := range require {
template.ResourceCountIs(key, val)
}
Expand Down
19 changes: 19 additions & 0 deletions cmd/lambda/petshop/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"github.com/aws/aws-lambda-go/lambda"
"github.com/fogfish/blueprint-serverless-golang/cmd"
httpd "github.com/fogfish/gouldian/v2/server/aws/apigateway"
)

func main() {
api := cmd.NewPetShopAPI()

lambda.Start(
httpd.Serve(
api.List(),
api.Create(),
api.Lookup(),
),
)
}
17 changes: 0 additions & 17 deletions cmd/lambda/scud/main.go

This file was deleted.

20 changes: 20 additions & 0 deletions cmd/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package main

import (
server "net/http"

"github.com/fogfish/blueprint-serverless-golang/cmd"
"github.com/fogfish/gouldian/v2/server/httpd"
)

func main() {
api := cmd.NewPetShopAPI()

server.ListenAndServe(":8080",
httpd.Serve(
api.List(),
api.Create(),
api.Lookup(),
),
)
}
21 changes: 21 additions & 0 deletions cmd/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package cmd

import (
core "github.com/fogfish/blueprint-serverless-golang"
"github.com/fogfish/blueprint-serverless-golang/http"
"github.com/fogfish/blueprint-serverless-golang/internal/mock"
"github.com/fogfish/blueprint-serverless-golang/internal/services/pets"
cache "github.com/fogfish/blueprint-serverless-golang/internal/storage"
)

func NewPetShopAPI() *http.PetShopAPI {
storePets := cache.New[core.Identity, core.Pet]()
storePrice := cache.New[core.Category, core.Price]()

fetcher := pets.NewFetcher(storePets, storePrice)
creator := pets.NewCreator(storePets, storePrice)

mock.SetupCreatorWithPets(creator)

return http.NewPetShopAPI(fetcher, creator)
}
Loading

0 comments on commit 8ef1e72

Please sign in to comment.