fix(ansible): git sources work in the image and survive a redeploy; pulls time out; alert vars go in a JSON file (#5157)
- git ships in the image; checkouts live under /data/ansible/sources (STEWARD_ANSIBLE_SOURCE_DIR), on the persistent volume. - One task, ansible_git_pulls, reads the sources every 30 s and pulls each as its interval passes: a source added in Settings is pulled without a restart, a removed one is forgotten. - git_pull: a 120 s timeout ending the process group, GIT_TERMINAL_PROMPT=0, pull --ff-only, a failed clone removed; it raises GitPullError with git's message, so the Sync button stops saying Synced after a failure (and the message is now escaped). - An alert action's vars and the firing's steward_alert_* vars reach ansible-playbook as one JSON extra-vars file, not -e key=value, which Ansible split on whitespace (a rule named 'High CPU on web'). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+30
-19
@@ -1,5 +1,5 @@
|
||||
"""Unit tests for alert -> Ansible action context vars (task 250)."""
|
||||
from steward.core.alerts import alert_extra_vars
|
||||
"""Unit tests for alert -> Ansible action context vars (task 250, #5157)."""
|
||||
from steward.core.alerts import action_vars, alert_extra_vars
|
||||
from steward.models.alerts import AlertOperator, AlertRule
|
||||
|
||||
|
||||
@@ -9,22 +9,33 @@ def test_alert_extra_vars_describes_the_firing():
|
||||
metric_name="battery_status", operator=AlertOperator.lt, threshold=3.0,
|
||||
created_by="u",
|
||||
)
|
||||
ev = alert_extra_vars(rule, 2.0)
|
||||
assert "steward_alert_rule=UPS low battery" in ev
|
||||
assert "steward_alert_source=snmp" in ev
|
||||
assert "steward_alert_resource=ups" in ev
|
||||
assert "steward_alert_metric=battery_status" in ev
|
||||
assert "steward_alert_value=2.0" in ev
|
||||
assert "steward_alert_threshold=3.0" in ev
|
||||
assert "steward_alert_operator=<" in ev
|
||||
assert alert_extra_vars(rule, 2.0) == {
|
||||
"steward_alert_rule": "UPS low battery", # one value, spaces and all
|
||||
"steward_alert_source": "snmp",
|
||||
"steward_alert_resource": "ups",
|
||||
"steward_alert_metric": "battery_status",
|
||||
"steward_alert_value": 2.0,
|
||||
"steward_alert_threshold": 3.0,
|
||||
"steward_alert_operator": "<",
|
||||
}
|
||||
|
||||
|
||||
def test_alert_extra_vars_are_key_value_strings():
|
||||
rule = AlertRule(
|
||||
name="r", source_module="host_agent", resource_name="srv1",
|
||||
metric_name="cpu_pct", operator=AlertOperator.gt, threshold=90.0,
|
||||
created_by="u",
|
||||
)
|
||||
ev = alert_extra_vars(rule, 95.5)
|
||||
assert all("=" in item for item in ev)
|
||||
assert all(item.startswith("steward_alert_") for item in ev)
|
||||
def test_action_vars_split_at_the_first_equals():
|
||||
assert action_vars(["greeting=hello world", "q=a=b", " k = v", "bare", "=x"]) == {
|
||||
"greeting": "hello world", "q": "a=b", "k": " v"}
|
||||
assert action_vars(None) == {}
|
||||
|
||||
|
||||
def test_an_alert_run_passes_its_vars_as_a_json_file_not_on_the_command_line():
|
||||
import json
|
||||
from steward.ansible.executor import build_ansible_command, build_extra_vars_file
|
||||
rule = AlertRule(name="High CPU on web", source_module="host_agent", resource_name="web",
|
||||
metric_name="cpu_pct", operator=AlertOperator.gt, threshold=90.0,
|
||||
created_by="u")
|
||||
merged = {**action_vars(["note=from the action"]), **alert_extra_vars(rule, 95.5)}
|
||||
cmd = build_ansible_command("p.yml", "inv", {"extra_vars_map": merged})
|
||||
assert "-e" not in cmd # nothing interpolated into argv
|
||||
argv, files = build_extra_vars_file(merged, "/tmp/x")
|
||||
assert argv == ["-e", "@/tmp/x/extravars.json"]
|
||||
assert json.loads(files[0][1])["steward_alert_rule"] == "High CPU on web"
|
||||
assert json.loads(files[0][1])["note"] == "from the action"
|
||||
|
||||
Reference in New Issue
Block a user