fix(host_agent): provision/deploy vars shadowed by play-var precedence
The assertion failed ("Pass steward_url/token/pubkey") because those were
injected as inventory HOST vars, but the playbooks declared them in the play
`vars:` block — and play vars OUTRANK inventory host vars, so the empty
defaults won and the injected values never reached the play.
- Pass globals (steward_url, steward_pubkey, steward_user, agent_interval) as
extra-vars via the JSON -e @file (highest precedence, space-safe). Keep only
the per-host steward_token as an inventory host var.
- provision.yml / install.yml: drop steward_token from `vars:` so the host var
isn't shadowed; assertions use `| default('')` for the un-defaulted token.
This was the next layer under the inventory-format fix — first the inventory
wouldn't parse, now the injected vars actually apply.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -741,10 +741,9 @@ async def deploy_via_ansible():
|
|||||||
host = await _ensure_host_for_target(db, t)
|
host = await _ensure_host_for_target(db, t)
|
||||||
tokens[t.name] = await _mint_registration_token(db, host)
|
tokens[t.name] = await _mint_registration_token(db, host)
|
||||||
inv = generate_inventory(targets) # built while ORM objects are still live
|
inv = generate_inventory(targets) # built while ORM objects are still live
|
||||||
|
# Per-host token as a host var; steward_url goes in as an extra-var below.
|
||||||
for name, tok in tokens.items():
|
for name, tok in tokens.items():
|
||||||
hv = inv["_meta"]["hostvars"].setdefault(name, {})
|
inv["_meta"]["hostvars"].setdefault(name, {})["steward_token"] = tok
|
||||||
hv["steward_url"] = url
|
|
||||||
hv["steward_token"] = tok
|
|
||||||
inventory_content = inventory_to_yaml(inv)
|
inventory_content = inventory_to_yaml(inv)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
@@ -756,7 +755,8 @@ async def deploy_via_ansible():
|
|||||||
playbook_path="host_agent/install.yml",
|
playbook_path="host_agent/install.yml",
|
||||||
inventory_content=inventory_content,
|
inventory_content=inventory_content,
|
||||||
inventory_scope=scope,
|
inventory_scope=scope,
|
||||||
params={"extra_vars": [f"agent_interval={interval}"]},
|
# extra-vars outrank the playbook's `vars:` defaults; token stays per-host.
|
||||||
|
params={"extra_vars_map": {"steward_url": url, "agent_interval": interval}},
|
||||||
triggered_by=session.get("user_id"),
|
triggered_by=session.get("user_id"),
|
||||||
)
|
)
|
||||||
if err:
|
if err:
|
||||||
@@ -817,15 +817,10 @@ async def provision_via_ansible():
|
|||||||
host = await _ensure_host_for_target(db, t)
|
host = await _ensure_host_for_target(db, t)
|
||||||
tokens[t.name] = await _mint_registration_token(db, host)
|
tokens[t.name] = await _mint_registration_token(db, host)
|
||||||
inv = generate_inventory(targets) # built while ORM objects are still live
|
inv = generate_inventory(targets) # built while ORM objects are still live
|
||||||
|
# Only the per-host token is a host var; the globals go in as extra-vars
|
||||||
|
# below (extra-vars outrank play vars, host vars do not).
|
||||||
for name, tok in tokens.items():
|
for name, tok in tokens.items():
|
||||||
hv = inv["_meta"]["hostvars"].setdefault(name, {})
|
inv["_meta"]["hostvars"].setdefault(name, {})["steward_token"] = tok
|
||||||
hv["steward_url"] = url
|
|
||||||
hv["steward_token"] = tok
|
|
||||||
# Pubkey carries a space (the comment) and steward_user is free text —
|
|
||||||
# injected as JSON hostvars (space-safe), NOT -e k=v strings which
|
|
||||||
# Ansible would shlex-split on whitespace.
|
|
||||||
hv["steward_pubkey"] = pubkey
|
|
||||||
hv["steward_user"] = steward_user
|
|
||||||
inventory_content = inventory_to_yaml(inv)
|
inventory_content = inventory_to_yaml(inv)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|
||||||
@@ -837,7 +832,14 @@ async def provision_via_ansible():
|
|||||||
playbook_path="host_agent/provision.yml",
|
playbook_path="host_agent/provision.yml",
|
||||||
inventory_content=inventory_content,
|
inventory_content=inventory_content,
|
||||||
inventory_scope=scope,
|
inventory_scope=scope,
|
||||||
params={"extra_vars": [f"agent_interval={interval}"]},
|
# extra_vars_map → a JSON -e @file: highest precedence (beats play vars)
|
||||||
|
# and space-safe (steward_pubkey carries a comment with a space).
|
||||||
|
params={"extra_vars_map": {
|
||||||
|
"steward_url": url,
|
||||||
|
"steward_pubkey": pubkey,
|
||||||
|
"steward_user": steward_user,
|
||||||
|
"agent_interval": interval,
|
||||||
|
}},
|
||||||
triggered_by=session.get("user_id"),
|
triggered_by=session.get("user_id"),
|
||||||
connection={"user": boot_user, "password": boot_password},
|
connection={"user": boot_user, "password": boot_password},
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,17 +7,18 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
|
# steward_token is a per-host inventory var — not declared here, or a play var
|
||||||
|
# would outrank and shadow it. steward_url arrives as an extra-var.
|
||||||
vars:
|
vars:
|
||||||
steward_url: ""
|
steward_url: ""
|
||||||
steward_token: ""
|
|
||||||
agent_interval: 30
|
agent_interval: 30
|
||||||
tasks:
|
tasks:
|
||||||
- name: Require steward_url and steward_token
|
- name: Require steward_url and steward_token
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- steward_url | length > 0
|
- steward_url | default('') | length > 0
|
||||||
- steward_token | length > 0
|
- steward_token | default('') | length > 0
|
||||||
fail_msg: "Pass steward_url and steward_token as extra-vars."
|
fail_msg: "Pass steward_url and steward_token (Steward injects these)."
|
||||||
|
|
||||||
- name: Create steward-agent system user
|
- name: Create steward-agent system user
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
|
|||||||
@@ -19,9 +19,12 @@
|
|||||||
hosts: all
|
hosts: all
|
||||||
become: true
|
become: true
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
|
# steward_token is injected as a per-host inventory var (it differs per host),
|
||||||
|
# so it must NOT be declared here — a play var would outrank the inventory var
|
||||||
|
# and shadow it. The globals below arrive as extra-vars (highest precedence),
|
||||||
|
# which override these defaults.
|
||||||
vars:
|
vars:
|
||||||
steward_url: ""
|
steward_url: ""
|
||||||
steward_token: ""
|
|
||||||
steward_pubkey: ""
|
steward_pubkey: ""
|
||||||
steward_user: steward
|
steward_user: steward
|
||||||
agent_interval: 30
|
agent_interval: 30
|
||||||
@@ -29,10 +32,10 @@
|
|||||||
- name: Require provisioning vars
|
- name: Require provisioning vars
|
||||||
ansible.builtin.assert:
|
ansible.builtin.assert:
|
||||||
that:
|
that:
|
||||||
- steward_url | length > 0
|
- steward_url | default('') | length > 0
|
||||||
- steward_token | length > 0
|
- steward_token | default('') | length > 0
|
||||||
- steward_pubkey | length > 0
|
- steward_pubkey | default('') | length > 0
|
||||||
fail_msg: "Pass steward_url, steward_token and steward_pubkey as extra-vars."
|
fail_msg: "Pass steward_url, steward_token and steward_pubkey (Steward injects these)."
|
||||||
|
|
||||||
# ── Managed login account ────────────────────────────────────────────────
|
# ── Managed login account ────────────────────────────────────────────────
|
||||||
- name: Create the steward management account
|
- name: Create the steward management account
|
||||||
|
|||||||
Reference in New Issue
Block a user