330 Clone jails and create inventory

Use case

Fetch releases, create basejails, clone from the basejails, and start the jails. Create and display the inventory. Use the role vbotka.freebsd.iocage instead of the Plugins.

Tree

shell> tree .
.
├── ansible.cfg
├── host_vars
│   ├── iocage_02
│   │   └── iocage.yml
│   └── iocage_04
│       └── iocage.yml
├── iocage.ini
├── pb-iocage-fetch-base-clone.yml
├── pb-iocage-list.yml
└── pb-test.yml

Synopsis

  • At two managed nodes: In the playbook pb-iocage-fetch-base-clone.yml, use the role vbotka.freebsd.iocage to:

    • fetch the release

    • create basejail

    • clone 3 jails from the basejail.

    In the playbook pb-iocage-list.yml, use the role vbotka.freebsd.iocage to:

    • create the lists of bases and jails

    • optionally, display the lists.

    In the playbook pb-test-01.yml:

    • create the inventory group test and compose variables

    • display the hosts and composed variables in the group test

    • display all groups.

Requirements

Notes

ansible.cfg

[defaults]
gathering = explicit
callback_result_format = yaml
display_skipped_hosts = 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

host_vars

host_vars/iocage_02/iocage.yml
freebsd_iocage_pool: zroot
freebsd_iocage_pool_mount: /zroot
freebsd_iocage_mount: "{{ freebsd_iocage_pool_mount }}/iocage"

properties:
  notes: "vmm={{ inventory_hostname }}"

fetch:
  - 14.3-RELEASE

basejails:
  - name: ansible_client
    release: 14.3-RELEASE
    properties:
      ip4_addr: 'em0|10.1.0.199/24'

clones:
  - name: test_111
    clone_from: ansible_client
    properties:
      ip4_addr: 'em0|10.1.0.111/24'
  - name: test_112
    clone_from: ansible_client
    properties:
      ip4_addr: 'em0|10.1.0.112/24'
  - name: test_113
    clone_from: ansible_client
    properties:
      ip4_addr: 'em0|10.1.0.113/24'

start:
  - test_113

iocage_env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1

# Required by the role vbotka.freebsd.iocage
freebsd_iocage_runner_env: "{{ iocage_env }}"
host_vars/iocage_04/iocage.yml
freebsd_iocage_pool: iocage
freebsd_iocage_pool_mount: /iocage
freebsd_iocage_mount: "{{ freebsd_iocage_pool_mount }}/iocage"

properties:
  vnet: 'on'
  defaultrouter: 10.1.0.10
  notes: "vmm={{ inventory_hostname }}"

fetch:
  - 15.0-RELEASE

basejails:
  - name: ansible_client
    release: 15.0-RELEASE
    properties:
      vnet: 1
      defaultrouter: 10.1.0.10
      ip4_addr: 'vnet0|10.1.0.198/24'

clones:
  - name: test_101
    clone_from: ansible_client
    properties:
      ip4_addr: 'vnet0|10.1.0.101/24'
  - name: test_102
    clone_from: ansible_client
    properties:
      ip4_addr: 'vnet0|10.1.0.102/24'
  - name: test_103
    clone_from: ansible_client
    properties:
      ip4_addr: 'vnet0|10.1.0.103/24'

start:
  - test_103

# In production, put the password into the vault.
ansible_become_password: admin

Playbook pb-iocage-fetch-base-clone.yml

- name: Iocage fetch releases, create basejail, and clone jails.
  hosts: iocage

  vars:

    freebsd_iocage_runner_exec: "fetch,create,clone"
    freebsd_iocage_runner_cmd: |
      {% filter from_yaml %}
      fetch:
      {% for release in fetch %}
      - cmd: iocage fetch --release {{ release }}
        creates: {{ freebsd_iocage_mount }}/releases/{{ release }}
      {% endfor %}
      create:
      {% for jail in basejails %}
      - cmd: iocage create --release {{ jail.release }} --name {{ jail.name }}
        creates: {{ freebsd_iocage_mount }}/jails/{{ jail.name }}
      {% endfor %}
      {% for jail in basejails %}
      {% for k, v in (properties | combine(jail.properties)).items() %}
      - cmd: iocage set {{ k }}={{ v }} {{ jail.name }}
      {% endfor %}
      {% endfor %}
      clone:
      {% for jail in clones %}
      - cmd: iocage clone {{ jail.clone_from }} --name {{ jail.name }}
        creates: {{ freebsd_iocage_mount }}/jails/{{ jail.name }}
      {% endfor %}
      {% for jail in clones %}
      {% for k, v in (properties | combine(jail.properties)).items() %}
      - cmd: iocage set {{ k }}={{ v }} {{ jail.name }}
      {% endfor %}
      {% endfor %}
      {% endfilter %}

  tasks:

    - name: Debug
      when: debug | d(false) | bool
      tags: debug
      ansible.builtin.debug:
        msg: |
          freebsd_iocage_runner_exec: {{ freebsd_iocage_runner_exec }}
          freebsd_iocage_runner_cmd:
            {{ freebsd_iocage_runner_cmd | to_nice_yaml(indent=2) | indent(2) }}

    - name: Fetch releases, create jails, and clone jails.
      tags: runner
      block:

        - name: Run commands
          register: out
          ansible.builtin.import_role:
            name: vbotka.freebsd.iocage
            tasks_from: runner

        - name: Debug
          when: debug2 | d(false) | bool
          ansible.builtin.debug:
            var: out

Playbook output - Display variables

(env) > ansible-playbook pb-iocage-fetch-base-clone.yml -i iocage.ini \
                                                        -t debug \
                                                        -e debug=true
PLAY [Iocage fetch releases, create basejail, and clone jails.] ****************

TASK [Debug] *******************************************************************
ok: [iocage_04] => 
    msg: |-
        freebsd_iocage_runner_exec: fetch,create,clone
        freebsd_iocage_runner_cmd:
          clone:
          - cmd: iocage clone ansible_client --name test_101
            creates: /iocage/iocage/jails/test_101
          - cmd: iocage clone ansible_client --name test_102
            creates: /iocage/iocage/jails/test_102
          - cmd: iocage clone ansible_client --name test_103
            creates: /iocage/iocage/jails/test_103
          - cmd: iocage set vnet=on test_101
          - cmd: iocage set defaultrouter=10.1.0.10 test_101
          - cmd: iocage set notes=vmm=iocage_04 test_101
          - cmd: iocage set ip4_addr=vnet0|10.1.0.101/24 test_101
          - cmd: iocage set vnet=on test_102
          - cmd: iocage set defaultrouter=10.1.0.10 test_102
          - cmd: iocage set notes=vmm=iocage_04 test_102
          - cmd: iocage set ip4_addr=vnet0|10.1.0.102/24 test_102
          - cmd: iocage set vnet=on test_103
          - cmd: iocage set defaultrouter=10.1.0.10 test_103
          - cmd: iocage set notes=vmm=iocage_04 test_103
          - cmd: iocage set ip4_addr=vnet0|10.1.0.103/24 test_103
          create:
          - cmd: iocage create --release 15.0-RELEASE --name ansible_client
            creates: /iocage/iocage/jails/ansible_client
          - cmd: iocage set vnet=1 ansible_client
          - cmd: iocage set defaultrouter=10.1.0.10 ansible_client
          - cmd: iocage set notes=vmm=iocage_04 ansible_client
          - cmd: iocage set ip4_addr=vnet0|10.1.0.198/24 ansible_client
          fetch:
          - cmd: iocage fetch --release 15.0-RELEASE
            creates: /iocage/iocage/releases/15.0-RELEASE
ok: [iocage_02] => 
    msg: |-
        freebsd_iocage_runner_exec: fetch,create,clone
        freebsd_iocage_runner_cmd:
          clone:
          - cmd: iocage clone ansible_client --name test_111
            creates: /zroot/iocage/jails/test_111
          - cmd: iocage clone ansible_client --name test_112
            creates: /zroot/iocage/jails/test_112
          - cmd: iocage clone ansible_client --name test_113
            creates: /zroot/iocage/jails/test_113
          - cmd: iocage set notes=vmm=iocage_02 test_111
          - cmd: iocage set ip4_addr=em0|10.1.0.111/24 test_111
          - cmd: iocage set notes=vmm=iocage_02 test_112
          - cmd: iocage set ip4_addr=em0|10.1.0.112/24 test_112
          - cmd: iocage set notes=vmm=iocage_02 test_113
          - cmd: iocage set ip4_addr=em0|10.1.0.113/24 test_113
          create:
          - cmd: iocage create --release 14.3-RELEASE --name ansible_client
            creates: /zroot/iocage/jails/ansible_client
          - cmd: iocage set notes=vmm=iocage_02 ansible_client
          - cmd: iocage set ip4_addr=em0|10.1.0.199/24 ansible_client
          fetch:
          - cmd: iocage fetch --release 14.3-RELEASE
            creates: /zroot/iocage/releases/14.3-RELEASE

PLAY RECAP *********************************************************************
iocage_02                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
iocage_04                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Playbook output - Runner

(env) > ansible-playbook pb-iocage-fetch-base-clone.yml -i iocage.ini \
                                                        -t runner
PLAY [Iocage fetch releases, create basejail, and clone jails.] ****************

TASK [vbotka.freebsd.iocage : Runner: Assert all commands are available.] ******
ok: [iocage_02]
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Runner: Assert all commands are iocage.] *********
ok: [iocage_02]
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Runner: Run listed commands.] ********************
ok: [iocage_04] => (item=iocage fetch --release 15.0-RELEASE)
ok: [iocage_02] => (item=iocage fetch --release 14.3-RELEASE)
changed: [iocage_04] => (item=iocage create --release 15.0-RELEASE --name ansible_client)
changed: [iocage_04] => (item=iocage set vnet=1 ansible_client)
changed: [iocage_04] => (item=iocage set defaultrouter=10.1.0.10 ansible_client)
changed: [iocage_04] => (item=iocage set notes=vmm=iocage_04 ansible_client)
changed: [iocage_04] => (item=iocage set ip4_addr=vnet0|10.1.0.198/24 ansible_client)
changed: [iocage_04] => (item=iocage clone ansible_client --name test_101)
changed: [iocage_04] => (item=iocage clone ansible_client --name test_102)
changed: [iocage_02] => (item=iocage create --release 14.3-RELEASE --name ansible_client)
changed: [iocage_04] => (item=iocage clone ansible_client --name test_103)
changed: [iocage_04] => (item=iocage set vnet=on test_101)
changed: [iocage_04] => (item=iocage set defaultrouter=10.1.0.10 test_101)
changed: [iocage_04] => (item=iocage set notes=vmm=iocage_04 test_101)
changed: [iocage_04] => (item=iocage set ip4_addr=vnet0|10.1.0.101/24 test_101)
changed: [iocage_04] => (item=iocage set vnet=on test_102)
changed: [iocage_02] => (item=iocage set notes=vmm=iocage_02 ansible_client)
changed: [iocage_04] => (item=iocage set defaultrouter=10.1.0.10 test_102)
changed: [iocage_04] => (item=iocage set notes=vmm=iocage_04 test_102)
changed: [iocage_04] => (item=iocage set ip4_addr=vnet0|10.1.0.102/24 test_102)
changed: [iocage_04] => (item=iocage set vnet=on test_103)
changed: [iocage_04] => (item=iocage set defaultrouter=10.1.0.10 test_103)
changed: [iocage_04] => (item=iocage set notes=vmm=iocage_04 test_103)
changed: [iocage_04] => (item=iocage set ip4_addr=vnet0|10.1.0.103/24 test_103)
changed: [iocage_02] => (item=iocage set ip4_addr=em0|10.1.0.199/24 ansible_client)
changed: [iocage_02] => (item=iocage clone ansible_client --name test_111)
changed: [iocage_02] => (item=iocage clone ansible_client --name test_112)
changed: [iocage_02] => (item=iocage clone ansible_client --name test_113)
changed: [iocage_02] => (item=iocage set notes=vmm=iocage_02 test_111)
changed: [iocage_02] => (item=iocage set ip4_addr=em0|10.1.0.111/24 test_111)
changed: [iocage_02] => (item=iocage set notes=vmm=iocage_02 test_112)
changed: [iocage_02] => (item=iocage set ip4_addr=em0|10.1.0.112/24 test_112)
changed: [iocage_02] => (item=iocage set notes=vmm=iocage_02 test_113)
changed: [iocage_02] => (item=iocage set ip4_addr=em0|10.1.0.113/24 test_113)

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

Note

The commands iocage set ... are not idempotent.

Hint

See the log on the remote host

shell> tail -f /var/log/iocage.log

Jails at iocage_02

[iocage_02]# iocage list -l
+------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |        IP4        | IP6 |    TEMPLATE    | BASEJAIL |
+======+================+======+=======+======+=================+===================+=====+================+==========+
| None | ansible_client | off  | down  | jail | 14.3-RELEASE-p8 | em0|10.1.0.199/24 | -   | -              | no       |
+------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
| None | test_111       | off  | down  | jail | 14.3-RELEASE-p8 | em0|10.1.0.111/24 | -   | ansible_client | no       |
+------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
| None | test_112       | off  | down  | jail | 14.3-RELEASE-p8 | em0|10.1.0.112/24 | -   | ansible_client | no       |
+------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+
| None | test_113       | off  | down  | jail | 14.3-RELEASE-p8 | em0|10.1.0.113/24 | -   | ansible_client | no       |
+------+----------------+------+-------+------+-----------------+-------------------+-----+----------------+----------+

Jails at iocage_04

[iocage_04]# iocage list -l
+------+----------------+------+-------+------+-----------------+---------------------+-----+----------------+----------+
| JID  |      NAME      | BOOT | STATE | TYPE |     RELEASE     |         IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+======+================+======+=======+======+=================+=====================+=====+================+==========+
| None | ansible_client | off  | down  | jail | 15.0-RELEASE-p3 | vnet0|10.1.0.198/24 | -   | -              | no       |
+------+----------------+------+-------+------+-----------------+---------------------+-----+----------------+----------+
| None | test_101       | off  | down  | jail | 15.0-RELEASE-p3 | vnet0|10.1.0.101/24 | -   | ansible_client | no       |
+------+----------------+------+-------+------+-----------------+---------------------+-----+----------------+----------+
| None | test_102       | off  | down  | jail | 15.0-RELEASE-p3 | vnet0|10.1.0.102/24 | -   | ansible_client | no       |
+------+----------------+------+-------+------+-----------------+---------------------+-----+----------------+----------+
| None | test_103       | off  | down  | jail | 15.0-RELEASE-p3 | vnet0|10.1.0.103/24 | -   | ansible_client | no       |
+------+----------------+------+-------+------+-----------------+---------------------+-----+----------------+----------+

Playbook pb-iocage-list.yml

- name: Iocage list datasets.
  hosts: iocage

  vars:

    jail_attr: [jid, name, boot, state, type, release, ip4, ip6, template, basejail]

  tasks:

    - name: Run commands
      tags: runner
      ansible.builtin.import_role:
        name: vbotka.freebsd.iocage
        tasks_from: runner
      vars:
        freebsd_iocage_runner_exec: lists
        freebsd_iocage_runner_cmd:
          lists:
            - cmd: iocage list -rh
            - cmd: iocage list -lh
            - cmd: iocage list -Ph
            - cmd: iocage list -th

    - name: Debug
      when: debug2 | d(false) | bool
      ansible.builtin.debug:
        var: out

    - name: Set lists
      ansible.builtin.set_fact:
        iocage_releases: "{{ out.results.0.stdout.splitlines() }}"
        iocage_jails: "{{ dict(out.results.1.stdout.splitlines()
                               | map('split', '\t')
                               | map('zip', jail_attr)
                               | map('map', 'reverse')
                               | map('community.general.dict')
                               | json_query('[].[name, @]')) }}"

    - name: Display lists
      when: debug | d(false) | bool
      ansible.builtin.debug:
        msg: |-
          iocage_releases: {{ iocage_releases }}
          iocage_jails:
            {{ iocage_jails | to_nice_yaml(indent=2) | indent(2) }}
#         iocage_plugins: {{ iocage_plugins }}
#         iocage_templates: {{ iocage_templates }}

Playbook output - Display iocage_jails

(env) > ansible-playbook pb-iocage-list.yml -i iocage.ini -e debug=true
PLAY [Iocage list datasets.] ***************************************************

TASK [vbotka.freebsd.iocage : Runner: Assert all commands are available.] ******
ok: [iocage_04]
ok: [iocage_02]

TASK [vbotka.freebsd.iocage : Runner: Assert all commands are iocage.] *********
ok: [iocage_04]
ok: [iocage_02]

TASK [vbotka.freebsd.iocage : Runner: Run listed commands.] ********************
changed: [iocage_04] => (item=iocage list -rh)
changed: [iocage_04] => (item=iocage list -lh)
changed: [iocage_04] => (item=iocage list -Ph)
changed: [iocage_04] => (item=iocage list -th)
changed: [iocage_02] => (item=iocage list -rh)
changed: [iocage_02] => (item=iocage list -lh)
changed: [iocage_02] => (item=iocage list -Ph)
changed: [iocage_02] => (item=iocage list -th)

TASK [Set lists] ***************************************************************
ok: [iocage_02]
ok: [iocage_04]

TASK [Display lists] ***********************************************************
ok: [iocage_04] => 
    msg: |-
        iocage_releases: ['14.3-RELEASE', '15.0-RELEASE']
        iocage_jails:
          ansible_client:
            basejail: 'no'
            boot: 'off'
            ip4: vnet0|10.1.0.198/24
            ip6: '-'
            jid: None
            name: ansible_client
            release: 15.0-RELEASE-p3
            state: down
            template: '-'
            type: jail
          test_101:
            basejail: 'no'
            boot: 'off'
            ip4: vnet0|10.1.0.101/24
            ip6: '-'
            jid: None
            name: test_101
            release: 15.0-RELEASE-p3
            state: down
            template: ansible_client
            type: jail
          test_102:
            basejail: 'no'
            boot: 'off'
            ip4: vnet0|10.1.0.102/24
            ip6: '-'
            jid: None
            name: test_102
            release: 15.0-RELEASE-p3
            state: down
            template: ansible_client
            type: jail
          test_103:
            basejail: 'no'
            boot: 'off'
            ip4: vnet0|10.1.0.103/24
            ip6: '-'
            jid: None
            name: test_103
            release: 15.0-RELEASE-p3
            state: down
            template: ansible_client
            type: jail
ok: [iocage_02] => 
    msg: |-
        iocage_releases: ['14.2-RELEASE', '14.3-RELEASE']
        iocage_jails:
          ansible_client:
            basejail: 'no'
            boot: 'off'
            ip4: em0|10.1.0.199/24
            ip6: '-'
            jid: None
            name: ansible_client
            release: 14.3-RELEASE-p8
            state: down
            template: '-'
            type: jail
          test_111:
            basejail: 'no'
            boot: 'off'
            ip4: em0|10.1.0.111/24
            ip6: '-'
            jid: None
            name: test_111
            release: 14.3-RELEASE-p8
            state: down
            template: ansible_client
            type: jail
          test_112:
            basejail: 'no'
            boot: 'off'
            ip4: em0|10.1.0.112/24
            ip6: '-'
            jid: None
            name: test_112
            release: 14.3-RELEASE-p8
            state: down
            template: ansible_client
            type: jail
          test_113:
            basejail: 'no'
            boot: 'off'
            ip4: em0|10.1.0.113/24
            ip6: '-'
            jid: None
            name: test_113
            release: 14.3-RELEASE-p8
            state: down
            template: ansible_client
            type: jail

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

Playbook pb-test.yml

- name: Create lists
  import_playbook: pb-iocage-list.yml

- name: Create group test
  hosts: iocage

  vars:

    jails: "{{ hostvars | json_query('*.iocage_jails') | combine }}"

  tasks:

    - name: Create inventory group test
      run_once: true
      block:

        - name: Debug
          when: debug | d(false) | bool
          ansible.builtin.debug:
            var: jails

        - name: Create inventory group test
          ansible.builtin.add_host:
            groups: test
            name: "{{ item }}"
            ansible_host: "{{ jails[item].ip4 | split('|') | last
                                              | split('/') | first }}"
            release:  "{{ jails[item].release }}"
          loop: "{{ jails.keys() | select('match', 'test') }}"
  
- name: Use group test
  hosts: test

  tasks:

    - debug:
        msg: |
          inventory_hostname: {{ inventory_hostname }}
          ansible_host: {{ ansible_host }}
          release: {{ release }}

    - debug:
        msg: |
          groups:
            {{ groups | to_yaml(indent=2) | indent(2) }}
      run_once: true

Playbook output - Create and use group

(env) > ansible-playbook pb-test.yml -i iocage.ini
PLAY [Iocage list datasets.] ***************************************************

TASK [vbotka.freebsd.iocage : Runner: Assert all commands are available.] ******
ok: [iocage_04]
ok: [iocage_02]

TASK [vbotka.freebsd.iocage : Runner: Assert all commands are iocage.] *********
ok: [iocage_04]
ok: [iocage_02]

TASK [vbotka.freebsd.iocage : Runner: Run listed commands.] ********************
changed: [iocage_04] => (item=iocage list -rh)
changed: [iocage_04] => (item=iocage list -lh)
changed: [iocage_04] => (item=iocage list -Ph)
changed: [iocage_04] => (item=iocage list -th)
changed: [iocage_02] => (item=iocage list -rh)
changed: [iocage_02] => (item=iocage list -lh)
changed: [iocage_02] => (item=iocage list -Ph)
changed: [iocage_02] => (item=iocage list -th)

TASK [Set lists] ***************************************************************
ok: [iocage_02]
ok: [iocage_04]

PLAY [Create group test] *******************************************************

TASK [Create inventory group test] *********************************************
changed: [iocage_02] => (item=test_111)
changed: [iocage_02] => (item=test_112)
changed: [iocage_02] => (item=test_113)
changed: [iocage_02] => (item=test_101)
changed: [iocage_02] => (item=test_102)
changed: [iocage_02] => (item=test_103)

PLAY [Use group test] **********************************************************

TASK [debug] *******************************************************************
ok: [test_111] => 
    msg: |-
        inventory_hostname: test_111
        ansible_host: 10.1.0.111
        release: 14.3-RELEASE-p8
ok: [test_112] => 
    msg: |-
        inventory_hostname: test_112
        ansible_host: 10.1.0.112
        release: 14.3-RELEASE-p8
ok: [test_113] => 
    msg: |-
        inventory_hostname: test_113
        ansible_host: 10.1.0.113
        release: 14.3-RELEASE-p8
ok: [test_102] => 
    msg: |-
        inventory_hostname: test_102
        ansible_host: 10.1.0.102
        release: 15.0-RELEASE-p3
ok: [test_101] => 
    msg: |-
        inventory_hostname: test_101
        ansible_host: 10.1.0.101
        release: 15.0-RELEASE-p3
ok: [test_103] => 
    msg: |-
        inventory_hostname: test_103
        ansible_host: 10.1.0.103
        release: 15.0-RELEASE-p3

TASK [debug] *******************************************************************
ok: [test_111] => 
    msg: |-
        groups:
          all: [test_111, test_112, test_113, test_101, test_102, test_103, iocage_02, iocage_04]
          iocage: [iocage_02, iocage_04]
          test: [test_111, test_112, test_113, test_101, test_102, test_103]
          ungrouped: []

PLAY RECAP *********************************************************************
iocage_02                  : ok=5    changed=2    unreachable=0    failed=0    skipped=5    rescued=0    ignored=0   
iocage_04                  : ok=4    changed=1    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0   
test_101                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_102                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_103                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_111                   : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_112                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_113                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0