fortune is a simple HTTP API that serves random fortune cookies. It comes with observability and telemetry configured for GCP/GKE.
The API has two endpoints. GET / returns a random fortune from the database. POST / accepts a plain text body with fortunes separated by %, as per the original format of the Unix fortune command.
Below are instructions for running the service locally or with kind.
Ensure you have the following installed before proceeding:
- Go (โฅ v1.23.3)
- golang-migrate (โฅ v4.18.2)
- goreleaser (โฅ v2.1.0)
- Docker (latest recommended version)
- kind (โฅ v0.27)
- kubectl (latest recommended version)
- Terraform (โฅ v1.2.9)
git clone [email protected]:tetsuo/fortune.git
cd fortune
git fetch --tags # Ensure tags are fetched for build versioningmake tidyRun the following script to start a MySQL 8.0 container with the fortune_db database:
./scripts/docker_mysql.shThis starts MySQL, sets the root password, and enables general query logging.
๐ก You can modify values in this script, but it's recommended to stick to defaults for simplicity.
Check if fortune_db exists:
docker exec -it mysql mysql -u root -p -e "SHOW DATABASES LIKE 'fortune_db';"Run migrate_db.sh to apply or manage database migrations.
Ensure go-migrate is installed, then verify the current migration version:
./scripts/migrate_db.sh version๐ก If you see error: no migration, it means no migrations have been applied yet.
Run the MySQL migrations from etc/migrations:
./scripts/migrate_db.sh updocker exec -it mysql \
mysql -u root -p -e "USE fortune_db; SHOW TABLES LIKE 'fortune_cookies';"make buildLOG_LEVEL=debug ./bin/frontend(Or run with go run ./cmd/frontend/....)
If everything works, you should see logs like this:
2025-03-14T13:24:43.766+0100 INFO frontend/main.go:116 debug server listening on localhost:8081
2025-03-14T13:24:43.772+0100 INFO frontend/main.go:192 frontend server listening on localhost:8080
Try retrieving a fortune cookie:
curl localhost:8080๐จ Expected output: Not Found (because we haven't added fortunes yet).
Bulk insert a fortunes.txt file containing 2,000+ fortunes:
curl -X POST -H "Content-Type: text/plain" \
--data-binary @fortunes.txt \
http://localhost:8080 -vcurl localhost:8080๐ฎ Example output: "One planet is all you get."
Visit localhost:8081 for debugging insights, metrics, and other useful details.
Before deploying, ensure all tests pass:
./all.bash ciThis installs linters and runs tests. If everything is โ , continue to release preparation.
Goreleaser handles packaging and release generation.
goreleaser release -f .goreleaser.yml --snapshot --clean๐ This outputs the build to the dist/ folder.
Quick build (no release):
goreleaser build -f .goreleaser.yml --snapshot --clean --single-targetdocker build -t fortune-frontend:latest .kind create clusterkind load docker-image fortune-frontend:latestFrom the root directory:
kind get kubeconfig --name kind > terraform/kubeconfig.yamlNavigate to terraform/ and run:
terraform initterraform applykubectl port-forward -n fortune services/mysql 3306:3306DATABASE_USER=kinduser DATABASE_PASSWORD=kindpassword ./scripts/migrate_db.sh up๐จ In production, run migrations securely. The included mysql chart is not meant for production use.
kubectl port-forward --namespace ingress-controller service/haproxy-kubernetes-ingress 8080:80Update your /etc/hosts file, ensure it contains:
127.0.0.1 local.haproxy.kind
127.0.0.1 www.local.haproxy.kind
curl -X POST -H "Content-Type: text/plain" \
--data-binary @fortunes.txt \
http://local.haproxy.kind:8080 -vcurl local.haproxy.kind:8080I reused some internals from golang/pkgsite (the Go package index) and adapted them to work with MySQL.
Specifically, I modified the internal/database package to support MySQL, along with the CLI tool in devtools/cmd/db. The other borrowed packages from pkgsite (memory, middleware, wraperr) remain largely unchanged, aside from minor cleanup.