Skip to content

Prevent broad Ansible playbooks from entering module roles on unrelated hosts #768

Description

@Vonng

Problem

Several Pigsty deployment playbooks intentionally use hosts: all so that module membership can be selected from inventory variables. In a mixed inventory, however, hosts that do not belong to a module may still enter or partially evaluate that module's role/tasks.

A practical example is an inventory that defines MinIO hosts but no PostgreSQL cluster. Running the broad deployment playbook can reach PostgreSQL identity/task evaluation on a MinIO-only host and fail with errors such as:

Error while resolving value for 'pg_instance': 'pg_cluster' is undefined
Task failed: 'item' is undefined

MinIO has a related membership problem:

  • A fixed inventory group name such as hosts: minio does not support user-defined MinIO group names.
  • A role default such as minio_cluster: minio makes the variable unsuitable as a host-membership marker, because unrelated hosts may inherit it.

Expected behavior

  • A broad module play should operate only on hosts where the corresponding cluster marker is explicitly defined:
    • pg_cluster
    • minio_cluster
    • redis_cluster
    • mysql_cluster
    • kafka_cluster
  • A non-member host should leave only the current play. Later plays in deploy.yml must remain reachable.
  • Membership filtering should check only the cluster marker. Missing instance identity such as *_seq, node number, or role should fail explicitly inside the module's existing identity validation instead of silently skipping the host.
  • Custom MinIO inventory group names should work without requiring a hard-coded minio group.
  • The implementation must remain compatible with Ansible 2.9.

Proposed minimal change

Use a compact play-level gate on broad module entry points:

pre_tasks: [ { name: skip non-pgsql hosts, meta: end_host, when: pg_cluster is not defined, tags: always } ]

Keep the corresponding role/block-level when: <cluster> is defined as a second safety layer for execution paths that bypass pre-tasks, such as --start-at-task.

Where a destructive role does not already run a dedicated identity role, add one small fail-fast assertion before any removal task. For example, pgsql-rm.yml currently runs node_id and pg_remove, not the full pg_id role. The removal role should validate only the local identity it requires rather than introducing cluster-wide topology checks that could block cleanup of a degraded cluster.

Likely broad-entry surfaces include:

  • deploy.yml (MinIO and PostgreSQL plays)
  • slim.yml
  • pgsql.yml, pgsql-rm.yml
  • minio.yml, minio-rm.yml
  • redis.yml, redis-rm.yml
  • mysql.yml
  • kafka.yml, kafka-rm.yml

Explicit-target operational playbooks such as PostgreSQL user/database/PITR workflows, strict removal workflows, and fixed-group plays such as ETCD should retain their existing contracts unless they independently exhibit the same broad-entry behavior.

This issue is limited to play/role entry filtering. Task-local loops that intentionally traverse hostvars or inventory groups should be reviewed separately.

Acceptance criteria

  • All affected playbooks pass --syntax-check with Ansible 2.9 and the current supported Ansible version.
  • In a synthetic mixed inventory, a non-member host exits the current module play without failure.
  • A later play still runs on that host, confirming that meta: end_host is play-local.
  • Role/block-level guards prevent execution when pre-tasks are bypassed.
  • A host with a cluster marker but missing required instance identity fails at the first identity assertion.
  • No new validation framework or broad role refactor is introduced.

Metadata

Metadata

Assignees

Labels

ENHANCEMENTNew feature or request

Projects

Status
No status

Relationships

None yet

Development

No branches or pull requests

Issue actions