amazon-ec2ansibleansible-inventory

Ansible aws_ec2 dynamic inventory issue deriving a parent group directly from groups defined by EC2 tags


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

  • Solution is:

    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?!