Skip to content

Submitting a Folder of Manifests (CLI)

You have a folder of Kubernetes manifests and want it to become a stack’s desired state — from your shell or a CI job, without writing any code. The brokkr CLI does this with one idempotent command.

  • The brokkr binary on your PATH (download the Linux or macOS tarball for your architecture from the GitHub Release, or build it from source with cargo build --release -p brokkr-cli).
  • A reachable broker and a PAK. A tenant PAK applies for its own tenant: that tenant owns the stack. An admin PAK can apply too, but it must name the tenant that owns the stack with --generator (the API calls a tenant a generator; see Apply as an admin). To mint a tenant PAK, see Create the tenant or Working with Generators.

Create ~/.brokkr/config so you don’t repeat the broker URL and PAK on every call:

broker_url = "https://broker.example.com"
pak = "brokkr_BRabcd1234_GeneratorTokenExample0001"

The /api/v1 suffix is added for you. Any value here can be overridden per-invocation with --broker-url / --pak, or supplied instead via BROKKR_BROKER_URL / BROKKR_PAK (handy in CI, where the PAK comes from a secret). Precedence is flag → environment → config file.

Terminal window
brokkr apply -f ./manifests --stack payments

This reads the top-level *.yaml/*.yml files in ./manifests (sorted), concatenates them into one multi-document stream, validates that each document has apiVersion and kind, and submits the bundle as the stack’s latest deployment object — creating the stack payments if it doesn’t exist. You’ll see one of:

created stack "payments": first revision (sequence 1)
updated stack "payments": new revision (sequence 2)
unchanged: stack "payments" already current

An admin PAK has no tenant of its own, so it cannot own a stack. Name the owner tenant with --generator, by name or by id:

Terminal window
brokkr apply -f ./manifests --stack payments --generator acme-payments

The stack is created under that tenant, and the PAK of that tenant can manage it from then on. Without --generator, an admin PAK gets:

error: invalid request: apply with an admin PAK needs the generator that owns the stack: give its name or id as `generator` (`--generator` in the brokkr CLI)

With a tenant PAK, --generator is optional. If you give it, it must name the tenant of that PAK: a tenant cannot apply for another tenant.

Add one or more labels so only matching agents reconcile the stack:

Terminal window
brokkr apply -f ./manifests --stack payments \
--target-label env:prod \
--target-label region:us

Labels are additive and applied every run; a label that already exists is left as-is.

--target-label is label-based fan-out: any agent whose labels match reconciles the stack — but only if that agent is registered with the tenant that owns it. Registration is the tenant consent boundary and it gates both targeting paths:

  • Label and annotation matching is filtered at read time. An agent that never registered with your tenant is served nothing, however its labels are set, and no error is raised anywhere — the stack simply doesn’t arrive.
  • Explicit per-agent targets (POST /agents/{id}/targets, created by an admin or by the tenant that owns the stack) are rejected outright with HTTP 403 / agent_not_registered when the agent isn’t registered.

So register the agents you intend to reach before you rely on labels: brokkr register --agent <id> --generator <tenant-id> with an admin PAK, or set BROKKR__AGENT__GENERATOR_IDS on the agent at startup so it self-registers. See Registering agents with generators and the error code reference.

apply is idempotent — it compares a checksum of the bundle against the stack’s current latest deployment object and submits a new revision only when the folder changed. That makes it safe to run on every push. A complete workflow around this one command is in CI/CD with Generators, Step 7:

Terminal window
BROKKR_BROKER_URL="$BROKER_URL" BROKKR_PAK="$BROKKR_GENERATOR_PAK" \
brokkr apply -f ./k8s --stack "$SERVICE_NAME" --target-label env:prod

A successful run exits 0 (including the unchanged case); any failure prints error: … to stderr and exits 1, so a failed apply fails the job.

A stack’s desired state is the single latest bundle, and the agent prunes anything no longer present. To delete a resource, remove its file from the folder and re-apply — the next reconcile deletes it from the cluster. Object ordering within the folder doesn’t matter: the agent front-loads Namespace and CustomResourceDefinition objects.