correctly reported, misread
Skipped, Not Broken: What "12 of 15 Hosts Skipped" Actually Meant
TL;DR: An Ansible task built to generate DNS rewrites for every host in
inventory reported most of the fleet as "skipped." The task wasn't malfunctioning —
it was correctly detecting that most hosts had no meaningful hostname to build a
record from in the first place, because they were defined in inventory.ini as
bare IP addresses rather than named aliases.
The symptom
A task meant to add a DNS rewrite for every lab host, driven by
hostvars[item].ansible_host, produced output like this across most of the fleet:
skipping: [10.0.1.130] => (item=10.0.2.1.hartwelg.com -> skipped)
skipping: [10.0.1.130] => (item=10.0.1.10.hartwelg.com -> skipped)
...
skipping: [10.0.1.130] => (item=k3s-master.hartwelg.com -> 10.0.1.20)
Twelve entries showed a nonsense domain — an IP address with .hartwelg.com
stapled onto it — and no resolved answer. Three showed a real hostname and a real
resolved IP.
Diagnosis
The task's own when: hostvars[item].ansible_host is defined condition was doing
exactly its job: for the twelve failing entries, item was itself already a bare
IP string ("10.0.2.1"), because that's literally how those hosts were written in
inventory.ini — no separate name, no ansible_host= assignment. Building
{{ item }}.hartwelg.com from that input produces a domain that's just an IP
address with a suffix, and since no ansible_host fact exists separately for those
entries, the condition correctly evaluated false and skipped them.
The three working entries — k3s-master, k3s-worker, thinclient — had already
been defined with a real alias and a separate ansible_host= value, the only
format the task was actually built to handle.
Root cause
The automation assumed every host in inventory had both a friendly name and a separate IP, because that happened to be true for the three hosts used to build and test it. It was true for 3 of roughly 15. The rest of the fleet had never been given that structure at all — this wasn't a bug in the DNS rewrite task, it was a gap in what the inventory itself provided for it to work with.
Fix
Converted the remaining bare-IP entries in inventory.ini to the same
name ansible_host=IP format already working for the three good examples:
[gitlab]
gitlab ansible_host=10.0.1.10
[vault]
vault ansible_host=10.0.1.80
Before renaming anything, checked for existing references to each host by its
current bare-IP identity as an actual Ansible target — hosts:, delegate_to:,
hostvars[...], a habitual --limit — since those would break the moment the
inventory name changed, distinct from places the same IP was used as plain
configuration data (a curl target, a sonar.host.url value), which are unrelated
strings and unaffected by renaming Ansible's own notion of the host:
grep -rn "10\.0\.1\.10" --include="*.yml" .
Each renamed host was tested individually with --check --diff before trusting the
rename across the whole fleet at once.
What this demonstrates
"12 of 15 skipped" read, at a glance, like a bug report. It was actually the task correctly reporting that most of its inputs didn't contain what it needed — a distinction that mattered, because the fix wasn't in the task's logic at all, it was in the data being fed to it. Reading exactly what the skip condition was actually checking, rather than assuming the automation was broken, turned this from "why isn't this working" into a much narrower, more accurate question: "why do most of these hosts have no name to work with." That's also the kind of gap that tends to be invisible until something downstream actually tries to use the missing structure — the inventory had worked fine for every other purpose in this build right up until a task needed a real hostname to build something from.