FIX: keep the app's target when pushing a per-node setting

For a setting saved for a single node, push_pillar replaced the app's
target from pillar_push_map.yaml with the node id. The app's state was
then applied to that node even if the node does not run the app.

Seen in the lab: the SOC config test saves
elasticsearch.config.cluster.routing.allocation.disk.threshold_enabled
for the first node SOC lists, and SOC lists nodes in random order. When
that node was a sensor, the elasticsearch state was applied to it and
failed to render (so_roles has no so-sensor entry), and so-push-drainer
logged "push failed".

Narrow the app's target to the node instead of replacing it:
"L@<node> and ( <app target> )". A node outside the app's target then
matches nothing, and so-push-drainer skips the action.
This commit is contained in:
Josh Patterson committed 2026-11-11 10:07:08 -05:00
1 parent 22a4acbb5a
commit cc970892ed
1 file changed
+6 -4
+6 -4
View File
@@ -7,7 +7,7 @@
# Two branches, keyed on node_id:
# A) node_id populated -> the change is scoped to that one minion. Look up the
# app in pillar_push_map.yaml and write an intent that runs the app's mapped
# state(s) targeted to just that node.
# state(s) on just that node, and only if the node is in the app's target.
# B) node_id empty -> grid-wide app change. Look up the app in
# pillar_push_map.yaml and write an intent with the entry's actions as-is.
#
@@ -116,15 +116,17 @@ def _app_from_setting(setting_id):
def _node_actions(entry, node_id):
# Copy the app's mapped actions but retarget each one to the single node.
# Copy the app's mapped actions but narrow each one to the single node.
# Preserves the state/highstate selection and any batch/batch_wait overrides.
# The app's own target is kept so the state is not applied to a node that does not
# run the app (e.g. an elasticsearch setting saved for a sensor fails to render there).
actions = []
for action in entry:
if not isinstance(action, dict):
continue
node_action = dict(action)
node_action['tgt'] = node_id
node_action['tgt_type'] = 'glob'
node_action['tgt'] = 'L@{} and ( {} )'.format(node_id, action.get('tgt', '*'))
node_action['tgt_type'] = 'compound'
actions.append(node_action)
return actions