Skip to content

fix(ansible): deploy-native-services targets host groups the inventory does not define #13745

Closed

Description

@mrveiss

Part of #13743 · Wave 2, no blockers.

deploy-native-services.yml declares plays against host groups that the inventory does not define:

Playbook Inventory (inventory/hosts.yml)
hosts: npu (line 317) npu_workers
hosts: aiml (line 473) ai_stack

Why it matters

An Ansible play whose host pattern matches nothing is skipped silently — the run reports ok=0 changed=0 for that play and exits 0. That reads as success. Combined with #13741 (the NPU play's requirements path does not exist), the native NPU deploy path currently either does nothing or fails, and "did nothing" is the quieter of the two.

The playbook is documented as the operator entry point in SERVICE_MANAGEMENT.md and INFRASTRUCTURE_DEPLOYMENT.md, including --tags npu and --limit invocations that assume these groups exist.

Fix

Reconcile the group names against inventory/hosts.yml. Prefer fixing the playbook to the inventory's names rather than the reverse — the inventory names are used by the role-based path and by group_vars/all.yml role facts.

Acceptance criteria

  • Every hosts: pattern in the playbook resolves against the shipped inventory.
  • A check fails when a play targets a group no inventory defines — a silently-skipped play must not read as success.
  • Verified by deliberate failure: introducing a bogus group name makes the check fail.

Activity

  1. mrveiss commented on Aug 8, 2026

    @mrveiss
    OwnerAuthor

    Tracked under epic #13743 (Python 3.14 consistency). Audit with the measurements: docs/audit/python_314_consistency.md, landing in PR #13750.

  2. mrveiss commented on Aug 9, 2026

    @mrveiss
    OwnerAuthor

    Delivered and merged: PR #13785, squashed as efcb3ff.

    The issue's specific claim does not reproduce, and that is the main finding.

    hosts: npu and hosts: aiml are defined in inventory/hosts.yml — by the #2515 cross-inventory alias block at the bottom of the file, which the issue's table missed by reading only the children: section:

    # Cross-inventory aliases (#2515)
    # Ensure group names from production.yml resolve in hosts.yml.
    aiml:
      children:
        ai_stack:
    npu:
      children:
        npu_workers:

    Resolving every hosts: pattern in the playbook against all shipped inventories:

      line    8  hosts: all      -> RESOLVES in hosts-router, hosts, localhost, production, slm-nodes
      line   55  hosts: database -> RESOLVES in hosts-router, hosts, production, slm-nodes
      line  183  hosts: frontend -> RESOLVES in hosts-router, hosts, production, slm-nodes
      line  317  hosts: npu      -> RESOLVES in hosts-router, hosts, production, slm-nodes
      line  481  hosts: aiml     -> RESOLVES in hosts-router, hosts, production, slm-nodes
      line  666  hosts: browser  -> RESOLVES in production, slm-nodes
    

    So AC 1 already held and no playbook edit was needed. AC 2 and AC 3 are the real deliverable — and they are the half that keeps holding. test_deploy_native_services_resolves_everywhere_it_needs_to pins this conclusion so a future inventory edit that breaks it fails in CI rather than on a host.

    The rule is "at least one inventory", not "every". Five ship, describing different topologies (hosts.yml has no browser node; production.yml does), and ansible.cfg configures no default — every invocation passes -i explicitly. Requiring every inventory to cover every play would report correct configurations as broken.

    AC 3 — deliberate failure: test_a_group_no_inventory_defines_is_reported builds a play targeting a group no inventory defines and asserts exit 1.

    Two rounds of false positives were fixed rather than tolerated (17 findings → 4 → 2): collecting only group names flagged 13 host-targeted plays, since hosts: accepts a host as readily as a group; and reading only inventory/*.yml missed the sibling inventory.yml and the INI inventory.

    One genuine finding survived and is filed as #13786 — slm-service-control.yml and slm-service-logs.yml target a target group no inventory defines and no in-repo caller supplies, so the documented restart command restarts nothing and reports success. That is a remote-execution contract decision needing sight of the caller, so it is allowlisted with the issue number beside it, and a test asserts that reference stays.

    Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions