Verify Environment Group Check

Verify and review the implementation of an environment check to ensure nodes are in exactly one environment group.

Projects:  c2platform/phx/ansible


Prerequisites

For the purpose of this how-to, the specific node does not matter because the environment check validates the complete inventory file hosts.ini. We will use the development desktop pxd-ubuntu-devtop. To create and start this node, see:

Verify Environment Check

An environment check is implemented in the inventory project of the PHX project  c2platform/phx/ansible/-/tree/master. The check ensures that as a part of a group-based environments approach, which is part of the inventory strategy of this project, a host can be in no more than one and at least one environment group. Let’s check if that is working.

No more than one

The content below shows the Ansible environment groups development and test with respectively 7 and 1 node. Note there is only 1 node in test.

 hosts.ini

 1[development]
 2# lxd
 3pxd-rproxy1       ansible_host=192.168.60.10
 4pxd-ubuntu-devtop ansible_host=192.168.60.11
 5pxd-gitlab        ansible_host=192.168.60.12
 6pxd-gitlab-runner ansible_host=192.168.60.13
 7
 8# virtualbox
 9pxd-ad            ansible_host=192.168.61.11
10pxd-win-devtop    ansible_host=192.168.61.10
11pxd-win           ansible_host=192.168.61.12
12
13[test]
14# lxd
15pxt-rproxy1       ansible_host=192.168.60.20

Open the hosts.ini file and add pxd-ubuntu-devtop to the test group. Note that this is not correct; this is a purposeful misconfiguration. Now the node pxd-ubuntu-devtop is part of both test and development, which is what we want to avoid because the behavior will be undetermined. The modified section should look as follows:

[test]
# lxd
pxt-rproxy1       ansible_host=192.168.60.20

# virtualbox
pxd-ubuntu-devtop

Now with the node in two environment groups, provision again:

vagrant provision pxd-ubuntu-devtop

This will now fail with a message like below:

TASK [c2platform.core.linux : Fail with custom message] ************************
failed: [pxd-ubuntu-devtop] (item=Node pxd-ubuntu-devtop should be associated with exactly one environment group of: test, development!) => changed=false
  ansible_loop_var: item
  item:
    msg: 'Node pxd-ubuntu-devtop should be associated with exactly one environment group of: test, development!'
    name: Environment pxd-ubuntu-devtop → test, development
    resource_group: 0_bootstrap
    type: fail
    when: true
  msg: 'Node pxd-ubuntu-devtop should be associated with exactly one environment group of: test, development!'

At least one

Now revert the change in hosts.ini and uncomment line 4, the line which puts pxd-ubuntu-devtop in the development environment. Now the node is no longer part of any environment group. This is also a misconfiguration the environment check will detect.

[development]
# lxd
pxd-rproxy1       ansible_host=192.168.60.10
# pxd-ubuntu-devtop ansible_host=192.168.60.11
pxd-gitlab        ansible_host=192.168.60.12
pxd-gitlab-runner ansible_host=192.168.60.13

# virtualbox
pxd-ad            ansible_host=192.168.61.11
pxd-win-devtop    ansible_host=192.168.61.10
pxd-win           ansible_host=192.168.61.12

And in ubuntu group add ansible_host line

[ubuntu]
pxd-rproxy1
pxd-ubuntu-devtop ansible_host=192.168.60.11
pxd-gitlab
pxd-gitlab-runner

Provision again

vagrant provision pxd-ubuntu-devtop

This will now fail with

TASK [c2platform.core.linux : Fail with custom message] ************************
failed: [pxd-ubuntu-devtop] (item=Node pxd-ubuntu-devtop should be associated with exactly one environment group of: test, development!) => changed=false
  ansible_loop_var: item
  item:
    msg: 'Node pxd-ubuntu-devtop should be associated with exactly one environment group of: test, development!'
    name: 'Environment pxd-ubuntu-devtop → '
    resource_group: 0_bootstrap
    type: fail
    when: true
  msg: 'Node pxd-ubuntu-devtop should be associated with exactly one environment group of: test, development!'

Review

Now, how is it implemented in the inventory project in the group_vars folder? First, look at the group_vars/all/env/yml:

 group_vars/all/env.yml

---
px_env: "{{ group_names | intersect(px_envs) | first }}"
px_envs: ['test', 'development']
px_envs_node: "{{ group_names | intersect(px_envs) }}"
px_envs_node_count: "{{ px_envs_node | length }}"
px_envs_check:
  name: >-
    Environment {{ inventory_hostname }} → {{ px_envs_node | join(', ') }}    
  type: fail
  msg: >-
    Node {{ inventory_hostname }} should be associated with exactly
    one environment group of: {{ px_envs | join(', ') }}!    
  when: "{{ px_envs_node_count != '1' }}"

This YAML file defines variables to enforce the environment group policy. The px_envs variable lists allowed environment groups (’test’ and ‘development’). The px_envs_node variable identifies which of these groups the current host belongs to by intersecting the host’s group names with px_envs. The px_envs_node_count counts these intersections. Finally, px_envs_check configures a failure condition: it triggers a fail task if the count is not exactly 1, with a message indicating the host must belong to exactly one environment group.

---
px_env: "{{ group_names | intersect(px_envs) | first }}"
px_envs: ['test', 'development']
px_envs_node: "{{ group_names | intersect(px_envs) }}"
px_envs_node_count: "{{ px_envs_node | length }}"
px_envs_check:
  name: >-
    Environment {{ inventory_hostname }} → {{ px_envs_node | join(', ') }}    
  type: fail
  msg: >-
    Node {{ inventory_hostname }} should be associated with exactly
    one environment group of: {{ px_envs | join(', ') }}!    
  when: "{{ px_envs_node_count != '1' }}"

We can now use the variable px_envs_check to configure the check for Linux systems (that are part of the linux group). And to configure the check for Windows systems (that are part of the win group). Note that on both Linux and Windows hosts we can use the ansible.builtin.fail module.

 group_vars/linux/main.yml

---
linux_resources:
  0_bootstrap:
    - "{{ px_envs_check }}"

 group_vars/win/main.yml

26win_resources:
27  0_bootstrap:
28    - name: Apps folder
29      type: win_file
30      path: "{{ px_apps_dir }}"
31      state: directory
32    - "{{ px_envs_check }}"

Note, furthermore, that the variables linux_resources and win_resources that are used to configure the environment check are part of respectively the Linux role  c2platform.core.linux and the Windows role  c2platform.wincore.win.

Additional Information

For additional insights and guidance:

  • Group-based Environments: Use a group-based approach to organize your Ansible inventory and variables for different environments.
  • Ansible Inventory Project: A structured collection of files used for managing hosts and configurations. It typically includes inventory files, playbooks, host configurations, group variables, and Ansible vault files.


Last modified September 19, 2025: how-to environment check PHX-162 (9f3934e)