Fortune is a service for serving fortune cookies. It reuses internal code from pkgsite (the Go package index), adapted for MySQL, and implements a lean, GCP-native stack with full observability. The project showcases a production-ready Go setup you can build on or deploy as-is.
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 versioning
make tidy
Run the following script to start a MySQL 8.0 container with the fortune_db
database:
./scripts/docker_mysql.sh
This 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 up
docker exec -it mysql \
mysql -u root -p -e "USE fortune_db; SHOW TABLES LIKE 'fortune_cookies';"
make build
LOG_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 ; echo
🚨 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 -v
curl localhost:8080 ; echo
🔮 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 ci
This 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-target
docker build -t fortune-frontend:latest .
kind create cluster
kind load docker-image fortune-frontend:latest
From the root directory:
kind get kubeconfig --name kind > terraform/kubeconfig.yaml
Navigate to terraform/
and run:
terraform init
terraform apply
kubectl port-forward -n fortune services/mysql 3306:3306
DATABASE_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:80
Update 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 -v
curl local.haproxy.kind:8080 ; echo
🎉 I hope it's a good one!
MIT license