Skip to content

Commit 8ef1e72

Browse files
authored
Merge pull request #40 from fogfish/upgrade-version
integrate api testing
2 parents 681eeb6 + 4b0e0e0 commit 8ef1e72

35 files changed

+1060
-193
lines changed

.assay-it.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"suites": [
3+
"http/suites/petshop.go"
4+
]
5+
}

.github/workflows/build.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,18 @@ jobs:
1818

1919
- uses: actions/checkout@v2
2020

21-
- uses: fogfish/deploy-cdk-go@latest
21+
- id: deploy
22+
uses: fogfish/deploy-cdk-go@latest
2223
with:
23-
go-version: 1.18
24+
go-version: "1.20"
2425
stack: ${{ matrix.stack }}
2526
version: latest
2627
issue-to-create: ./.github/issue-spawn-latest.md
2728
aws-access-key: ${{ secrets.AWS_ACCESS_KEY }}
2829
aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
2930
aws-region: eu-west-1
31+
32+
- uses: assay-it/github-actions-quality-check@latest
33+
with:
34+
install-go: false
35+
system-under-test: ${{ steps.deploy.outputs.deployed-api }}

.github/workflows/carry.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ jobs:
1515

1616
- uses: actions/checkout@v2
1717

18-
- uses: fogfish/deploy-cdk-go@latest
18+
- id: deploy
19+
uses: fogfish/deploy-cdk-go@latest
1920
with:
20-
go-version: 1.18
21+
go-version: "1.20"
2122
stack: ${{ matrix.stack }}
2223
version: ${{ github.event.release.name }}
2324
issue-to-create: ./.github/issue-spawn-release.md
2425
aws-access-key: ${{ secrets.AWS_ACCESS_KEY }}
2526
aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
2627
aws-region: eu-west-1
28+
29+
- uses: assay-it/github-actions-quality-check@latest
30+
with:
31+
install-go: false
32+
system-under-test: ${{ steps.deploy.outputs.deployed-api }}

.github/workflows/check-clean.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121

2222
- uses: fogfish/deploy-cdk-go@latest
2323
with:
24-
go-version: 1.18
24+
go-version: "1.20"
2525
command: destroy
2626
stack: ${{ matrix.stack }}
2727
version: pr${{ github.event.number }}

.github/workflows/check-code.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818

1919
- uses: actions/setup-go@v3
2020
with:
21-
go-version: 1.18
21+
go-version: "1.20"
2222
cache: true
2323

2424
- uses: dominikh/[email protected]

.github/workflows/check-spawn.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,22 @@ jobs:
2020
steps:
2121
- uses: actions/checkout@v2
2222

23-
- uses: fogfish/deploy-cdk-go@latest
23+
- id: deploy
24+
uses: fogfish/deploy-cdk-go@latest
2425
with:
25-
go-version: 1.18
26+
go-version: "1.20"
2627
stack: ${{ matrix.stack }}
2728
version: pr${{ github.event.number }}
2829
issue-to-comment: ${{ github.event.number }}
2930
aws-access-key: ${{ secrets.AWS_ACCESS_KEY }}
3031
aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
3132
aws-region: eu-west-1
3233

34+
- uses: assay-it/github-actions-quality-check@latest
35+
with:
36+
install-go: false
37+
system-under-test: ${{ steps.deploy.outputs.deployed-api }}
38+
3339
- uses: buildsville/add-remove-label@v1
3440
if: always()
3541
with:

.github/workflows/check-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323

2424
- uses: actions/setup-go@v3
2525
with:
26-
go-version: 1.18
26+
go-version: "1.20"
2727
cache: true
2828

2929
- name: go build

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717
node_modules/
1818
.vscode/
1919

20+
suites/assay-it/

README.md

Lines changed: 65 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ This project crafts a fully functional blueprint of Golang serverless RESTful ap
4040

4141
[AWS CDK](https://aws.amazon.com/cdk) is amazing technology to automate the development and operation of application into one process and one codebase.
4242

43-
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.
43+
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.
44+
4445

4546
## Installation
4647

47-
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.
48+
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.
4849

4950
```
5051
go get github.com/fogfish/blueprint-serverless-golang
@@ -75,64 +76,86 @@ git merge blueprint/main --allow-unrelated-histories --squash
7576
Before Getting started, you have to ensure
7677

7778
* [Golang](https://golang.org/dl/) development environment v1.16 or later
78-
* [AWS CDK](https://docs.aws.amazon.com/cdk/latest/guide/work-with.html#work-with-prerequisites)
79-
* Access to AWS Account
79+
* [assay-it](https://assay.it) utility for testing cloud apps in production
80+
* [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
81+
* [GitHub](https://github.com) account for managing source code and running CI/CD pipelines as [GitHub Actions](https://docs.github.com/en/actions)
82+
* Account on [Amazon Web Services](https://aws.amazon.com) for running the application in production
8083

8184

8285
## Getting started
8386

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

86-
The structure resembles the standard package layout proposed in [this blog post](https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1):
89+
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:
8790

8891
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.
8992

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

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

9497
```
9598
github.com/.../the-beautiful-app
96-
├─ stub.go // domain types, unit test
97-
├─ ... // "algebra" of your application
98-
|
99-
├─ http // RESTful API and HTTP protocol
100-
| ├─ api.go // api endpoint(s), unit tests,
101-
| └─ ... // other endpoints
102-
|
103-
├─ cmd // executables of the project
104-
| └─ lambda // aws lambda's are main packages
105-
| ├─ scud // each lambda stays at own executable
106-
| | └─ main.go
107-
| └─ ...
108-
|
109-
├─ cloud // IaC, aws cdk application
110-
| └─ ... // orchestrate ops model
111-
|
112-
├─ .github // CI/CD with GitHub Actions
113-
| └─ ...
114-
|
115-
└─ suite // API testing suite
116-
├─ api.go // (disabled in this release)
117-
└─ ...
99+
├─ pet.go // the root defines domain types, unit test
100+
├─ ... // "algebra" of your application
101+
|
102+
├─ storage.go // defines capability requires to store core
103+
| // objects at the external storage, hex-arch
104+
| // use "port" concept to depict it
105+
|
106+
├─ internal/storage // sub-package for dependency/technology ...
107+
| // it follows the standard package layout to
108+
| // adapt domain/implementation/dependency.
109+
| // in this example storage implements in-memory
110+
| // database for all domain objects.
111+
|
112+
├─ internal/services // entry point to the core, implement app logic
113+
| └─ pets // entire logic about pets domain
114+
| ├─ fetcher.go // fetch and enrich pets objects
115+
| └─ creator.go // create pets objects
116+
|
117+
├─ internal/mock // shared mock
118+
|
119+
├─ http // public REST API exposed by application.
120+
| ├─ petshop.go // collection of petshop endpoints impl. by app
121+
| | // endpoints consumer services using ports
122+
| |
123+
| ├─ api // public objects used by API
124+
| | └─ pet.go
125+
| └─ suites // testing suites for api endpoint(s)
126+
|
127+
├─ cmd // executables of the project
128+
| ├─ lambda // aws lambda's are main packages
129+
| | ├─ petshop // each lambda stays at own executable
130+
| | | └─ main.go // single lambda pattern is not recommended
131+
| | ...
132+
| └─ server // run application as standalone server
133+
| └─ main.go
134+
|
135+
├─ cloud // IaC, aws cdk application
136+
| └─ ... // orchestrate ops model
137+
|
138+
└─ .github // CI/CD with GitHub Actions
139+
└─ ...
118140
```
119141

120142
### Development workflows
121143

122-
**dependencies**
144+
**unit testing**
123145

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

126148
```bash
127-
go get -d ./...
149+
go test ./...
128150
```
129151

130-
**unit testing**
152+
**local testing**
131153

132-
Test the Golang application and its cloud infrastructure
154+
Run application locally
133155

134156
```bash
135-
go test ./...
157+
go run cmd/server/main.go
158+
assay-it test --target http://127.1:8080
136159
```
137160

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

156179
```
157-
curl https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/api/scud
180+
curl https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/api
181+
```
182+
183+
**test in production**
184+
185+
```bash
186+
assay-it test --target https://xxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/api
158187
```
159188

189+
160190
**destroy**
161191

162192
Destroy the application and remove all its resource from AWS account

cloud/blueprint.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/fogfish/scud"
1212
)
1313

14-
//
1514
func vsn(app awscdk.App) string {
1615
switch val := app.Node().TryGetContext(jsii.String("vsn")).(type) {
1716
case string:
@@ -44,20 +43,19 @@ func main() {
4443
app.Synth(nil)
4544
}
4645

47-
//
4846
// NewBlueprint create example REST api
4947
func NewBlueprint(scope constructs.Construct) {
5048
gateway := scud.NewGateway(scope, jsii.String("Gateway"),
5149
&awsapigateway.RestApiProps{
52-
RestApiName: jsii.String("scud"),
50+
RestApiName: jsii.String("petshop"),
5351
},
5452
)
5553

5654
myfun := scud.NewFunctionGo(scope, jsii.String("MyFun"),
5755
&scud.FunctionGoProps{
5856
SourceCodePackage: "github.com/fogfish/blueprint-serverless-golang",
59-
SourceCodeLambda: "cmd/lambda/scud",
57+
SourceCodeLambda: "cmd/lambda/petshop",
6058
},
6159
)
62-
gateway.AddResource("scud", myfun)
60+
gateway.AddResource("petshop", myfun)
6361
}

cloud/blueprint_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestBlueprint(t *testing.T) {
2424
jsii.String("Custom::LogRetention"): jsii.Number(1),
2525
}
2626

27-
template := assertions.Template_FromStack(stack)
27+
template := assertions.Template_FromStack(stack, nil)
2828
for key, val := range require {
2929
template.ResourceCountIs(key, val)
3030
}

cmd/lambda/petshop/main.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package main
2+
3+
import (
4+
"github.com/aws/aws-lambda-go/lambda"
5+
"github.com/fogfish/blueprint-serverless-golang/cmd"
6+
httpd "github.com/fogfish/gouldian/v2/server/aws/apigateway"
7+
)
8+
9+
func main() {
10+
api := cmd.NewPetShopAPI()
11+
12+
lambda.Start(
13+
httpd.Serve(
14+
api.List(),
15+
api.Create(),
16+
api.Lookup(),
17+
),
18+
)
19+
}

cmd/lambda/scud/main.go

Lines changed: 0 additions & 17 deletions
This file was deleted.

cmd/server/main.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package main
2+
3+
import (
4+
server "net/http"
5+
6+
"github.com/fogfish/blueprint-serverless-golang/cmd"
7+
"github.com/fogfish/gouldian/v2/server/httpd"
8+
)
9+
10+
func main() {
11+
api := cmd.NewPetShopAPI()
12+
13+
server.ListenAndServe(":8080",
14+
httpd.Serve(
15+
api.List(),
16+
api.Create(),
17+
api.Lookup(),
18+
),
19+
)
20+
}

cmd/service.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package cmd
2+
3+
import (
4+
core "github.com/fogfish/blueprint-serverless-golang"
5+
"github.com/fogfish/blueprint-serverless-golang/http"
6+
"github.com/fogfish/blueprint-serverless-golang/internal/mock"
7+
"github.com/fogfish/blueprint-serverless-golang/internal/services/pets"
8+
cache "github.com/fogfish/blueprint-serverless-golang/internal/storage"
9+
)
10+
11+
func NewPetShopAPI() *http.PetShopAPI {
12+
storePets := cache.New[core.Identity, core.Pet]()
13+
storePrice := cache.New[core.Category, core.Price]()
14+
15+
fetcher := pets.NewFetcher(storePets, storePrice)
16+
creator := pets.NewCreator(storePets, storePrice)
17+
18+
mock.SetupCreatorWithPets(creator)
19+
20+
return http.NewPetShopAPI(fetcher, creator)
21+
}

0 commit comments

Comments
 (0)