Add automatic ascender_stats_* job artifacts (changed/failed flags and host lists)#562
Add automatic ascender_stats_* job artifacts (changed/failed flags and host lists)#562fernandorocagonzalez wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds automatic awx_stats_* job artifacts derived from the final playbook_on_stats event so downstream workflow nodes (and conditional connectors) can branch on “changed/failed” outcomes and (optionally) per-host lists without requiring set_stats in playbooks.
Changes:
- Compute and merge automatic
awx_stats_*artifacts onplaybook_on_stats, withset_statsvalues taking precedence on key collisions. - Introduce settings/API configuration for enabling the feature and capping host list size (
AWX_ENABLE_TEMPLATE_STATS,AWX_AUTO_STATS_MAX_HOSTS), plus per-job/workflow extra-var overrides. - Add unit tests and workflow documentation describing the new artifacts and settings.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| docs/workflow.md | Documents the new automatic awx_stats_* artifacts and how they propagate through workflows. |
| awx/settings/defaults.py | Adds default values for AWX_ENABLE_TEMPLATE_STATS and AWX_AUTO_STATS_MAX_HOSTS. |
| awx/main/tests/unit/tasks/test_runner_callback.py | Adds unit tests for stats artifact computation, truncation behavior, enable/disable logic, and merge precedence. |
| awx/main/tasks/callback.py | Implements stats artifact computation and merge into job artifacts during playbook_on_stats. |
| awx/main/conf.py | Exposes the new settings via the settings registry (Jobs category) with labels/help text. |
|
Just an FYI, new variable names should probably include ascender instead of awx. Eventually its on the roadmap to change the name of most of the variables to expunge the awx name completely from the codebase. |
|
Yes that was something I thought, since I saw there was already an ongoing effort to change references but was unsure. Will do |
Every finished playbook job (jobs launched from job templates; project updates, inventory syncs and ad hoc commands are not affected) now automatically contributes a set of ascender_stats_* keys to its artifacts, computed from the final playbook_on_stats event without requiring set_stats in the playbook: - ascender_stats_changed / ascender_stats_failed booleans (failed includes unreachable hosts, matching the job event semantics) - ascender_stats_changed_hosts / ascender_stats_non_changed_hosts / ascender_stats_failed_hosts / ascender_stats_non_failed_hosts sorted host lists - ascender_stats_hosts_truncated, set when the play involved more hosts than ASCENDER_AUTO_STATS_MAX_HOSTS (default 100), in which case the host lists are omitted so artifacts stay small as they propagate through workflows; the boolean flags are always kept Since these are regular artifacts, they propagate to descendant workflow nodes as extra vars and can drive conditional workflow connectors (requested in ctrliq#505: traverse a path only when the previous job reported changes). Keys set by the playbook via set_stats win over the automatic ones on collision, and _ansible_no_log redaction is unaffected. The feature is gated by the ASCENDER_AUTO_STATS_ENABLED setting (default true); both settings are exposed in the settings API (Jobs category) and can be overridden per job or per workflow with extra variables of the same name, resolved at the single per-job stats event so the event handler hot path is untouched. A negative max hosts override through extra vars is ignored in favor of the setting, which is itself validated with min_value=0.
Every playbook job now emits the same ascender_stats_* key names, so aggregating artifacts with plain dict.update() let the last finished sibling mask the others: with a sliced job template, a failed host reported by slice 1 disappeared if slice 2 finished clean afterwards, so a conditional connector on ascender_stats_failed would not fire and the per-host lists passed downstream were wrong. The same applied to nested workflows and to several parents converging into one child. The ascender_stats_* keys are now merged where sibling artifacts meet (WorkflowJob.get_effective_artifacts and the ancestor artifacts built in get_job_kwargs): booleans are OR-ed and the host lists unioned, with truncation on any side dropping the merged lists. Everything else keeps last-writer-wins, and within a single branch a node's own output still supersedes what it inherited.
77b28af to
f20bd3e
Compare
|
Done. All the new names now use the ascender prefix: the artifact keys are While at it I also addressed the review remarks: a negative |
Summary
Related to #505, where @cigamit asked for a "Changed" connector ("only traverses the path if something reported as changed in the playbook before it, or maybe only the hosts that reported as change traverse"). Complementary to #561.
Every finished playbook job (jobs launched from job templates; project updates, inventory syncs and ad hoc commands are not affected) now automatically contributes a set of
ascender_stats_*keys to its artifacts, computed from the finalplaybook_on_statsevent — noset_statsneeded in the playbook:ascender_stats_changedtruewhen any host reported a changeascender_stats_failedtruewhen any host failed or was unreachableascender_stats_changed_hosts/ascender_stats_non_changed_hostsascender_stats_failed_hosts/ascender_stats_non_failed_hostsascender_stats_hosts_truncatedtruewhen the host lists were omitted (see below)Because these are regular artifacts, everything that already works for
set_statsdata works for them:ascender_stats_changed == truetraverses only when the previous job actually changed something — and the same primitive covers failed/unreachable/per-host variations.Configuration
ASCENDER_AUTO_STATS_ENABLED(defaulttrue): master switch, exposed in the settings API (Jobs category).ASCENDER_AUTO_STATS_MAX_HOSTS(default100): when a play involves more hosts than this, the four host name lists are omitted (andascender_stats_hosts_truncatedset) so artifacts stay small as they accumulate throughancestor_artifactsin long workflows; the boolean flags are always kept.Both can be overridden per job or per workflow with extra variables of the same name (workflow extra vars reach every spawned job), e.g. disable the feature for one noisy workflow, or raise the host cap only where the lists are needed. A negative
ASCENDER_AUTO_STATS_MAX_HOSTSoverride through extra vars is ignored in favor of the setting, which is itself validated withmin_value=0.Implementation notes
RunnerCallback.event_handler: the automatic keys are merged into the samedelay_update(artifacts=...)used forset_statsdata, so there is no second writer racing on theartifactsfield. Keys set by the playbook viaset_statsalways win on collision, and_ansible_no_logredaction is unaffected.failures+dark), the same computationJobHostSummaryis built from.event_handler) is untouched.ascender_stats_*keys are merged instead of last writer wins: booleans get OR-ed and the host lists unioned, so a failed host reported by slice 1 is still visible after a clean slice 2 finishes. If any side was truncated the merged lists are dropped. All other artifact keys keep the usual update semantics.Test plan
test_runner_callback.py: stats computation, truncation, enable/cap resolution (setting vs extra var, string coercion, negative override),set_statsprecedence on merge, non-job callbacks unaffected.test_workflow_unit.pyfor the sibling merge (boolean OR, host list union, truncation, one-sided keys, plain keys untouched).tasks/, functionalapi/test_settings.py(one pre-existing failure onmainunrelated to this change),models/test_job.py,models/test_workflow.py,awx/conf/tests.