Development¶
This guide covers building, testing, and releasing the driver locally.
Prerequisites¶
| Tool | Version | Notes |
|---|---|---|
| Go | ≥ 1.24 | go.mod specifies the minimum |
| golangci-lint (optional) | Latest | Or rely on the CI lint job |
Building¶
# Clone the repository
git clone https://github.com/teamzuzu/rancher-rackspace-spot-driver.git
cd rancher-rackspace-spot-driver
# Sync dependencies
go mod tidy
# Build for your current platform
go build -o bin/kontainer-engine-driver-rackspacespot .
# Cross-compile for linux/amd64
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 \
go build -ldflags "-s -w" -o bin/kontainer-engine-driver-rackspacespot .
# Cross-compile for linux/arm64
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 \
go build -ldflags "-s -w" -o bin/kontainer-engine-driver-rackspacespot-arm64 .
Running tests¶
Tests use the standard library only — no external test dependencies are required.
Linting¶
# Format
go fmt ./...
# Vet
go vet ./...
# Full lint (requires golangci-lint)
golangci-lint run --timeout 5m
The CI pipeline runs all three checks on every pull request.
Project layout¶
.
├── main.go # Entry point — starts the gRPC driver server
├── driver/
│ ├── driver.go # types.Driver interface implementation
│ ├── client.go # Rackspace Spot API client wrapper
│ ├── config.go # Cluster state, flags, and serialization
│ └── util.go # Kubeconfig parsing + Rancher service account bootstrap
├── docs/ # MkDocs source (this site)
├── .github/
│ └── workflows/
│ ├── ci.yml # Lint, build, test on every PR
│ ├── release.yml # Manual release workflow
│ └── pages.yml # GitHub Pages deployment
├── .golangci.yml # golangci-lint configuration
├── .goreleaser.yml # GoReleaser build configuration
└── mkdocs.yml # MkDocs site configuration
Making changes¶
- Fork and clone the repository
- Create a branch:
git checkout -b feature/my-change - Make changes and add tests where appropriate
- Run CI checks locally:
- Open a pull request against
main
All PRs must pass the CI pipeline before merge. The pipeline runs:
golangci-lint(format, errcheck, staticcheck, and more)go mod tidydrift checkgo buildfor linux/amd64 and linux/arm64go test -racego vet
Architecture notes¶
Driver lifecycle¶
Rancher calls the driver over a local gRPC socket. The sequence for cluster creation is:
Rancher → Create() → provisions CloudSpace + node pools
→ PostCheck() → waits for Ready, fetches kubeconfig, bootstraps service account
For updates:
Rancher → Update() → reconciles node pools (create/update as needed)
→ PostCheck() → re-validates readiness
For deletion:
State persistence¶
The driver serializes cluster state (pool config, CloudSpace name, organization) into ClusterInfo.Metadata["state"] as JSON. The refresh token is stored separately in ClusterInfo.Password so it is never included in the logged metadata blob. Rancher stores both and passes them back on every subsequent call. There is no external state store.
k8s dependency pinning¶
The go.mod contains replace directives that pin k8s.io/api, k8s.io/apimachinery, and k8s.io/client-go to v0.27.4. This is required because kontainer-engine transitively depends on rancher/rke, which imports k8s.io/client-go v12.0.0+incompatible. That version references alpha API packages (auditregistration/v1alpha1, batch/v2alpha1) that were removed in k8s.io/api ≥ v0.28. The pin keeps those packages available without breaking the module graph.
Releasing¶
Releases are created via the Release workflow in GitHub Actions — no manual tagging needed.
- Go to Actions → Release → Run workflow
- Enter the version in
vMAJOR.MINOR.PATCHformat (e.g.v1.2.3) - Optionally check Publish as draft release to review before it goes public
- Click Run workflow
The workflow will:
- Validate the version format
- Create and push a signed git tag
- Run GoReleaser to build linux/amd64 and linux/arm64 binaries and publish a GitHub Release
Permissions
Only repository maintainers with write access can trigger the release workflow.
Contributing¶
Issues and pull requests are welcome. Please open an issue first for significant changes so the approach can be discussed before you invest time in an implementation.