204 Create DHCP jails with auto UUID and iocage_tags v2

Extending example 203 Create DHCP jails with auto UUID and iocage_tags

Use case

Instead of the module vbotka.freebsd.iocage create the variable iocage_jails using the filter vbotka.freebsd.iocage

pb-iocage-ansible-clients-v2/iocage_jails.yml
---
- name: Get iocage list of jails
  register: out
  changed_when: false
  ansible.builtin.command: iocage list --long

- name: Set dictionary iocage_jails
  ansible.builtin.set_fact:
    iocage_jails: "{{ out.stdout | vbotka.freebsd.iocage('jails') }}"

- name: Get properties of iocage jails
  register: out
  changed_when: false
  ansible.builtin.command: "iocage get --all {{ item }}"
  loop: "{{ iocage_jails.keys() }}"

- name: Set dictionary iocage_jails_properties
  vars:
    _keys: "{{ out.results | map(attribute='item') }}"
    _vals: "{{ out.results | map(attribute='stdout_lines')
                           | map('map', 'split', ':', 1)
                           | map('community.general.dict')
                           | map('community.general.dict_kv', 'properties') }}"
  ansible.builtin.set_fact:
    iocage_jails_properties: "{{ dict(_keys | zip(_vals))  }}"

- name: Combine iocage_jails and iocage_jails_properties
  ansible.builtin.set_fact:
    iocage_jails: "{{ [iocage_jails, iocage_jails_properties] | combine(recursive=true) }}"

Test filter vbotka.freebsd.iocage

Given the input vars/iocage_datasets.yml

---

iocage_dict:
  jails: |
    +------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
    | JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |        IP4        | IP6 |    TEMPLATE    | BASEJAIL |
    +======+================+======+=======+======+=================+===================+=====+================+==========+
    | None | ansible_client | off  | down  | jail | 14.1-RELEASE-p6 | em0|10.1.0.199/24 | -   | -              | no       |
    +------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
    | None | test_111       | off  | down  | jail | 14.1-RELEASE-p6 | em0|10.1.0.111/24 | -   | ansible_client | no       |
    +------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
  releases: |
    14.1-RELEASE

iocage_jails: |
  +------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
  | JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |        IP4        | IP6 |    TEMPLATE    | BASEJAIL |
  +======+================+======+=======+======+=================+===================+=====+================+==========+
  | None | ansible_client | off  | down  | jail | 14.1-RELEASE-p6 | em0|10.1.0.199/24 | -   | -              | no       |
  +------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
  | None | test_111       | off  | down  | jail | 14.1-RELEASE-p6 | em0|10.1.0.111/24 | -   | ansible_client | no       |
  +------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+

iocage_releases: |
  14.1-RELEASE

The below playbook pb-test-filter.yml

- name: Test filter vbotka.freebsd.iocage
  hosts: localhost

  vars_files:
    - iocage_datasets.yml

  vars:

    result: "{{ iocage_dict | vbotka.freebsd.iocage }}"
    jails: "{{ iocage_jails | vbotka.freebsd.iocage('jails') }}"
    releases: "{{ iocage_releases | vbotka.freebsd.iocage('releases') }}"

  tasks:

    - debug:
        var: result

    - debug:
        var: jails

    - debug:
        var: releases

gives

PLAY [Test filter vbotka.freebsd.iocage] ***************************************

TASK [debug] *******************************************************************
ok: [localhost] => 
    result:
        jails:
            ansible_client:
                basejail: 'no'
                boot: 'off'
                ip4: 10.1.0.199
                ip4_dict:
                    ip4:
                    -   ifc: em0
                        ip: 10.1.0.199
                        mask: '24'
                    msg: ''
                ip6: '-'
                jid: None
                release: 14.1-RELEASE-p6
                state: down
                template: '-'
                type: jail
            test_111:
                basejail: 'no'
                boot: 'off'
                ip4: 10.1.0.111
                ip4_dict:
                    ip4:
                    -   ifc: em0
                        ip: 10.1.0.111
                        mask: '24'
                    msg: ''
                ip6: '-'
                jid: None
                release: 14.1-RELEASE-p6
                state: down
                template: ansible_client
                type: jail
        releases:
        - 14.1-RELEASE

TASK [debug] *******************************************************************
ok: [localhost] => 
    jails:
        ansible_client:
            basejail: 'no'
            boot: 'off'
            ip4: 10.1.0.199
            ip4_dict:
                ip4:
                -   ifc: em0
                    ip: 10.1.0.199
                    mask: '24'
                msg: ''
            ip6: '-'
            jid: None
            release: 14.1-RELEASE-p6
            state: down
            template: '-'
            type: jail
        test_111:
            basejail: 'no'
            boot: 'off'
            ip4: 10.1.0.111
            ip4_dict:
                ip4:
                -   ifc: em0
                    ip: 10.1.0.111
                    mask: '24'
                msg: ''
            ip6: '-'
            jid: None
            release: 14.1-RELEASE-p6
            state: down
            template: ansible_client
            type: jail

TASK [debug] *******************************************************************
ok: [localhost] => 
    releases:
    - 14.1-RELEASE

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Tree

shell> tree .
.
├── ansible.cfg
├── group_vars
│   └── all
│       └── iocage.yml
├── hosts
│   ├── 02_iocage.yml
│   ├── 04_iocage.yml
│   └── 99_constructed.yml
├── iocage.ini
├── pb-iocage-ansible-clients-v2
│   ├── iocage_jails.yml
│   ├── swarm_destroy.yml
│   └── swarm.yml
├── pb-iocage-ansible-clients-v2.yml
├── pb-test.yml
├── pb-test-filter.yml
└── vars
    └── iocage_datasets.yml

Synopsis

  • At two managed nodes:

    • iocage_02

    • iocage_04

    In the playbook pb-iocage-ansible-clients-v2.yml, use:

    • module ansible.builtin.command to:

      • create variable iocage_jails

      • create jails

      • start jails

      • optionally, stop and destroy the jails.

  • At all created jails:

    In the playbook pb-test.yml:

    • connect to the created jails

    • display the basic jails’ configuration.

Requirements

Notes

Templates created in 202 Create iocage templates. Clone DHCP jails. are used in this example.

See also

Templates at iocage_02

[iocage_02]# iocage list -lt
+------+----------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| JID  |      NAME      | BOOT | STATE |   TYPE   |     RELEASE     |        IP4         | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+==========+=================+====================+=====+==========+==========+
| None | ansible_client | off  | down  | template | 14.3-RELEASE-p8 | DHCP (not running) | -   | -        | no       |
+------+----------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+

Templates at iocage_04

[iocage_04]# iocage list -lt
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| JID  |         NAME          | BOOT | STATE |   TYPE   |     RELEASE     |        IP4         | IP6 | TEMPLATE | BASEJAIL |
+======+=======================+======+=======+==========+=================+====================+=====+==========+==========+
| None | ansible_client        | off  | down  | template | 15.0-RELEASE-p3 | DHCP (not running) | -   | -        | no       |
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| None | ansible_client_apache | off  | down  | template | 15.0-RELEASE-p3 | DHCP (not running) | -   | -        | no       |
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| None | ansible_client_pull   | off  | down  | template | 15.0-RELEASE-p3 | DHCP (not running) | -   | -        | no       |
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+

ansible.cfg

[defaults]
gathering = explicit
callback_result_format = yaml
display_skipped_hosts = false
host_key_checking = false

[connection]
pipelining = true

Inventory iocage.ini

iocage_02 ansible_host=10.1.0.73
iocage_04 ansible_host=10.1.0.29

[iocage]
iocage_02
iocage_04

[iocage:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=auto_silent

group_vars

group_vars/all/iocage.yml
properties:
  bpf: 1
  dhcp: 1
  vnet: 1
  notes: "vmm={{ inventory_hostname }}"

swarms:
  sw_01:
    count: 3
    template: ansible_client

Playbook pb-iocage-ansible-clients-v2.yml

---
- name: Create and start jails. Optionally stop and destroy jails.
  hosts: iocage
  environment: "{{ iocage_env | d({}) }}"

  vars:

    debug: false
    debug2: false
    dry_run: false

    swarm: false
    swarm_destroy: false
    clone: false
    clone_destroy: false

    _tags: "{{ dict(iocage_jails.keys()
                    | zip(iocage_jails.values()
                          | map(attribute='properties.notes')
                          | map('split')
                          | map('map', 'split', '=')
                          | map('community.general.dict'))) }}"
    _started: "{{ iocage_jails | dict2items
                               | selectattr('value.state', 'eq', 'up')
                               | map(attribute='key') }}"

  tasks:

    - name: Create and start swarms
      when: swarm | bool
      tags: swarm
      ansible.builtin.import_tasks: pb-iocage-ansible-clients-v2/swarm.yml

    - name: Stop and destroy swarms
      when: swarm_destroy | bool
      tags: swarm_destroy
      ansible.builtin.import_tasks: pb-iocage-ansible-clients-v2/swarm_destroy.yml

Playbook output - Create and start jails

(env) > ansible-playbook pb-iocage-ansible-clients-v2.yml \
                         -i iocage.ini \
                         -t swarm -e swarm=true -e debug=true
PLAY [Create and start jails. Optionally stop and destroy jails.] **************

TASK [Get iocage list of jails] ************************************************
ok: [iocage_04]
ok: [iocage_02]

TASK [Set dictionary iocage_jails] *********************************************
ok: [iocage_02]
ok: [iocage_04]

TASK [Set dictionary iocage_jails_properties] **********************************
ok: [iocage_02]
ok: [iocage_04]

TASK [Combine iocage_jails and iocage_jails_properties] ************************
ok: [iocage_04]
ok: [iocage_02]

TASK [Debug cmd_create debug=true] *********************************************
ok: [iocage_04] => (item=sw_01) => 
    msg: |-
        iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_04  swarm=sw_01"
ok: [iocage_02] => (item=sw_01) => 
    msg: |-
        iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_02  swarm=sw_01"

TASK [Create swarms] ***********************************************************
changed: [iocage_04] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)

TASK [Debug create swarms debug=true] ******************************************
ok: [iocage_02] => 
    out:
        changed: true
        msg: All items completed
        results:
        -   ansible_loop_var: item
            changed: true
            cmd:
            - iocage
            - create
            - --short
            - --template
            - ansible_client
            - --count
            - '3'
            - bpf=1
            - dhcp=1
            - vnet=1
            - notes=vmm=iocage_02  swarm=sw_01
            delta: '0:00:04.716321'
            end: '2026-02-24 23:28:42.947132'
            failed: false
            invocation:
                module_args:
                    _raw_params: null
                    _uses_shell: false
                    argv: null
                    chdir: null
                    cmd: |-
                        iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_02  swarm=sw_01"
                    creates: null
                    executable: null
                    expand_argument_vars: true
                    removes: null
                    stdin: null
                    stdin_add_newline: true
                    strip_empty_ends: true
            item:
                key: sw_01
                value:
                    count: 3
                    template: ansible_client
            msg: ''
            rc: 0
            start: '2026-02-24 23:28:38.230811'
            stderr: ''
            stderr_lines: []
            stdout: |-
                4e912b72 successfully created!
                0c1e035b successfully created!
                7134406d successfully created!
            stdout_lines:
            - 4e912b72 successfully created!
            - 0c1e035b successfully created!
            - 7134406d successfully created!
        skipped: false
ok: [iocage_04] => 
    out:
        changed: true
        msg: All items completed
        results:
        -   ansible_loop_var: item
            changed: true
            cmd:
            - iocage
            - create
            - --short
            - --template
            - ansible_client
            - --count
            - '3'
            - bpf=1
            - dhcp=1
            - vnet=1
            - notes=vmm=iocage_04  swarm=sw_01
            delta: '0:00:00.843386'
            end: '2026-02-24 23:28:39.857766'
            failed: false
            invocation:
                module_args:
                    _raw_params: null
                    _uses_shell: false
                    argv: null
                    chdir: null
                    cmd: |-
                        iocage create --short --template ansible_client --count 3 bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_04  swarm=sw_01"
                    creates: null
                    executable: null
                    expand_argument_vars: true
                    removes: null
                    stdin: null
                    stdin_add_newline: true
                    strip_empty_ends: true
            item:
                key: sw_01
                value:
                    count: 3
                    template: ansible_client
            msg: ''
            rc: 0
            start: '2026-02-24 23:28:39.014380'
            stderr: ''
            stderr_lines: []
            stdout: |-
                2bb0309b successfully created!
                8bffc54e successfully created!
                2e1d307d successfully created!
            stdout_lines:
            - 2bb0309b successfully created!
            - 8bffc54e successfully created!
            - 2e1d307d successfully created!
        skipped: false

TASK [Get iocage list of jails] ************************************************
ok: [iocage_04]
ok: [iocage_02]

TASK [Set dictionary iocage_jails] *********************************************
ok: [iocage_02]
ok: [iocage_04]

TASK [Get properties of iocage jails] ******************************************
ok: [iocage_04] => (item=2bb0309b)
ok: [iocage_04] => (item=2e1d307d)
ok: [iocage_04] => (item=8bffc54e)
ok: [iocage_02] => (item=0c1e035b)
ok: [iocage_02] => (item=4e912b72)
ok: [iocage_02] => (item=7134406d)

TASK [Set dictionary iocage_jails_properties] **********************************
ok: [iocage_04]
ok: [iocage_02]

TASK [Combine iocage_jails and iocage_jails_properties] ************************
ok: [iocage_04]
ok: [iocage_02]

TASK [Debug cmd_start debug=true] **********************************************
ok: [iocage_02] => (item=sw_01) => 
    msg: |-
        iocage start 7134406d 4e912b72 0c1e035b
ok: [iocage_04] => (item=sw_01) => 
    msg: |-
        iocage start 2bb0309b 2e1d307d 8bffc54e

TASK [Start swarms] ************************************************************
changed: [iocage_04] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)

TASK [Debug start swarms debug=true] *******************************************
ok: [iocage_02] => 
    out:
        changed: true
        msg: All items completed
        results:
        -   ansible_loop_var: item
            changed: true
            cmd:
            - iocage
            - start
            - 7134406d
            - 4e912b72
            - 0c1e035b
            delta: '0:00:33.593382'
            end: '2026-02-24 23:29:30.732721'
            failed: false
            invocation:
                module_args:
                    _raw_params: null
                    _uses_shell: false
                    argv: null
                    chdir: null
                    cmd: |-
                        iocage start 7134406d 4e912b72 0c1e035b
                    creates: null
                    executable: null
                    expand_argument_vars: true
                    removes: null
                    stdin: null
                    stdin_add_newline: true
                    strip_empty_ends: true
            item:
                key: sw_01
                value:
                    count: 3
                    template: ansible_client
            msg: ''
            rc: 0
            start: '2026-02-24 23:28:57.139339'
            stderr: |-
                No default gateway found for ipv6.
                No default gateway found for ipv6.
                No default gateway found for ipv6.
            stderr_lines:
            - No default gateway found for ipv6.
            - No default gateway found for ipv6.
            - No default gateway found for ipv6.
            stdout: |-
                * Starting 7134406d
                  + Started OK
                  + Using devfs_ruleset: 1000 (iocage generated default)
                  + Configuring VNET OK
                  + Using IP options: vnet
                  + Starting services OK
                  + Executing poststart OK
                  + DHCP Address: 10.1.0.235/24
                * Starting 4e912b72
                  + Started OK
                  + Using devfs_ruleset: 1001 (iocage generated default)
                  + Configuring VNET OK
                  + Using IP options: vnet
                  + Starting services OK
                  + Executing poststart OK
                  + DHCP Address: 10.1.0.160/24
                * Starting 0c1e035b
                  + Started OK
                  + Using devfs_ruleset: 1002 (iocage generated default)
                  + Configuring VNET OK
                  + Using IP options: vnet
                  + Starting services OK
                  + Executing poststart OK
                  + DHCP Address: 10.1.0.129/24
            stdout_lines:
            - '* Starting 7134406d'
            - '  + Started OK'
            - '  + Using devfs_ruleset: 1000 (iocage generated default)'
            - '  + Configuring VNET OK'
            - '  + Using IP options: vnet'
            - '  + Starting services OK'
            - '  + Executing poststart OK'
            - '  + DHCP Address: 10.1.0.235/24'
            - '* Starting 4e912b72'
            - '  + Started OK'
            - '  + Using devfs_ruleset: 1001 (iocage generated default)'
            - '  + Configuring VNET OK'
            - '  + Using IP options: vnet'
            - '  + Starting services OK'
            - '  + Executing poststart OK'
            - '  + DHCP Address: 10.1.0.160/24'
            - '* Starting 0c1e035b'
            - '  + Started OK'
            - '  + Using devfs_ruleset: 1002 (iocage generated default)'
            - '  + Configuring VNET OK'
            - '  + Using IP options: vnet'
            - '  + Starting services OK'
            - '  + Executing poststart OK'
            - '  + DHCP Address: 10.1.0.129/24'
        skipped: false
ok: [iocage_04] => 
    out:
        changed: true
        msg: All items completed
        results:
        -   ansible_loop_var: item
            changed: true
            cmd:
            - iocage
            - start
            - 2bb0309b
            - 2e1d307d
            - 8bffc54e
            delta: '0:00:25.820579'
            end: '2026-02-24 23:29:23.716682'
            failed: false
            invocation:
                module_args:
                    _raw_params: null
                    _uses_shell: false
                    argv: null
                    chdir: null
                    cmd: |-
                        iocage start 2bb0309b 2e1d307d 8bffc54e
                    creates: null
                    executable: null
                    expand_argument_vars: true
                    removes: null
                    stdin: null
                    stdin_add_newline: true
                    strip_empty_ends: true
            item:
                key: sw_01
                value:
                    count: 3
                    template: ansible_client
            msg: ''
            rc: 0
            start: '2026-02-24 23:28:57.896103'
            stderr: |-
                No default gateway found for ipv6.
                No default gateway found for ipv6.
                No default gateway found for ipv6.
            stderr_lines:
            - No default gateway found for ipv6.
            - No default gateway found for ipv6.
            - No default gateway found for ipv6.
            stdout: |-
                * Starting 2bb0309b
                  + Started OK
                  + Using devfs_ruleset: 1000 (iocage generated default)
                  + Configuring VNET OK
                  + Using IP options: vnet
                  + Starting services OK
                  + Executing poststart OK
                  + DHCP Address: 10.1.0.123/24
                * Starting 2e1d307d
                  + Started OK
                  + Using devfs_ruleset: 1001 (iocage generated default)
                  + Configuring VNET OK
                  + Using IP options: vnet
                  + Starting services OK
                  + Executing poststart OK
                  + DHCP Address: 10.1.0.201/24
                * Starting 8bffc54e
                  + Started OK
                  + Using devfs_ruleset: 1002 (iocage generated default)
                  + Configuring VNET OK
                  + Using IP options: vnet
                  + Starting services OK
                  + Executing poststart OK
                  + DHCP Address: 10.1.0.245/24
            stdout_lines:
            - '* Starting 2bb0309b'
            - '  + Started OK'
            - '  + Using devfs_ruleset: 1000 (iocage generated default)'
            - '  + Configuring VNET OK'
            - '  + Using IP options: vnet'
            - '  + Starting services OK'
            - '  + Executing poststart OK'
            - '  + DHCP Address: 10.1.0.123/24'
            - '* Starting 2e1d307d'
            - '  + Started OK'
            - '  + Using devfs_ruleset: 1001 (iocage generated default)'
            - '  + Configuring VNET OK'
            - '  + Using IP options: vnet'
            - '  + Starting services OK'
            - '  + Executing poststart OK'
            - '  + DHCP Address: 10.1.0.201/24'
            - '* Starting 8bffc54e'
            - '  + Started OK'
            - '  + Using devfs_ruleset: 1002 (iocage generated default)'
            - '  + Configuring VNET OK'
            - '  + Using IP options: vnet'
            - '  + Starting services OK'
            - '  + Executing poststart OK'
            - '  + DHCP Address: 10.1.0.245/24'
        skipped: false

PLAY RECAP *********************************************************************
iocage_02                  : ok=15   changed=2    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   
iocage_04                  : ok=15   changed=2    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0   

Jails at iocage_02

[iocage_02]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID |   NAME   | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 87  | 0c1e035b | off  | up    | jail | 14.3-RELEASE-p8 | epair0b|10.1.0.129 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 86  | 4e912b72 | off  | up    | jail | 14.3-RELEASE-p8 | epair0b|10.1.0.160 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 85  | 7134406d | off  | up    | jail | 14.3-RELEASE-p8 | epair0b|10.1.0.235 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

Jails at iocage_04

[iocage_04]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID |   NAME   | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 64  | 2bb0309b | off  | up    | jail | 15.0-RELEASE-p3 | epair0b|10.1.0.123 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 65  | 2e1d307d | off  | up    | jail | 15.0-RELEASE-p3 | epair0b|10.1.0.201 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 66  | 8bffc54e | off  | up    | jail | 15.0-RELEASE-p3 | epair0b|10.1.0.245 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

Inventory hosts

hosts/02_iocage.yml
plugin: vbotka.freebsd.iocage
host: 10.1.0.73
user: admin
get_properties: True
hooks_results:
  - /var/db/dhclient-hook.address.epair0b
compose:
  ansible_host: (iocage_hooks.0 == '-') | ternary(iocage_ip4, iocage_hooks.0)
  iocage_tags: dict(iocage_properties.notes | regex_findall('(\w+)=([\w\-]+)'))
hosts/04_iocage.yml
plugin: vbotka.freebsd.iocage
host: 10.1.0.29
user: admin
get_properties: True
hooks_results:
  - /var/db/dhclient-hook.address.epair0b
compose:
  ansible_host: (iocage_hooks.0 == '-') | ternary(iocage_ip4, iocage_hooks.0)
  iocage_tags: dict(iocage_properties.notes | regex_findall('(\w+)=([\w\-]+)'))
hosts/99_constructed.yml
plugin: ansible.builtin.constructed
keyed_groups:
  - prefix: swarm
    key: iocage_tags.swarm
  - prefix: vmm
    key: iocage_tags.vmm

Note

The option get_properties: True is needed to get the dictionary iocage_properties.

Display inventory

(env) > ansible-inventory -i hosts --graph
@all:
  |--@ungrouped:
  |--@swarm_sw_01:
  |  |--0c1e035b
  |  |--4e912b72
  |  |--7134406d
  |  |--2bb0309b
  |  |--2e1d307d
  |  |--8bffc54e
  |--@vmm_iocage_02:
  |  |--0c1e035b
  |  |--4e912b72
  |  |--7134406d
  |--@vmm_iocage_04:
  |  |--2bb0309b
  |  |--2e1d307d
  |  |--8bffc54e

Playbook pb-test.yml

- name: Connect to the group test.
  hosts: swarm_sw_01
  remote_user: admin
  gather_facts: false

  vars:

    ansible_python_interpreter: auto_silent
    
  tasks:

    - ansible.builtin.command: hostname
      register: out_host
    
    - ansible.builtin.debug:
        msg: >
          ansible_host={{ ansible_host }}
          iocage_tags={{ iocage_tags | to_yaml }}

Playbook output - Display iocage_tags

(env) > ansible-playbook pb-test.yml -i hosts
PLAY [Connect to the group test.] **********************************************

TASK [ansible.builtin.command] *************************************************
changed: [2bb0309b]
changed: [2e1d307d]
changed: [8bffc54e]
changed: [7134406d]
changed: [4e912b72]
changed: [0c1e035b]

TASK [ansible.builtin.debug] ***************************************************
ok: [0c1e035b] => 
    msg: |-
        ansible_host=10.1.0.129 iocage_tags={swarm: sw_01, vmm: iocage_02}
ok: [4e912b72] => 
    msg: |-
        ansible_host=10.1.0.160 iocage_tags={swarm: sw_01, vmm: iocage_02}
ok: [7134406d] => 
    msg: |-
        ansible_host=10.1.0.235 iocage_tags={swarm: sw_01, vmm: iocage_02}
ok: [2bb0309b] => 
    msg: |-
        ansible_host=10.1.0.123 iocage_tags={swarm: sw_01, vmm: iocage_04}
ok: [2e1d307d] => 
    msg: |-
        ansible_host=10.1.0.201 iocage_tags={swarm: sw_01, vmm: iocage_04}
ok: [8bffc54e] => 
    msg: |-
        ansible_host=10.1.0.245 iocage_tags={swarm: sw_01, vmm: iocage_04}

PLAY RECAP *********************************************************************
0c1e035b                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
2bb0309b                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
2e1d307d                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
4e912b72                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
7134406d                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
8bffc54e                   : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Hint

The below command stops and destroys the jails in swarms

ansible-playbook pb-iocage-ansible-clients-v2.yml \
                 -i iocage.ini \
                 -t swarm_destroy -e swarm_destroy=true