Go implementation of Distributed cowboys shootout game. Spec:
- We have a set of cowboys.
- Each cowboy has a unique name, health points and damage points.
- Each cowboy runs in it’s own isolated process, workload or replica.
- All communication between cowboys happen via your Redis MQ
- Cowboys encounter starts at the same time in parallel. Each cowboys selects random target and shoots.
- Subtract shooter damage points from target health points.
- If target cowboy health points are 0 or lower, then target is dead.
- Cowboys don’t shoot themselves and don’t shoot dead cowboys.
- After the shot shooter sleeps for 1 second.
- Last standing cowboy is the winner. Kubernetes, Helm, and Docker-compose are used for container orchestration solution.
You can run the game in two ways:
- You can run this game using docker compose where we have a master to orchestrate the game and each player will run in it's own container.
- You can run this game using Kubernetes platform with helm
This layout is following pattern:
cowboys
└───
├── .github
│ └── workflows
│ └── go.yml
├── cmd
│ └── master
│ └── main.go
│ └── app
│ └── setup.go
│ └── app.go
│ └── context.go
│ └── player
│ └── main.go
│ └── app
│ └── setup.go
│ └── app.go
│ └── context.go
├── internal
│ └── app
│ └── master.go
│ └── player.go
│ └── domain
│ └── master.go
│ └── player.go
│ └── game
│ └── event.go
│ └── game-state.go
├── build
│ └── Dockerfile
├── helm
│ └── <helm chart files>
├── docker-compose.yml.j2
├── Makefile
├── README.md
└── <source packages>
cowboys game is available in github cowboys
go get github.com/reactivejson/cowboys
build the app and docker images To build the components of the project, use the following commands:
make docker-build
This will build this application docker images so-called master and player
We use Jinja2 to run the application dynamically.
Use the following command to run the game and provide your list of players (or use the default one)
make run-app players=players.json
Example input:
{
"players": [
{
"name": "p1",
"health": 10,
"damage": 3
},
{
"name": "p2",
"health": 5,
"damage": 4
},
{
"name": "p3",
"health": 10,
"damage": 1
},
{
"name": "p4",
"health": 7,
"damage": 2
}
]
}
And check the logs to see who won:)
docker compose logs -f
make test
In order to deploy it in a Kubernetes platform with helm. Create Helm package
make helm-create
helm upgrade --namespace neo --install master chart/master -f <your-custom-values>.yml
helm upgrade --namespace neo --install player chart/player -f <your-custom-values-with-players>.yml
Test coverage is checked as a part of test execution with the gotestsum tool.
Test coverage is checked for unit tests and integration tests.
Coverage report files are available and stored as *coverage.txt
and are also imported in the SonarQube for easier browsing.
In the effort of reducing errors and improving the overall quality of code, golangci-lint is run as a part of the pipeline. Linting is run for the services and packages that have changes since the previous green build (in master) or previous commit (in local or review).
Any issues found by golangci-lint for the changed code will lead to a failed build.
golangci-lint rules are configured in .golangci.yml
.
- Go 1.18 or newer https://golang.org/doc/install
- Docker 18.09.6 or newer
Commonly used one letter variable names:
- i for index
- r for reader
- w for writer
- c for client
Apache 2.0, see LICENSE.