fortune

module
v0.0.0-...-cc2cefa Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 28, 2025 License: MIT

README ¶

fortune

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.

Installation

Below are instructions for running the service locally or with kind.

Prerequisites

Ensure you have the following installed before proceeding:

Clone the repository
git clone git@github.com:tetsuo/fortune.git
cd fortune
git fetch --tags  # Ensure tags are fetched for build versioning
Install Go dependencies
make tidy
Spin up a local MySQL instance

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.

Verify database creation

Check if fortune_db exists:

docker exec -it mysql mysql -u root -p -e "SHOW DATABASES LIKE 'fortune_db';"

Running migrations

Run migrate_db.sh to apply or manage database migrations.

Check migration status

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.

Apply migrations

Run the MySQL migrations from etc/migrations:

./scripts/migrate_db.sh up
Verify table creation
docker exec -it mysql \
  mysql -u root -p -e "USE fortune_db; SHOW TABLES LIKE 'fortune_cookies';"

Building & running the application

Build the application
make build
Start the fortune server
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

🚨 Expected output: Not Found (because we haven't added fortunes yet).

Upload fortunes

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
Retrieve a fortune
curl localhost:8080

🔮 Example output: "One planet is all you get."

Explore the local debug server

Visit localhost:8081 for debugging insights, metrics, and other useful details.

Running tests

Before deploying, ensure all tests pass:

./all.bash ci

This installs linters and runs tests. If everything is ✅, continue to release preparation.

Releasing

Goreleaser handles packaging and release generation.

Generate a release tarball
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
Build a Docker image
docker build -t fortune-frontend:latest .

Deploying to Kind

Create a Kind cluster
kind create cluster
Load the Docker image into the cluster
kind load docker-image fortune-frontend:latest
Set up Kubernetes config

From the root directory:

kind get kubeconfig --name kind > terraform/kubeconfig.yaml
Initialize Terraform

Navigate to terraform/ and run:

terraform init
Apply Terraform changes
terraform apply

Running migrations on Kubernetes

Forward MySQL port
kubectl port-forward -n fortune services/mysql 3306:3306
Run migrations
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.

Exposing the service

Forward HAProxy port
kubectl port-forward --namespace ingress-controller service/haproxy-kubernetes-ingress 8080:80
Update your hosts file

Update your /etc/hosts file, ensure it contains:

127.0.0.1 local.haproxy.kind
127.0.0.1 www.local.haproxy.kind
Upload fortunes again
curl -X POST -H "Content-Type: text/plain" \
  --data-binary @fortunes.txt \
  http://local.haproxy.kind:8080 -v
🔮 Get a fortune
curl local.haproxy.kind:8080

Third-party code

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

Directories ¶

Path Synopsis
cmd
frontend command
devtools
cmd/db command
internal
memory
Package memory provides functions to collect memory information from a variety of places.
Package memory provides functions to collect memory information from a variety of places.
middleware
Package middleware implements a simple middleware pattern for http handlers, along with implementations for some common middlewares.
Package middleware implements a simple middleware pattern for http handlers, along with implementations for some common middlewares.
wraperr
Package wraperr provides functions for wrapping/formatting errors.
Package wraperr provides functions for wrapping/formatting errors.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL