Monedula
monedula-gitops docs menu

One model, two runtimes

How the monedula-gitops CLI and Kubernetes operator share one resource model and one diff engine, and where credentials and gating differ.

Concepts 1 of 6

2 min read

Updated 9 October 2026

Markdown

On this page

The CLI runs from a terminal or a CI/CD pipeline, and the Kubernetes operator runs inside a cluster. Both work with the same six kinds, all with apiVersion: gitops.monedula.dev/v1alpha1: KafkaCluster, KafkaTopic, KafkaAccessPolicy, KafkaQuota, KafkaRoleBinding and KafkaUser. These are Kubernetes-native types, so a manifest you pass to the CLI has the shape of a custom resource the operator watches.

One engine

The diff, the risk gates and the executor are shared code. The operator runs one reconciler per kind on the same engine as apply, so plans, approval gates, reconciliation modes and the definition of drift are identical in both runtimes.

Where the runtimes differ

CLI Operator
Runs when you run a command, for example in CI continuously, on resource changes and on every resync
KafkaCluster file or directory from --cluster-config-file custom resource in the referencing resource’s namespace, or in the clusterNamespace
Credentials valueFrom.env, valueFrom.file relative to the cluster config directory, or inline valueFrom.secretKeyRef, a Secret in the resource’s namespace, or inline; env and file are rejected
KafkaUser passwords valueFrom.env, valueFrom.file valueFrom.secretKeyRef, or generate
Schema bodies valueFrom.file (relative to the manifest), inline inline, configMapKeyRef, secretKeyRef
Approve destructive changes apply --allow-destructive annotation gitops.monedula.dev/allow-destructive
Opt in to pruning apply --prune spec.prune: true
Removing a resource deletes no topic, user or quota; grants still in the managed scope are removed only with --prune finalizer under spec.deletionPolicy; topics and access policies also need the annotation gitops.monedula.dev/allow-delete
Tenancy policy checks its shape only enforced per namespace
Admission webhooks none optional, off by default
Only here import cluster, doctor status conditions, Kubernetes events, Prometheus metrics

Because env, file and secretKeyRef each work in one runtime only, a KafkaCluster or KafkaUser that uses them resolves in one runtime only. A KafkaCluster with inline credentials resolves in both, with the values in plain text in the manifest. Topics, access policies, quotas and role bindings carry no credentials and work in both, except schema bodies read from files.

The CLI reads an absolute valueFrom.file path as it is. It rejects a relative path that .. takes out of its base: the cluster config directory for credentials and passwords, or the parent of the manifest’s directory for schema bodies, so file: ../schemas/orders-value.avsc still works.