Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development

The operator is Python 3.12 on kopf, managed with uv. The package is qdrant_operator.

Layout

PathContents
src/qdrant_operator/domain.pyFrozen dataclasses for every spec and status, from_dict/to_dict, Helm value derivation, cron and retention rules. No I/O, no framework imports
src/qdrant_operator/ports.pytyping.Protocol interfaces: HelmPort, QdrantPort, StoragePort, KubernetesPort, TokenPort
src/qdrant_operator/usecases.pyOne dataclass per operation: ReconcileCluster, ObserveCluster, DeleteCluster, ExecuteBackup, DeleteBackupData, ExpireBackup, ExecuteRestore, ProcessSchedule, ReconcileCollection, DeleteCollection, IssueAccessKey, ExecuteMigration
src/qdrant_operator/handlers.pykopf handlers: event to dataclasses to use case to patch.status
src/qdrant_operator/*_adapter.pyHelm CLI, Qdrant REST over httpx, S3 over aioboto3, Kubernetes over kubernetes-asyncio, JWT signing over PyJWT
src/qdrant_operator/container.pyWires adapters into use cases
src/qdrant_operator/main.pyEntry point, loguru setup, kopf run
manifests/crds/The CRDs; charts/qdrant-operator/crds/ must be an identical copy
charts/qdrant-operator/The operator's own chart
tests/Unit tests with in-memory fakes, CRD sync check, integration suite
docs/This book

Rules the code follows: handlers call use cases only, use cases see ports only, adapters implement ports structurally. Status goes through patch.status.update. Transient problems raise kopf.TemporaryError, everything else writes Failed and raises kopf.PermanentError. Adapters keep no connection state and build a client per call. No temp files: snapshots stream node to bucket and bucket to node, Helm values go over stdin.

Make targets

make dev                # run against the current kubeconfig, text logs
make lint               # ruff check, ruff format --check, pyright --strict, helm lint
make format
make test               # unit tests
make test-integration   # QDRANT_OPERATOR_INTEGRATION=1, needs a cluster and helm
make crds-sync          # copy manifests/crds into the chart
make build              # docker image

Tests

tests/fakes.py holds FakeHelm, FakeQdrant, FakeStorage and FakeKubernetes, in-memory implementations of the ports that record calls; there is no mock.patch. test_domain.py and test_usecases.py run against those in well under a second and cover value derivation, cron and retention arithmetic, the backup and restore flows, schedule concurrency, collection reconciliation, token claims and renewal, and the migration copy loop. test_crds.py fails when the chart's CRDs differ from manifests/crds.

test_integration.py runs against a real cluster with helm on the path and the CRDs applied: it installs a one-node cluster through ReconcileCluster, waits for Running, port-forwards and queries Qdrant, uninstalls, and checks that the API server enforces the admission rules. CI runs it on a kind cluster on every push and pull request.

Releasing

Releases are cut by release-please from the conventional commit history. A release PR keeps pyproject.toml, Chart.yaml, uv.lock and CHANGELOG.md current; merging it tags vX.Y.Z, publishes the wheel and sdist to PyPI, pushes the multi-arch image and the Helm chart to ghcr.io/4thel00z, and attaches the CRDs to the GitHub release.

Documentation

mdbook serve docs --open

The book publishes to GitHub Pages from the book workflow on every push to main.