module

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

OSDIST_LIST = [{"Altlinux", "/etc/altlinux-release"}, {"OracleLinux", "/etc/oracle-release"}, {"Slackware", "/etc/slackware-version"}, {"CentOS", "/etc/centos-release"}, {"RedHat", "/etc/redhat-release"}, {"VMwareESX", "/etc/vmware-release"}, {"OpenWrt", "/etc/openwrt_release"}, {"Amazon", "/etc/os-release"}, {"Amazon", "/etc/system-release"}, {"Alpine", "/etc/alpine-release"}, {"Archlinux", "/etc/arch-release"}, {"Archlinux", "/etc/os-release"}, {"SUSE", "/etc/os-release"}, {"SUSE", "/etc/SuSE-release"}, {"Gentoo", "/etc/gentoo-release"}, {"Debian", "/etc/os-release"}, {"Debian", "/etc/lsb-release"}, {"Mandriva", "/etc/lsb-release"}, {"SMGL", "/etc/sourcemage-release"}, {"ClearLinux", "/usr/lib/os-release"}, {"Coreos", "/etc/coreos/update.conf"}, {"Flatcar", "/etc/os-release"}, {"NA", "/etc/os-release"}]

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).

SEARCH_STRING = {"OracleLinux" => "Oracle Linux", "RedHat" => "Red Hat", "Altlinux" => "ALT", "SMGL" => "Source Mage GNU/Linux"}

Class methods

distribution_file_facts(distro_id : String) : Hash(String, String) | Nil

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).
Source
family_for(name : String) : String | Nil

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.

Source
refine_debian(data : String) : Hash(String, String) | Nil

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.

Source