204 Create DHCP jails from template v2. Auto UUID, iocage_tags

Extending example 203 Create DHCP jails from template. Auto UUID, iocage_tags

Use case

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

---
- 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-02.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

(env) > ansible-playbook pb-test-02.yml

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
│   ├── 01_iocage.yml
│   ├── 02_iocage.yml
│   └── 03_constructed.yml
├── host_vars
│   ├── iocage_01
│   │   └── iocage.yml
│   └── iocage_02
│       └── iocage.yml
├── iocage-hosts.ini
├── pb-iocage-ansible-clients
│   ├── iocage_jails.yml
│   ├── swarm_destroy.yml
│   └── swarm.yml
├── pb-iocage-ansible-clients-v2.yml
├── pb-test-01.yml
├── pb-test-02.yml
└── vars
    └── iocage_datasets.yml

Synopsis

  • On two iocage hosts:

    • iocage_01

    • iocage_02

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

    • ansible.builtin.command to:

      • create variable iocage_jails

      • create jails

      • start jails

      • optionally stop and destroy the jails.

  • On all created jails:

    In the playbook pb-test-01.yml:

    • connect created jails

    • display basic configuration of the jails.

Requirements

Notes

Templates created in 202 Create Ansible client templates and clone DHCP Ansible client jails are used in this example

See also

List templates at iocage_01

[iocage_01]# iocage list -lt
+------+----------------+------+-------+----------+-----------------+---------------------+-----+----------+----------+
| JID  |      NAME      | BOOT | STATE |   TYPE   |     RELEASE     |         IP4         | IP6 | TEMPLATE | BASEJAIL |
+======+================+======+=======+==========+=================+=====================+=====+==========+==========+
| None | ansible_client | off  | down  | template | 13.4-RELEASE-p2 | vnet0|10.1.0.198/24 | -   | -        | no       |
+------+----------------+------+-------+----------+-----------------+---------------------+-----+----------+----------+

List 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.1-RELEASE-p6 | em0|10.1.0.199/24 | -   | -        | no       |
+------+----------------+------+-------+----------+-----------------+-------------------+-----+----------+----------+

Configuration ansible.cfg

[defaults]
gathering = explicit
callback_result_format = yaml

[connection]
pipelining = true

group_vars/all/iocage.yml

properties:
  bpf: 1
  dhcp: 1
  vnet: 1
  notes: "vmm={{ inventory_hostname }}"

swarms:
  sw_01:
    count: 3
    template: ansible_client

host_vars/iocage_01/iocage.yml

ansible_python_interpreter: /usr/local/bin/python3.9
ansible_become_password: admin

host_vars/iocage_02/iocage.yml

ansible_python_interpreter: /usr/local/bin/python3.11

freebsd_iocage_runner_env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1

Inventory iocage-hosts.ini

iocage_01 ansible_host=10.1.0.18
iocage_02 ansible_host=10.1.0.73

[iocage]
iocage_01
iocage_02

[iocage:vars]
ansible_user=admin
ansible_become=true

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

---
- name: Create and start jails. Optionally stop and destroy jails.
  hosts: iocage
  environment: "{{ freebsd_iocage_runner_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/swarm.yml

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

Playbook output

(env) > ansible-playbook pb-iocage-ansible-clients-v2.yml -i iocage-hosts.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] ****************************************************************
changed: [iocage_01]
changed: [iocage_02]

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

TASK [Get properties of iocage jails] **********************************************************
skipping: [iocage_01]
skipping: [iocage_02]

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

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

TASK [Debug iocage_jails] **********************************************************************
skipping: [iocage_01]
skipping: [iocage_02]

TASK [Debug _tags] *****************************************************************************
ok: [iocage_01] => 
    _tags: {}
ok: [iocage_02] => 
    _tags: {}

TASK [Debug cmd_create] ************************************************************************
ok: [iocage_01] => (item=sw_01) => 
    msg: |-
        iocage create --short --template ansible_client --count 3  bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_01 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_01] => (item=sw_01)
changed: [iocage_02] => (item=sw_01)

TASK [Debug create swarms] *********************************************************************
ok: [iocage_01] => 
    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_01 swarm=sw_01
            delta: '0:00:03.580335'
            end: '2025-02-07 03:21:56.918689'
            failed: false
            invocation:
                module_args:
                    _raw_params: |-
                        iocage create --short --template ansible_client --count 3  bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_01 swarm=sw_01"
                    _uses_shell: false
                    argv: null
                    chdir: null
                    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: '2025-02-07 03:21:53.338354'
            stderr: ''
            stderr_lines: []
            stdout: |-
                16ed61e2 successfully created!
                824cdb51 successfully created!
                58fc3c05 successfully created!
            stdout_lines:
            - 16ed61e2 successfully created!
            - 824cdb51 successfully created!
            - 58fc3c05 successfully created!
        skipped: false
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.449358'
            end: '2025-02-07 03:21:49.421339'
            failed: false
            invocation:
                module_args:
                    _raw_params: |-
                        iocage create --short --template ansible_client --count 3  bpf=1 dhcp=1 vnet=1 notes="vmm=iocage_02 swarm=sw_01"
                    _uses_shell: false
                    argv: null
                    chdir: null
                    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: '2025-02-07 03:21:44.971981'
            stderr: ''
            stderr_lines: []
            stdout: |-
                5d599b2c successfully created!
                6d98c114 successfully created!
                1349277e successfully created!
            stdout_lines:
            - 5d599b2c successfully created!
            - 6d98c114 successfully created!
            - 1349277e successfully created!
        skipped: false

TASK [Get iocage list of jails] ****************************************************************
changed: [iocage_01]
changed: [iocage_02]

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

TASK [Get properties of iocage jails] **********************************************************
changed: [iocage_01] => (item=16ed61e2)
changed: [iocage_01] => (item=58fc3c05)
changed: [iocage_02] => (item=1349277e)
changed: [iocage_01] => (item=824cdb51)
changed: [iocage_02] => (item=5d599b2c)
changed: [iocage_02] => (item=6d98c114)

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

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

TASK [Debug iocage_jails] **********************************************************************
skipping: [iocage_01]
skipping: [iocage_02]

TASK [Debug cmd_start] *************************************************************************
ok: [iocage_01] => (item=sw_01) => 
    msg: |-
        iocage start 58fc3c05 16ed61e2 824cdb51
ok: [iocage_02] => (item=sw_01) => 
    msg: |-
        iocage start 1349277e 6d98c114 5d599b2c

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

TASK [Debug start swarms] **********************************************************************
ok: [iocage_01] => 
    out:
        changed: true
        msg: All items completed
        results:
        -   ansible_loop_var: item
            changed: true
            cmd:
            - iocage
            - start
            - 58fc3c05
            - 16ed61e2
            - 824cdb51
            delta: '0:00:35.208372'
            end: '2025-02-07 03:22:46.563563'
            failed: false
            invocation:
                module_args:
                    _raw_params: |-
                        iocage start 58fc3c05 16ed61e2 824cdb51
                    _uses_shell: false
                    argv: null
                    chdir: null
                    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: '2025-02-07 03:22:11.355191'
            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 58fc3c05
                  + 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.136/24
                * Starting 16ed61e2
                  + 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.244/24
                * Starting 824cdb51
                  + 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.115/24
            stdout_lines:
            - '* Starting 58fc3c05'
            - '  + 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.136/24'
            - '* Starting 16ed61e2'
            - '  + 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.244/24'
            - '* Starting 824cdb51'
            - '  + 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.115/24'
        skipped: false
ok: [iocage_02] => 
    out:
        changed: true
        msg: All items completed
        results:
        -   ansible_loop_var: item
            changed: true
            cmd:
            - iocage
            - start
            - 1349277e
            - 6d98c114
            - 5d599b2c
            delta: '0:00:37.295468'
            end: '2025-02-07 03:22:40.285180'
            failed: false
            invocation:
                module_args:
                    _raw_params: |-
                        iocage start 1349277e 6d98c114 5d599b2c
                    _uses_shell: false
                    argv: null
                    chdir: null
                    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: '2025-02-07 03:22:02.989712'
            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 1349277e
                  + 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.156/24
                * Starting 6d98c114
                  + 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.183/24
                * Starting 5d599b2c
                  + 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.184/24
            stdout_lines:
            - '* Starting 1349277e'
            - '  + 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.156/24'
            - '* Starting 6d98c114'
            - '  + 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.183/24'
            - '* Starting 5d599b2c'
            - '  + 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.184/24'
        skipped: false

PLAY RECAP *************************************************************************************
iocage_01: ok=16   changed=5    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0
iocage_02: ok=16   changed=5    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0

List jails at iocage_01

[iocage_01]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID |   NAME   | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 71  | 16ed61e2 | off  | up    | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.244 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 70  | 58fc3c05 | off  | up    | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.136 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 72  | 824cdb51 | off  | up    | jail | 13.4-RELEASE-p2 | epair0b|10.1.0.115 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

List jails at iocage_02

[iocage_02]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID |   NAME   | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 76  | 1349277e | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.156 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 78  | 5d599b2c | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.184 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 77  | 6d98c114 | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.183 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

Inventory hosts/01_iocage.yml

plugin: vbotka.freebsd.iocage
host: 10.1.0.18
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 | split | map('split', '='))

Inventory hosts/02_iocage.yml

plugin: vbotka.freebsd.iocage
host: 10.1.0.73
user: admin
env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
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 | split | map('split', '='))

Note

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

Inventory hosts/03_constructed.yml

plugin: ansible.builtin.constructed
keyed_groups:
  - prefix: swarm
    key: iocage_tags.swarm
  - prefix: vmm
    key: iocage_tags.vmm

Display inventory

(env) > ansible-inventory -i hosts --graph
@all:
  |--@ungrouped:
  |--@swarm_sw_01:
  |  |--16ed61e2
  |  |--58fc3c05
  |  |--824cdb51
  |  |--1349277e
  |  |--5d599b2c
  |  |--6d98c114
  |--@vmm_iocage_01:
  |  |--16ed61e2
  |  |--58fc3c05
  |  |--824cdb51
  |--@vmm_iocage_02:
  |  |--1349277e
  |  |--5d599b2c
  |  |--6d98c114
  

Playbook pb-test-01.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 }}"

Playbook output

(env) > ansible-playbook pb-test-01.yml -i hosts

PLAY [Connect to the group test.] *************************************************************

TASK [ansible.builtin.command] ****************************************************************
changed: [824cdb51]
changed: [16ed61e2]
changed: [58fc3c05]
changed: [1349277e]
changed: [5d599b2c]
changed: [6d98c114]

TASK [ansible.builtin.debug] ******************************************************************
ok: [16ed61e2] => 
    msg: 'ansible_host=10.1.0.244 iocage_tags={''vmm'': ''iocage_01'', ''swarm'': ''sw_01''}'
ok: [58fc3c05] => 
    msg: 'ansible_host=10.1.0.136 iocage_tags={''vmm'': ''iocage_01'', ''swarm'': ''sw_01''}'
ok: [824cdb51] => 
    msg: 'ansible_host=10.1.0.115 iocage_tags={''vmm'': ''iocage_01'', ''swarm'': ''sw_01''}'
ok: [1349277e] => 
    msg: 'ansible_host=10.1.0.156 iocage_tags={''vmm'': ''iocage_02'', ''swarm'': ''sw_01''}'
ok: [5d599b2c] => 
    msg: 'ansible_host=10.1.0.184 iocage_tags={''vmm'': ''iocage_02'', ''swarm'': ''sw_01''}'
ok: [6d98c114] => 
    msg: 'ansible_host=10.1.0.183 iocage_tags={''vmm'': ''iocage_02'', ''swarm'': ''sw_01''}'

PLAY RECAP ************************************************************************************
1349277e: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
16ed61e2: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
58fc3c05: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
5d599b2c: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
6d98c114: ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
824cdb51: 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-hosts.ini \
                                                  -t swarm_destroy \
                                                  -e swarm_destroy=true