A CLAUDE.md is just a markdown file at the root of your repo. Copy the content below into your own project's CLAUDE.md to give your agent the same context.
npx versuz@latest install mongodb-mongodb-atlas-kubernetes --kind=claude-mdcurl -o CLAUDE.md https://raw.githubusercontent.com/mongodb/mongodb-atlas-kubernetes/HEAD/CLAUDE.md# CLAUDE.md
## Project overview
MongoDB Atlas Kubernetes Operator — a Kubernetes operator that provides native integration between Kubernetes and MongoDB Atlas. It manages Atlas projects, clusters, database users, network access, backups, and more through Kubernetes custom resources.
## Setup
This project uses [devbox](https://www.jetify.com/devbox). Before making any changes, verify you are inside a devbox environment:
```shell
if [ -z "$DEVBOX_SHELL_ENABLED" ]; then echo "WARNING: Not in a devbox environment. Run 'devbox shell' first."; fi
```
If not in a devbox environment, always ask the user whether to prefix commands with `devbox run`.
## Code style and conventions
Code style and formatting conventions are maintained as agent skills. See the Skills section below for local and global skill directories.
## Architecture
Key directories:
- `api/v1/` — CRD type definitions (the public API surface). Each `atlas*_types.go` file defines a custom resource (e.g. `AtlasProject`, `AtlasDeployment`, `AtlasDatabaseUser`).
- `internal/controller/` — Reconciliation controllers, one sub-package per custom resource (e.g. `atlasproject/`, `atlasdeployment/`). This is where the core operator logic lives.
- `pkg/` — Importable library code (controller helpers, finalizers, rate limiting, state machine).
- `internal/indexer/` — Hand-written indexer registration logic. Registers field indexes on the controller-runtime cache so controllers can efficiently look up resources by fields like project references or credentials.
- `internal/mocks/` — Generated mock interfaces for Atlas SDK and translation layers.
- `internal/generated/` — Scaffolded code generated by `make gen-all`. Contains three sub-areas:
- `internal/generated/crds/` — Embedded CRD YAML generated from OpenAPI specs.
- `internal/generated/indexers/` — Scaffolded field indexers for experimental CRDs (e.g. look up clusters/database users by group).
- `internal/generated/controller/` — Scaffolded controllers for experimental CRDs.
- `internal/generated/controller/connectionsecret/` — Controller that manages connection secrets for feature generated CRDs. It watches Cluster/FlexCluster resources and reconciles Kubernetes Secrets containing connection strings, credentials, and endpoints so applications can connect to Atlas databases.
- `internal/nextapi/` — Experimental / auto-generated types and controllers (enabled with `EXPERIMENTAL=1`).
- `internal/nextapi/generated/v1/` — Go types generated from OpenAPI specs. Do not edit by hand.
- `config/` — Kustomize overlays, CRD bases (`config/crd/`), RBAC (`config/rbac/`), webhook config, samples.
- `config/generated/` — Generated CRDs from OpenAPI specs. Do not edit by hand.
- `cmd/manager/` — Operator entrypoint.
- `test/` — All non-unit test code (see Testing section below).
- `docs/` — Project documentation (development, testing, releases, runbooks).
## Testing
See @docs/testing.md for the full testing philosophy and mock examples.
Key principles:
- Prefer unit tests over integration and e2e tests. Unit tests are the primary gatekeepers against regressions.
- Prefer TDD: write the test before the implementation when the behavior is clear.
- Keep each test focused on a single check.
- Use external test packages (`package xxx_test`) whenever possible.
- When adding new e2e tests, use the newer `test/e2e2/` framework instead of `test/e2e/`.
Running tests:
- `make unit-test` — run all unit tests with race detection and coverage. This should always pass without any setup.
- `make int-test label=<label>` — run integration tests (requires `AKO_INT_TEST=1` and Atlas credentials).
- `make e2e label=<label>` — run e2e tests (requires `AKO_E2E_TEST=1`, Atlas credentials, and a kind cluster).
- Run a single test: `go test -run TestFoo ./pkg/...`
Test code layout:
- `test/helper/` — shared test helpers and utilities.
- `test/atlas/` — Atlas SDK service mocks for unit tests.
- `test/int/` — integration tests (skipped by default, need `AKO_INT_TEST=1`).
- `test/e2e/` — end-to-end tests (skipped by default, need `AKO_E2E_TEST=1`).
Mocking:
- For Kubernetes: use `sigs.k8s.io/controller-runtime/pkg/client/fake` with `NewClientBuilder`.
- For Atlas: mock at the SDK service interface level using structs in `test/atlas/`. Prefer this over HTTP-level mocking.
- Generated mocks live in `internal/mocks/` — regenerate with `make generate`.
## Guardrails
Do not:
- Edit generated files by hand. These are regenerated by `make generate` or `make gen-all`:
- `zz_generated.deepcopy.go` files anywhere in the tree
- Files under `internal/nextapi/generated/v1/`
- Files under `config/generated/`
- Files under `internal/mocks/`
- Run `go mod tidy`, `go generate`, or any Go toolchain command outside of devbox. Always use `make` targets or prefix with `devbox run`.
- Add new dependencies without running `make lint` and `make unit-test` to verify compatibility.
- Introduce e2e tests when unit or integration tests suffice. E2e tests are expensive and slow CI.
## Verification
After making changes, run `make ci` to execute all unit tests and linting checks before considering the work done. This is the same gate that CI enforces on pull requests.
For smaller iterations, run `make fmt && make lint && make unit-test` individually.
## Skills
Agent skills with detailed instructions are available in these directories:
- `.claude/skills/` — project-specific skills
- `~/.claude/skills/` — user-level skills
Available skills:
- `investigate-e2e-failure` — diagnose CI end-to-end test failures by downloading and analyzing GitHub Actions logs using `gh`.
## Makefile targets
Run `make help` for the full list. Key targets:
- `make run` — build and run the operator locally against kind
- `make manager` — build the manager binary
- `make generate` — generate code (deep copy, mocks)
- `make manifests` — generate CRDs, RBAC, webhooks
- `make fmt` — format code (gci)
- `make vet` — run go vet
- `make lint` — run golangci-lint
- `make unit-test` — run unit tests
- `make e2e label=<label>` — run e2e tests by label
- `make ci` — run all unit tests and linting checks
- `make install-crds` — install CRDs in Kubernetes
- `make run-kind` / `make stop-kind` — manage local kind cluster
- `make image` — build operator image for local development
- `make bundle` — generate OLM bundle
- `make clean` — clean built binaries and generated files
- `make gen-all` — generate all CRDs, Go types, and scaffolding
- `make api-docs` — generate API documentation
## Bundle generation
The operator is distributed on OpenShift via OLM (Operator Lifecycle Manager). `make bundle` generates the OLM bundle — a directory containing the ClusterServiceVersion (CSV), CRDs, and metadata that OLM uses to install and upgrade the operator.
See @docs/dev/bundle.md for full details on the bundle pipeline, directory layout, versioning, and deployment.
Key targets:
- `make bundle` — generate the full OLM bundle (CSV, CRDs, metadata, Dockerfile) into `bundle/`.
- `make bundle-dev` — generate a bundle patched for the QA Atlas endpoint.
- `make bundle-build` — build the bundle container image.
- `make bundle-validate` — validate the bundle with `operator-sdk bundle validate`.
- `make deploy-olm` — build, push, and deploy the bundle to OpenShift via CatalogSource and Subscription.
- `make clean-bundle` — remove all generated bundle and deploy artifacts.
Key files:
- `config/manifests-template/bases/` — hand-maintained CSV template. Edit this to change operator metadata or install modes.
- `config/release/{dev,prod}/` — Kustomize overlays per environment (`ENV` variable, default `dev`).
- `version.json` — source of truth for `current` (released) and `next` (upcoming) versions.
- `bundle/` and `bundle.Dockerfile` — generated output, not checked in.
## CRD generation
`make manifests` generates CRD YAML, RBAC roles, and webhook config from Go type definitions using `controller-gen`.
How it works:
1. `controller-gen` reads marker comments (e.g. `// +kubebuilder:...`) from Go types in `api/` and controller code in `internal/controller/`.
2. It produces CRD YAML files into `config/crd/bases/`. These files are auto-generated — do not edit by hand.
3. A kustomization is created in `config/crd/bases/` so Kustomize can compose CRDs with patches and overlays.
4. RBAC roles are split into clusterwide and namespaced variants via `scripts/split_roles_yaml.sh`.
Key paths:
- `api/v1/` — Go types with `kubebuilder` markers that drive CRD generation.
- `config/crd/bases/` — generated CRD YAML output. Regenerated on every `make manifests`, not checked in.
- `config/crd/kustomization.yaml` — references `bases/` and applies `kustomizeconfig.yaml` for webhook name/namespace substitution.
- `config/crd/experimental/` — placeholder for experimental CRD overlays (used when `EXPERIMENTAL=1`).
To regenerate: `make manifests`. This is also a dependency of `make bundle` and `make release`.
## Feature generated CRDs
Feature generated CRDs are an auto-generated set of CRDs, Go types, controllers, and indexers derived from the MongoDB Atlas OpenAPI specification. They live under the `atlas.generated.mongodb.com` API group and are gated behind `EXPERIMENTAL=1`.
The pipeline has three stages, orchestrated by `make gen-all`:
**1. CRD generation (`make gen-crds`)**
The `openapi2crd` tool (in `tools/openapi2crd/`) reads the Atlas OpenAPI spec and produces CRD YAML. It is configured by `crd2go/openapi2crd.yaml`, which defines:
- Which OpenAPI spec version to use (e.g. `v20250312`).
- Which CRDs to generate (Group, Cluster, FlexCluster, DatabaseUser, CustomRole, etc.), each mapped to an Atlas API path and OpenAPI schema.
- Which properties are spec-only (read-write), status-only (read-only), sensitive, or skipped.
- Cross-resource references (e.g. Cluster references a Group via `groupRef`).
- A plugin pipeline (`base`, `parameters`, `connection_secret`, `status`, `references`, etc.) that shapes the CRD output.
Output goes to `config/generated/crd/bases/crds.yaml` and is copied to `internal/generated/crds/crds.yaml` for embedding.
**2. Go type generation (`make gen-go-types`)**
The `crd2go` tool reads the generated CRD YAML and produces Go structs into `internal/nextapi/generated/v1/`. Configuration is in `crd2go/crd2go.yaml`, which controls type renames, imports, and deep copy generation. Do not edit the generated Go files by hand.
**3. Controller and indexer scaffolding (`make run-scaffolder`)**
The `scaffolder` tool (in `tools/scaffolder/`) reads the generated CRD YAML and produces:
- Field indexers into `internal/generated/indexers/` (e.g. look up clusters by group).
- Controller scaffolding into `internal/generated/controller/` (one sub-package per CRD kind).
- Exporter scaffolding into `pkg/generated/exporter/`.
Use `SCAFFOLDER_FLAGS` to control scope: `--all` (default) regenerates everything, `--kind=Group --override` targets a single kind.
Key targets:
- `make gen-all` — run all three stages plus formatting.
- `make regen-crds` — clean and regenerate CRDs only.
- `make build-autogen` — generate everything and build an experimental operator image.
To enable at runtime, set `EXPERIMENTAL=1` on `make manifests`, `make generate`, or `make install-crds`.
## Documentation
Project documentation lives in `docs/`. Scan it recursively for context on development, testing, releases, API references, and operational runbooks.