Ansible
Configuration management, roles, collections and awkward targets.
Posts
Taking the Talos collection from a green test cluster to the live one: the drift a read-only check showed, three bugs only production could find, and a feature I moved and then deleted because Flux already did it.
I wanted real-cluster tests for an Ansible collection that drives Talos. On my machine neither Docker nor QEMU would give me a node in maintenance mode, so I tested the rendering instead: fixtures, talosctl validate, determinism and negative cases. What it caught, and the five CI runs it took to go green.
Notes
An old NAS with Python 3.5 is a raw-only Ansible target. Everything then goes through a busybox shell that discards background jobs, reports success regardless, and has to be verified by its side effects.
The ansible pip package already ships its collections. Installing them again into the project directory puts newer copies first on the collections path, silently replacing the versions you froze.
If one task sets check_mode itself, the command line flag no longer reaches it, and ansible-playbook --check -e apply=true mutates for real. Fold ansible_check_mode into the variable the task uses.
The API server rewrites stringData into data, so kubernetes.core.k8s sees a difference each time. Use data with b64encode. Also: omit does not work inside a nested definition, so merge optional keys with combine.
A regex written as '\\s' inside a >- block never matched, so every node in my upgrade role looked outdated. Backslashes are literal in folded and literal scalars; double them only in double-quoted strings.
Merging the same Talos context twice renames it to name-1 and makes it current; talosctl kubeconfig --merge issues a new client certificate on every call. How to add a cluster to your default configs from automation without surprises.
The dry run prints its summary and diff to stderr, no drift is the text No changes, and a regex that anchors at the start of the string makes a role re-apply every node every run. Plus how to find what forces a reboot, and why failed applies must never be logged.
ansible -m command -a with docker ps --format {{.Names}} fails, because Ansible runs the argument through Jinja before the shell ever sees it. Wrap the Go template in a raw block.
A leftover state file makes Molecule report "instances already prepared" and skip the wipe. Run molecule reset first. Also: a cold start can outlast a 15 minute health gate.
Encrypt one value with ansible-vault encrypt_string into its own small vars file, so the big encrypted vault stays untouched, and prove nothing changed by comparing hashes per host.