Krikri::PluginHelpers::DistributionFacts
DistributionFacts - the per-distro DISPLAY-NAME logic real Ansible's
DistributionFactCollector applies on top of the generic
/etc/os-release facts, ported from its own
module_utils/facts/system/distribution.py. Pure string logic, no
I/O, so it is unit-testable against a corpus of real os-release
files - see distribution_facts_spec.cr, whose expectations were
generated by running the REAL Python parser over that same corpus
rather than written by hand.
Constants
Real Ansible's distribution-FILE facts: ansible_distribution_file_ {variety,path,parsed} (+ the parse's own distribution/version/
release overrides), from its process_dist_files() walk over
OSDIST_LIST - found missing via cloudalchemy.process_exporter
(round 195): the role's with_first_found list keys a vars file off
{{ ansible_distribution_file_variety | lower }}.yml (→ redhat.yml
on Rocky), and with the keys never set here the template raised
"'ansible_distribution_file_variety' is undefined" where real
Ansible rc=0'd. Ported branch-for-branch (see the follow-up block
below for the walk itself).
Class methods
The walk itself, ported from process_dist_files() + _parse_dist_file():
- SEARCH_STRING names parse ALWAYS (search string absent → distribution = first whitespace token of the file content - this is exactly where real Ansible's ansible_distribution="Rocky" comes from on Rocky, not from the os-release ID);
- OS_RELEASE_ALIAS (Archlinux): content must contain "Arch Linux";
- otherwise a per-name parse function, missing = parse failure (real Ansible's AttributeError → return False);
- first success sets variety/path/parsed and stops; if NOTHING parses the file_* facts stay unset (real Ansible's own behavior - the keys are simply never written).
Names and groupings taken from real Ansible's own OS_FAMILY_MAP (module_utils/facts/system/distribution.py), so the display names #refine_debian now produces ("Linux Mint Debian Edition", "Cumulus Linux", "Devuan", ...) still map to the right family - none of them is an os-release ID, so they would otherwise fall through to ID_LIKE, or to the distribution name itself.
Real Ansible's own parse_distribution_file_Debian, ported branch
for branch and IN ITS ORDER - the order is load-bearing, since
several of these substrings co-occur in one /etc/os-release (LMDE's
own file mentions linuxmint.com, Kali's mentions Debian), and real
Ansible's first matching branch wins.
Real Ansible reports a per-distro DISPLAY NAME here, not the
capitalized os-release ID this engine used to emit: on LMDE 7 it
says "Linux Mint Debian Edition" where this said "Linuxmint", and
on Raspbian it says "Debian" where this said "Raspbian". A role
gating on ansible_distribution == "Linux Mint", or keying a vars
file off it, took the wrong branch on every derivative.
Returns the facts to OVERRIDE (never mutating the caller's own
differently-typed fact hash), or nil for real Ansible's own
return False - no branch matched, and the generic os-release
name the caller already computed stands.
Several branches deliberately reproduce quirks of the Python
original rather than "fixing" them, because parity is the goal
and a role may already depend on them: the release regexes use a
negated character class with no MULTILINE anchor, so [^"]+ runs
PAST the end of its own line (real Ansible's Deepin
distribution_release is literally "apricot\nID=Deepin\n
ID_LIKE=debian\n"). Crystal's regex engine behaves the same way
here, which the corpus differential confirms rather than assumes.