Runner CLI¶
runner is the program inside every CAPTF Job. The manager does not run Terraform or OpenTofu itself: it creates a Job, and the runner in that Job prepares the working directory, runs the module’s runtime step by step, and writes a small JSON result that the manager reads back when the Job ends. The binary is part of the manager image (/runner).
You never start the runner by hand in normal use. The manager builds the Job so that:
- An init container, from the manager image, runs
/runner copy /captf/bin/runner. This puts a copy of the binary on a shared volume, so the module’s own image does not need to contain it. - The main container, from the module’s source image, runs
/captf/bin/runner runwith the flags for one operation.
Run it yourself only to reproduce a failed Job in a container you control, or to read its flags while debugging a Job spec. See the image contract for the paths the runner expects and Choosing the Operation for when the manager picks each operation.
Synopsis¶
runner [global flags] copy <dest>
runner [global flags] run --op=<op> [flags]
runner [global flags] version
runner --version[=raw]
A bare runner prints its usage to standard error and exits with code 2.
Global flags¶
Every subcommand accepts these. They are the logging and version flags that every Kubernetes component registers, so they behave as they do in kube-apiserver or kubectl.
| Flag | Type | Default | Description |
|---|---|---|---|
--feature-gates | key=value,... | Enable alpha or beta logging features. The gates are AllAlpha, AllBeta, ContextualLogging, LoggingAlphaOptions and LoggingBetaOptions. | |
--log-flush-frequency | duration | 5s | Longest interval between log flushes. |
--log-json-info-buffer-size | quantity | 0 | Alpha. Buffer info messages in JSON format with split streams. 0 disables buffering. Needs the LoggingAlphaOptions gate. |
--log-json-split-stream | bool | false | Alpha. In JSON format, write errors to standard error and info messages to standard output. Needs the LoggingAlphaOptions gate. |
--log-text-info-buffer-size | quantity | 0 | Alpha. The same buffering for text format with split streams. |
--log-text-split-stream | bool | false | Alpha. The same stream split for text format. |
--logging-format | string | text | Log format: text or json. The json format needs the LoggingBetaOptions gate, which is on by default. |
-v, --v | Level | 0 | Log verbosity. |
--version | version | false | Print version information and exit. --version=raw prints the full build information. --version=vX.Y.Z sets the reported version. |
--vmodule | pattern=N,... | Per-file verbosity. Works with the text format only. |
Invalid logging flags fail with exit code 2. For run, they also write a result (see Result error kinds).
copy¶
Copies the running binary to <dest> and sets it executable (mode 0755). <dest> is the one required argument and takes no flags. The Job’s init container uses it to place the runner at /captf/bin/runner.
It exits 0 on success, 1 when it cannot read or write a file, and 2 when it does not get exactly one argument.
run¶
Runs one operation in the Job’s main container. It takes no arguments, only flags. --op is required, and takes one of these:
| Operation | What the runner does |
|---|---|
apply | Runs init, validate, then apply. With --guard-deletes or --expect-plan, it plans first, checks the plan, and applies the saved plan only when the checks pass. |
destroy | Runs init, then destroy. |
refresh | Runs init, then a refresh-only apply to update state from the real resources. |
drift | Runs init, a refresh-only apply, then a plan without refresh, and reads the plan to report whether anything differs. |
plan | Runs init, validate, then plan, and summarizes the plan for review. Nothing is applied. |
restore | Runs init, then pushes a state backup assembled from <config>/restore and lists the result as a check. |
Every operation runs init first, with -backend-config values from --backend-config and the lock timeout from --lock-timeout. When --force-unlock is set, force-unlock runs right after init.
The result goes to --result when the run ends, whether it succeeded or not.
Paths and environment¶
| Flag | Type | Default | Description |
|---|---|---|---|
--bin | stringArray | /captf/runtime | The runtime command, one flag per element. Repeat it to pass a command with arguments. |
--config | string | /captf/config | Directory with the rendered root module and tfvars: the mount of the per-run Secret. |
--module | string | /captf/module | The module directory. |
--providers | string | /captf/providers | The provider mirror directory. Optional. |
--workdir | string | /captf/work | The writable work directory. |
--image | string | The source image reference, echoed in the result. | |
--result | string | /dev/termination-log | Where to write the result. |
Runtime behavior¶
| Flag | Type | Default | Description |
|---|---|---|---|
--op | string | The operation: apply, destroy, refresh, drift, restore or plan. Required. | |
--backend-config | stringArray | A value for init -backend-config. Repeatable. | |
--lock-timeout | duration | 5m0s | How long a step waits for the state lock. |
--stop-timeout | duration | 1m0s | How long an interrupted step has to stop before the runner sends it SIGKILL. |
--force-unlock | string | A stale lock ID to force-unlock after init. |
Approval and plan checks¶
| Flag | Type | Default | Description |
|---|---|---|---|
--guard-deletes | bool | false | For apply: stop before a plan that deletes or replaces a resource, unless --allow-deletes-hash equals --inputs-hash. |
--inputs-hash | string | The hash of the inputs the Job renders. An approval of a destructive plan must name it. | |
--allow-deletes-hash | string | The hash approved for a destructive plan. | |
--expect-plan | string | For apply: the approved plan hash. Stops with error kind plan-changed unless the plan’s hash matches. | |
--plan-key-file | string | /captf/plan-key/key | For plan and an approved apply: the file with the key of the plan fingerprint. Both fail when it cannot be read. |
See The Destructive-Plan Guard and Manual Plan Approval for how the manager sets these.
Restore and events¶
| Flag | Type | Default | Description |
|---|---|---|---|
--restore-chunks | int | 0 | For restore: the number of backup chunks under <config>/restore. |
--restore-resources | int | 0 | For restore: the backup’s count of managed resources. When it is not 0, state list must show at least one. |
--event-object | string | Emit progress events about this object, as <apiVersion>/<kind>/<namespace>/<name>/<uid>. No events when unset. | |
--job-name | string | The Job the events relate to. |
Example¶
A plan Job for a cluster, as the manager would start it, trimmed to the flags that matter:
/captf/bin/runner run \
--op=plan \
--image=registry.example.com/acme/cluster:v1.2.0 \
--inputs-hash=<inputs-hash>
<inputs-hash>is the hash the manager computed for the inputs it rendered into--config.
The manager supplies the rest through the defaults above and the mounts it builds. A run that finishes writes its result to the container’s termination log, which the manager reads from the Pod status.
version¶
Prints the program name and its build information, then exits 0. runner --version=raw prints the full build information instead.
Exit codes¶
| Code | Name | Meaning |
|---|---|---|
0 | ExitOK | Every step succeeded, or an apply’s plan had no changes to apply. |
1 | ExitFailure | A step failed, was interrupted, stopped before a destructive plan (blocked), or found that its approved plan had changed. Also returned when preflight or preparation fails, or when the result cannot be written. When the failing step has its own exit code of 1 or more, the runner returns that code. |
2 | ExitUsage | Bad input: an unknown --op, a bad flag, unexpected arguments or invalid logging flags. |
Result error kinds¶
runner run always writes a result document, to --result (the termination log by default). A successful run has error: null. A failed run carries an error object with a kind, the step that failed and a bounded tail that summarizes the failure. The kind is one of:
| Kind | Meaning |
|---|---|
image-layout | The image does not follow the image contract: the module or runtime is not where the contract puts it. Fix the image. |
step | A runtime step (init, plan, apply and so on) failed, or the runner’s own setup failed, such as preparing the work directory or assembling a restore. A bad flag also reports this kind, with step flags. |
interrupted | The Job was canceled while a step ran, for example by a drain, an eviction or a deletion. It does not count toward retry backoff. |
blocked | A guarded apply stopped before a plan that deletes or replaces resources, because no approval names the inputs hash. It changed nothing, and the manager does not retry it until the inputs or the approval change. |
plan-changed | An apply approved for one plan (--expect-plan) found a different plan. It changed nothing, carries the new plan and waits for it to be approved. |
Results are small by design
The kubelet truncates a termination message at 4096 bytes. The runner drops optional detail, such as the plan’s resource list, before it drops the counts and hashes the manager needs. The full output of every step is in the Pod log.