Kubernetes operator for the nais platform that manages Postgres, Valkey, and OpenSearch resources. It reconciles opinionated nais CRDs into the full set of cloud-provider resources needed to run these services on GCP.
| CRD | API group | Backend | Creates |
|---|---|---|---|
Postgres |
data.nais.io/v1 |
Zalando postgres-operator or CloudNativePG | Postgres cluster, NetworkPolicy, IAM resources, ServiceAccount, RoleBinding, PrometheusRule |
Valkey |
nais.io/v1 |
Aiven | Aiven Valkey instance + ServiceIntegration (metrics) |
OpenSearch |
nais.io/v1 |
Aiven | Aiven OpenSearch instance + ServiceIntegration (metrics) |
- mise — manages all tool versions and tasks
- Docker — for building images
- A Kubernetes cluster (for e2e tests)
# Install all tools (Go, golangci-lint, controller-gen, etc.)
mise install
# Run all checks and tests
mise run all
# Run only unit/integration tests
mise run test
# Run only linting
mise run lint| Task | Description |
|---|---|
mise run all |
Run all checks, tests, and build |
mise run test |
Run tests (requires envtest binaries) |
mise run test-race |
Run tests with race detector |
mise run test-e2e |
Run Chainsaw e2e tests (requires a running cluster) |
mise run lint |
Run golangci-lint |
mise run vet |
Run go vet |
mise run check |
Run govulncheck |
mise run fmt |
Format code |
mise run fmt-check |
Check formatting |
mise run generate |
Generate CRDs, RBAC, and DeepCopy methods |
mise run generate-check |
Verify generated code is up to date |
mise run tidy-check |
Verify go.mod is tidy |
mise run build |
Build manager binary |
mise run helm-lint |
Lint Helm charts |
mise run docker |
Build Docker image |
mise run run |
Run controller locally |
mise run generate:doc |
Generate documentation for nais/doc |
Lefthook is configured for pre-commit (fmt, lint, vet, generate check) and pre-push (tests). Install hooks with:
lefthook installSee ARCHITECTURE.md for detailed information about project structure, conventions, and design patterns.
The Postgres CRD supports two backend engines:
- Zalando (default) — uses the Zalando postgres-operator with Spilo
- CNPG — uses CloudNativePG with barman-cloud backups
Engine selection is immutable after creation. The operator detects existing resources and prevents engine changes.
CI uses the centralized nais/actions reusable workflow (mise-build-deploy-fasit.yaml), which runs all mise tasks in parallel, builds and pushes the Docker image and Helm chart, and deploys via Fasit.
E2E tests run separately in a kind cluster using Chainsaw.
- Install tools —
mise installsets up Go, golangci-lint, controller-gen, helm, and all other dependencies at pinned versions. - Make changes — edit code, CRD types, or Helm chart.
- Regenerate — if you changed types in
pkg/api/, runmise run generateto update CRDs and DeepCopy methods. - Test locally —
mise run testruns the full Ginkgo test suite with envtest (a real API server + etcd, no cluster needed). - Commit — lefthook pre-commit hooks run fmt, lint, vet, and generate-check automatically.
- Push — pre-push hook runs tests. CI runs the full matrix in parallel.
Golden tests are data-driven: each test case is a directory under internal/controller/testdata/{resource}/{case-name}/:
my-test-case/
├── object.yaml # Input CRD spec to reconcile
├── prepared_data.yaml # Optional: set engine, projectID, etc.
├── related_objects/ # Optional: pre-existing objects in cluster
├── contains/ # Assert actions contain at least these (use for partial checks)
│ └── cluster.yaml
└── consists_of/ # Assert actions match exactly these (use for full coverage)
└── cluster.yaml
Each expected file in contains/ or consists_of/ specifies:
action:create,update,createOrUpdate,claim,recreatematcher:Equal(exact match) orSubset(only specified fields must match)object: the expected Kubernetes resource
mise run test # Integration tests (envtest — no cluster required)
mise run test-e2e # E2E tests (requires kind cluster with operator deployed)After modifying types in pkg/api/ or RBAC markers (+kubebuilder:rbac):
mise run generate # Regenerate CRDs + DeepCopy + copy to Helm chart
mise run generate-check # Verify nothing is out of date (CI runs this)This repository occasionally uses GitHub Copilot to generate code.