module

Krikri::PluginHelpers::DnfInstallFailures

Shared parser for dnf/yum (dnf4-backend) install-failure output, turning the CLI's own stderr/stdout text into Ansible's dnf-module failures list (observed live on Rocky, dnf 2.19 backend):

"Error: Unable to find a match: redhat-lsb-core" and "No match for argument: redhat-lsb-core" become "No package redhat-lsb-core available."

"All matches were filtered out by modular filtering for argument: mysql-devel" becomes "mysql-devel All matches were filtered out by modular filtering for argument: mysql-devel"

(Ansible prefixes the modular-filtering line with the spec; a missing-spec entry is its own canned wording, not the dnf line.)

Ansible emits one failures entry PER REQUESTED SPEC, in request order, duplicates kept (observed live: cloud3rsio.phpbuild lists libmcrypt-devel twice and real Ansible reported 11 entries where krikri reported 10) - dnf itself only prints each missing spec once, so when the caller passes requested the parsed entries are re-expanded against that list. Without requested the parsed entries are returned deduped, as callers that can't supply the request list have always seen.

Returns nil when nothing in the output matches any known failure line (repo-metadata/404 class errors), so the caller can keep its pre-existing raw-output failure shape instead of guessing.

Constants

DNF_DEPSOLVE_EMPTY_FAILURE_ORDER = ["changed", "msg", "rc", "results", "failed"] of ::String

Ansible-core 2.21's dnf module wrapper re-reports the backend script's failure through fail_json(msg=, results=, rc=) whenever that script's failures list is EMPTY, so the key is absent entirely: alphabetical changed/msg/rc/results with the controller-appended failed trailing. A bare depsolve error (curl against the installed curl-minimal, gremid.clojure in round29902238) never marks a spec unresolvable, so it lands here

  • live-confirmed against ansible-core 2.21.6 on Rocky 9 (issue #989).
DNF_DEPSOLVE_FAILURE_ORDER = ["changed", "failures", "msg", "rc", "results", "failed"] of ::String

Ansible's observed depsolve-failure key order (live on Rocky, dnf4 backend): alphabetical - changed, failures, msg, rc, results - with no stderr key, and the controller-appended failed trailing like every other registered order. Only a depsolve that still carries per-spec entries gets here (the missing-spec-then-depsolve combination of issue #321); a depsolve error on its own has no failures key at all.

DNF_INSTALL_FAILURE_ORDER = ["msg", "failures", "results", "rc", "failed"] of ::String

Ansible's module failure key order for a transaction that failed to install some of the requested packages - no stderr key.

DNF_METADATA_FAILURE_ORDER = ["changed", "msg", "rc", "results", "failed"] of ::String

Ansible's observed repo-metadata-failure key order (live on Rocky, dnf4 backend): alphabetical - changed, msg, rc, results - with neither a stderr key NOR a failures key (the module's metadata-download except block does a bare fail_json(msg=, rc=1)

  • a metadata failure carries no per-spec failure list), the controller-appended failed trailing like every other registered order (issue #267).

Instance methods

depsolve_failure_msg(output : String) : String | Nil

Ansible's dnf module catches the libdnf DepsolveError and fails with "Depsolve Error occurred: " + str(exception), which is the whole "Problem: ..." block (every "- ..." detail line) and not the CLI's trailing "(try to add '--allowerasing' ...)" hint (issue #60).

Source
group_not_available_msg(output : String) : String | Nil

Ansible's dnf module resolves a requested GROUP spec (a leading @) against the comps data BEFORE any transaction and, when the group/environment is unknown, raises its own "No group <spec> available." (group_spec is name[1:].strip) via a fail_json whose empty failures list is dropped - so the result is msg/results/rc only, no failures key. dnf's own CLI names the same condition differently ("Module or Group '<name>' is not available." then "Error: Nothing to do.", exit 1), so a group the repos don't define used to fall through to the generic "Failed to install packages" raw-output dump instead of matching ansible (issue #958, AAROC.CODE-RADE-container). dnf prints one line per unknown group; ansible raises on the first, so the first wins.

Source
missing_specs_from_failures(failures : Array(String)) : Array(String)

Issue #321 (Rocky 9): ansible's dnf module marks every requested spec the repos can't name into failures FIRST, then STILL depsolves the survivors - a DepsolveError there (libcurl against the installed libcurl-minimal) fails the task with the depsolve msg AND that per-spec failures list, while the CLI aborts at the missing spec before ever reaching that depsolve. Only THIS exact canned wording names a spec worth re-trying without: the modular-filtering form carries its own different verdict, so those specs stay in the batch.

Source
parse_dnf_install_failures(stdout : String, stderr : String, requested : Array(String) | Nil = nil) : Array(String) | Nil
Source
repo_metadata_failure_msg(output : String) : String | Nil

Ansible's dnf module reports a repo-metadata download failure (the repo's repodata/repomd.xml 404s) as JUST libdnf's own error text - its "Failed to download metadata for repo 'x': ..." summary line with dnf's "Error: " prefix stripped (issue #267)

  • and NOT the per-spec failures shape above: a metadata failure carries no failures list at all. The compound dnf ... || yum ... prints the line once per package-manager binary (yum's retry replays the identical failure against the same dead repo), so only the first hit - the task's own dnf attempt - is what ansible's msg holds.
Source
specs_without_missing(specs : Array(String), failures : Array(String)) : Array(String)

The batch that still depsolves what ansible depsolved: the requested specs minus the ones the repos can't name, so a --assumeno re-run can surface the Problem block the first missing-spec abort hid.

Source