zarf_kubectl
Run a kubectl command through the kubectl zarf carries.
Write it as colonel_byte.zarf.zarf_kubectl. It runs zarf on the node the task is delegated to; nothing is installed on the cluster’s nodes.
Added in colonel_byte.zarf 0.88.0.
Runs zarf tools kubectl with the arguments given, against the cluster a kubeconfig names, and reports what it wrote to standard output.
The module is a compiled binary with zarf linked into it, and zarf vendors kubectl. It needs no zarf and no kubectl on the node, which is what it is for: a management node that drives an air-gapped cluster can read and apply resources without a kubectl of its own.
It is a passthrough and renders nothing into args. Zarf already vendors kubectl and already resolves which cluster to talk to, so projecting kubectl’s flags into Ansible parameters would be reimplementing kubectl in YAML. For declarative resource management prefer kubernetes.core.k8s, which this is not a replacement for.
Parameters
| Parameter | Type | Required | Flag | Description |
|---|---|---|---|---|
args | list of str | yes | None | The kubectl argument vector, as a list: ['get', 'pods', '-A']. A list rather than a command line, because a shell is what splits a command line into words and there is none here. A quoted selector stays one entry. Positional, so it renders no flag. |
kubeconfig | str | no | None | The kubeconfig of the cluster to act on. Zarf has no --kubeconfig flag, so it is passed as KUBECONFIG in the environment the command runs in. kubectl’s own --kubeconfig works too, in args. |
wrapper_binary | str | no | None | The module wrapper to run, resolved on the path when it holds no separator. The action plugin consumes this parameter; the wrapper never sees it. |
parameters | dict | no | None | Further module parameters, merged into the ones given directly. A parameter given both directly and inside parameters is an error naming it. The action plugin consumes this key; the wrapper never sees it. |
Notes
- Set
run_once: trueanddelegate_toon the task. One command runs against the whole cluster, so a play over the cluster’s own inventory would otherwise run it once per host. - The task always reports
changed: true, withzarf.changedSignalset tounknown. The argument vector is kubectl’s, so the module knows the command succeeded and nothing about whether it altered anything. Setchanged_when: falseon a read. - Check mode reports the task as skipped, for the same reason: nothing here can tell a
getfrom anapply. - Standard output comes back as
zarf.output, with its trailing newline removed. Use-o jsonor-o yamlandfrom_jsonorfrom_yamlwhen a playbook has to read the result rather than show it. - A failure comes back as
failedwith kubectl’s own message inmsgand its exit status inzarf.exitCode, including the failures kubectl would normally exit the process over – a cluster it cannot reach is one. - A command kubectl does not have is refused by name before anything runs, rather than printing kubectl’s help and reporting success.
- kubectl plugins are not reachable, deliberately: the handler that resolves them can replace this process with the plugin, or exit it without a result.
Example
- name: Read the nodes of an air-gapped cluster without installing kubectl
colonel_byte.zarf.zarf_kubectl:
args:
- get
- nodes
- -o
- json
kubeconfig: /etc/rancher/rke2/rke2.yaml
delegate_to: localhost
run_once: true
changed_when: false
register: nodes_result
- name: Report how many nodes are ready
ansible.builtin.debug:
msg: "{{ (nodes_result.zarf.output | from_json)['items'] | length }} nodes"
- name: Restart the zarf agent after rotating its certificate
colonel_byte.zarf.zarf_kubectl:
args:
- rollout
- restart
- deployment/agent-hook
- -n
- zarf
kubeconfig: /etc/rancher/rke2/rke2.yaml
delegate_to: localhost
run_once: true