all: document the shared-value role trap - #310
Merged
Merged
Conversation
ideaship
force-pushed
the
docs-groupvars-guidance
branch
3 times, most recently
from
September 12, 2026 11:03
e4fa040 to
faa00a0
Compare
The 2026.1 mirror re-sync shipped two regressions of the same shape, and this file did not describe that shape. Both are fixed -- #307 and #309 -- so record what they have in common while it is concrete. all/ is one tree serving every supported release, but each release's roles come from its own kolla-ansible image. When upstream changes a value and the code that reads it in one commit, mirroring the value alone splits the pair: the new value meets the old consumer. The README described the case where a value must differ by release; it did not say why, and it did not cover the variant that survives the usual check. openstack_auth is the first shape -- the meaning moved, since 2026.1 reads five of the six keys from a clouds.yaml older releases do not have. designate_backend_external is the second: "no" became false, the truth value was preserved, and every boolean-equivalence check therefore called it inert, while the older role compares against the string and false == 'no' is False. Note "no" is truthy on its own; it is | bool that makes the two agree. So state the rule: a notation change is inert only if every consumer's behaviour is preserved. Search the older releases' roles for a comparison against the key and evaluate it against both values. Document two further things that cost time in that investigation: - Resolving a variable by hand needs the filter-plugin path, the vault secrets and the site inputs. Each missing piece fails differently, and a missing secret prints VARIABLE IS NOT DEFINED! for a key that is defined. The result is also synthetic -- every -e replaces a real input -- and a NOT DEFINED cannot distinguish an undefined key from an undefined dependency; the raw definition settles that, which is what ansible-inventory --host is good for. - A resolved value proves delivery, not consumption. om_rabbitmq_qos_prefetch_count resolves on every release and, under OSISM's default profile, reaches no config file at all. Add a worked example for gating a non-scalar value, using the openstack_auth gate, with the note that sync-mirror's --retain cannot verify one: it parses only quoted scalar literals, so such a key takes --retain-unverified. Drop the parenthetical naming the supported range in Where a variable goes. It was stale before this branch touched it, and naming a range that moves every release would only go stale again. The file already says the range is derived rather than declared -- check-drift.py globs latest/openstack-*.yml in osism/release -- so point there instead, the way the openstack_release note two sections up points at 001-common.yml. Assisted-by: Claude:claude-opus-5 Signed-off-by: Roger Luethi <luethi@osism.tech>
ideaship
force-pushed
the
docs-groupvars-guidance
branch
from
September 14, 2026 08:08
faa00a0 to
5f37173
Compare
ideaship
marked this pull request as ready for review
September 14, 2026 08:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Documentation only —
all/README.md. No behaviour change, no variable touched.Why
The 2026.1 mirror re-sync shipped two regressions of the same shape, and this
file did not describe that shape:
openstack_authlostauth_urlon every release below2026.1; keystone registration failed on four testbed lanes.
designate_backend_externalwent from"no"tofalse; bind9 stopped being configured below 2026.1.Both are fixed. This records what they have in common, while it is concrete.
The gap being filled
all/is one tree serving every supported release, but each release's rolescome from its own kolla-ansible image. So when upstream changes a value and
the code that reads it in the same commit, mirroring the value alone splits the
pair — the new value meets the old consumer.
The README already said the detector cannot catch "a value that must differ by
release". It did not say why, and it did not describe the variant that is
easy to miss:
openstack_authclouds.yamlolder releases do not havedesignate_backend_external"no"→false)falseunder| bool, so every boolean-equivalence check calls it inert — but the older role compares against the string, andfalse == 'no'isFalse. (The bare string"no"is truthy; it is the filter that makes them agree.)So the new text states the rule: a notation change is inert only if every
consumer coerces. Search the older releases' roles for a literal comparison
against the key, and evaluate it against both values rather than stopping at
the match. Of the three keys that matched in the 2026.1 sweep, only one
inverted.
Also documented
Two things that cost real time during the investigation:
recommends. An ad-hoc
ansible … -m debug -a "var=…"has no filterplugins, no vault and no site inputs. Each missing piece fails differently,
and a missing secret prints
VARIABLE IS NOT DEFINED!for a key that isdefined — the opposite of the truth. The working invocation and the three
failure modes are now written down.
om_rabbitmq_qos_prefetch_countresolves on every release and is renderedinto no config file at all, because the template that would emit it sits
behind a guard OSISM turns off.
Plus a worked example for gating a non-scalar value (the
openstack_authgate from #307), including the caveat that
sync-mirror's--retaincannotverify a mapping-valued gate today — it only parses quoted scalar literals, so
such a gate takes
--retain-unverified.Scope
Guidance, not an incident write-up. The two regressions appear as one clause
each with a PR reference; the forensics stay in the PRs. Deliberately not
covered here: where to read an effective deployed value on a live cluster —
that is diagnosis workflow rather than
group_varslayering, and stating itcorrectly needs more caveats than it earns in this file.
Drive-by
Where a variable goes named the supported range in a parenthetical, and it
was stale — it still said 2024.1–2025.2. Rather than update it to a value that
moves every release, the parenthetical is gone: the file already states that
the range is derived, not declared (
check-drift.pyglobslatest/openstack-*.ymlinosism/release), so this now points there, the waythe
openstack_releasenote two sections up points at001-common.yml.🤖 Generated with Claude Code