I need to define a series of parent groups based off of EC2 tags. For example:
here are my EC2 tag definitions:
ansible-tag-app: "val"
ansible-tag-category: "livetools"
ansible-tag-env: "dev"
ansible-tag-os: "oracle_8"
ansible-tag-role: "cadvisor_container,netdata_container,node_exporter"
ansible-tag-team-owner: "livetools"
I have over a hundred hosts with various values for the above keys. The ansible-tag-role values differ from host to host. I would like to have a group in my dynamic inventory tag_Role_monitoring that would various children groups such as "cadvisor_container,netdata_container". Here is my dynamic inventory file contents:
plugin: amazon.aws.aws_ec2
aws_profile: dev
debug: true
regions:
- us-east-1
- eu-west-1
hostnames:
- name: "tag:route53-a0"
keyed_groups:
- key: tags['ansible-tag-app'].split(',')
prefix: 'tag_App_'
separator: ''
- key: tags['ansible-tag-role'].split(',')
prefix: 'tag_Role_'
separator: ''
- key: tags['ansible-tag-env'].split(',')
prefix: 'tag_Env_'
separator: ''
- key: tags['ansible-tag-category'].split(',')
prefix: 'tag_Category_'
separator: ''
compose:
groups:
tag_Role_monitoring: >
'prometheus' in (tags.get('ansible-tag-role', '') | split(',')) or
'influxdb3' in (tags.get('ansible-tag-role', '') | split(',')) or
'influxdb_exporter' in (tags.get('ansible-tag-role', '') | split(',')) or
'alertmanager' in (tags.get('ansible-tag-role', '') | split(',')) or
'node_exporter' in (tags.get('ansible-tag-role', '') | split(',')) or
'netdata' in (tags.get('ansible-tag-role', '') | split(',')) or
'netdata_container' in (tags.get('ansible-tag-role', '') | split(',')) or
'cadvisor_container' in (tags.get('ansible-tag-role', '') | split(',')) or
'windows_exporter' in (tags.get('ansible-tag-role', '') | split(','))
In my ansible playbook I reference tag_Role_monitoring:
---
- name: Deploy Common Configurations
hosts: tag_Role_monitoring:!tag_Role_windows_exporter
gather_facts: true
become: true
become_user: "{{ deploy_user }}"
strategy: free
collections:
- project.mysandbox
tasks:
- import_role:
name: common
tasks_from: main
I can use ansible-inventory to output groups and their hosts for each of the child groups like prometheus, influxdb3, etc. My playbook runs for these as well. However instead of having a really long line of groups, I would like to just use one parent group.
This works:
$ venv/bin/ansible-inventory -i inventory/dev/dev.aws_ec2.yml --vault-password-file ~/.passwd --graph
|
|--@tag_App_influxdb3:
| |--dev-influxdb3-01.domain.com
|--@tag_Role_influxdb3:
| |--dev-influxdb3-01.domain.com
|--@tag_Role_influxdb_exporter:
| |--dev-influxdb3-01.domain.com
and this works:
$ venv/bin/ansible-inventory -i inventory/dev/dev.aws_ec2.yml --vault-password-file ~/.passwd --list | jq '.["tag_Role_prometheus"].hosts'
[
"dev-prometheus-01.domain.com",
"sandbox-ansible-monitor.domain.com"
]
however this returns a null.
$ venv/bin/ansible-inventory -i inventory/dev/dev.aws_ec2.yml --vault-password-file ~/.passwd --list | jq '.["tag_Role_monitoring"].hosts'
null
I have used so many different variations for trying to get the parent group working, but no matter what I do I cant get it work. I have tried many permutations that I found on the net. I can find simple examples, but nothing like this.
Running the playbook:
venv/bin/ansible-playbook deploy_common.yml --flush-cache --timeout 60 -e "ansible_python_interpreter=/usr/bin/python3" -i inventory/dev/custom_ec2_inventory --vault-password-file ~/.passwd --limit 'tag_Role_monitoring' -v
My setup:
$ venv/bin/python --version Python 3.9.6
$ venv/bin/ansible --version
ansible [core 2.15.13]
executable location = venv/bin/ansible
python version = 3.9.6 (default, Mar 14 2025, 15:38:51) [GCC 13.3.1 20240611 (Red Hat 13.3.1-2.2.0.1)] (venv/bin/python)
jinja version = 3.1.6
libyaml = True
$ tree -L 3 inventory/dev/
inventory/dev/
├── group_vars
│ ├── all
│ │ ├── all.yml
│ │ └── vault.yml
│ ├── tag_Role_alertmanager.yml
│ ├── tag_Role_cadvisor_container.yml
│ ├── tag_Role_influxdb3.yml
│ ├── tag_Role_influxdb_exporter.yml
│ ├── tag_Role_monitored.yml
│ ├── tag_Role_monitoring.yml
│ ├── tag_Role_netdata_container.yml
│ ├── tag_Role_node_exporter.yml
│ ├── tag_Role_prometheus.yml
│ └── tag_Role_windows_exporter.yml
├── dev.aws_ec2.yml
Help would be greatly appreciated.
Solution is:
one must expose tags to be able to be used in groups using 'compose'
groups cannot be nested under compose
Example:
compose:
tags: tags
groups:
tag_Role_monitoring: >
'prometheus' in (tags.get('ansible-tag-role', '') | split(',') | map('trim')) ...
I guess Ill leave off with a rant/comment to the Ansible developer community: why not name it 'expose' instead of 'compose' but more importantly why make tags available to keyed_groups, but not groups by default?!