013 Tags and custom groups

Extending example 010 Clone basejails and create inventory.

Use case

Use the property notes to create tags:

  • Add the property notes: "vmm={{ inventory_hostname }}"

In the inventory plugin:

  • compose the variable iocage_tags

  • create groups vmm_* from the attribute iocage_tags.vmm

Tree

shell> tree .
.
├── ansible.cfg
├── hosts
│   ├── 02_iocage.yml
│   └── 04_iocage.yml
├── host_vars
│   ├── iocage_02
│   │   └── iocage.yml
│   └── iocage_04
│       └── iocage.yml
├── iocage.ini
├── pb-all.yml
├── pb-ansible-client.yml
├── pb-iocage-base.yml
├── pb-iocage-clone.yml
└── pb-test.yml

Synopsis

  • At two managed nodes:

    • iocage_02

    • iocage_04

    In the playbook pb-iocage-base.yml, use the module vbotka.freebsd.iocage to:

    • create basejail ansible_client

    In the playbook pb-iocage-clone.yml, use the module vbotka.freebsd.iocage to:

    • clone 3 jails from the basejail ansible_client

    In the playbooks:

    • pb-all.yml

    • pb-ansible-client.yml

    • pb-test.yml

    use the inventory plugin vbotka.freebsd.iocage to:

    • create the inventory groups and compose variables

    • create the dictionary iocage_tags from iocage_properties.notes

    • display hosts, composed variables, and groups

    • comment on hosts potentially overriding each other silently.

Requirements

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

Inventory hosts

Enable get_properties: true to create the dictionary iocage_properties. Then, the dictionary iocage_tags can be created from iocage_properties.notes

hosts/02_iocage.yml
plugin: vbotka.freebsd.iocage
host: 10.1.0.73
user: admin
env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
get_properties: True
compose:
  ansible_host: iocage_ip4
  release: iocage_release | split('-') | first
  iocage_tags: dict(iocage_properties.notes | regex_findall('(\w+)=([\w\-]+)'))
groups:
    test_02: inventory_hostname.startswith('test')
keyed_groups:
  - prefix: distro_02
    key: iocage_release
  - prefix: state_02
    key: iocage_state
  - prefix: vmm
    key: iocage_tags.vmm
hosts/04_iocage.yml
plugin: vbotka.freebsd.iocage
host: 10.1.0.29
user: admin
get_properties: True
compose:
  ansible_host: iocage_ip4
  release: iocage_release | split('-') | first
  iocage_tags: dict(iocage_properties.notes | regex_findall('(\w+)=([\w\-]+)'))
groups:
    test_04: inventory_hostname.startswith('test')
keyed_groups:
  - prefix: distro_04
    key: iocage_release
  - prefix: state_04
    key: iocage_state
  - prefix: vmm
    key: iocage_tags.vmm

Note

The structure of the notes is up to you. If you change it, fit the declaration of iocage_tags in the inventory.

host_vars

host_vars/iocage_02/iocage.yml
properties:
  notes: "vmm={{ inventory_hostname }}"

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'

iocage_env:
  CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
host_vars/iocage_04/iocage.yml
properties:
  vnet: 'on'
  defaultrouter: 10.1.0.10
  notes: "vmm={{ inventory_hostname }}"

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

clones:
  - name: test_131
    clone_from: ansible_client
    properties:
      ip4_addr: 'vnet0|10.1.0.131/24'
  - name: test_132
    clone_from: ansible_client
    properties:
      ip4_addr: 'vnet0|10.1.0.132/24'
  - name: test_133
    clone_from: ansible_client
    properties:
      ip4_addr: 'vnet0|10.1.0.133/24'

Playbook pb-iocage-base.yml

- hosts: iocage
  environment: "{{ iocage_env | d({}) }}"

  tasks:

    - name: Create basejail
      register: out
      vbotka.freebsd.iocage:
        state: basejail
        name: "{{ item.name }}"
        release: "{{ item.release }}"
        properties: "{{ [properties, item.properties] | combine }}"
      loop: "{{ basejails }}"
      loop_control:
        label: "{{ item.name }} {{ item.release }}"

    - name: Debug
      when: debug | d(false) | bool
      ansible.builtin.debug:
        var: out
      
    - name: Display lists of bases, plugins, templates, and jails.
      ansible.builtin.debug:
        msg: |-
          releases: {{ ansible_facts.iocage_releases }}
          plugins: {{ ansible_facts.iocage_plugins.keys() | list }}
          templates: {{ ansible_facts.iocage_templates.keys() | list }}
          jails: {{ ansible_facts.iocage_jails.keys() | list }}

Playbook output - Create basejails

(env) > ansible-playbook pb-iocage-base.yml -i iocage.ini
PLAY [iocage] ******************************************************************

TASK [Create basejail] *********************************************************
changed: [iocage_04] => (item=ansible_client 15.0-RELEASE)
changed: [iocage_02] => (item=ansible_client 14.3-RELEASE)

TASK [Display lists of bases, plugins, templates, and jails.] ******************
ok: [iocage_02] => 
    msg: |-
        releases: ['14.2-RELEASE', '14.3-RELEASE']
        plugins: []
        templates: []
        jails: ['ansible_client']
ok: [iocage_04] => 
    msg: |-
        releases: ['14.3-RELEASE', '15.0-RELEASE']
        plugins: []
        templates: ['ansible_client_apache', 'ansible_client_pull']
        jails: ['ansible_client']

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

Playbook pb-iocage-clone.yml

- hosts: iocage
  environment: "{{ iocage_env | d({}) }}"

  tasks:

    - name: Clone from basejail
      register: out
      vbotka.freebsd.iocage:
        state: cloned
        clone_from: "{{ item.clone_from }}"
        name: "{{ item.name }}"
        properties: "{{ [properties, item.properties] | combine }}"
      loop: "{{ clones }}"
      loop_control:
        label: "{{ item.name }} {{ item.clone_from }}"

    - name: Debug
      when: debug | d(false) | bool
      ansible.builtin.debug:
        var: out
      
    - name: Display lists of bases, plugins, templates, and jails.
      ansible.builtin.debug:
        msg: |-
          releases: {{ ansible_facts.iocage_releases }}
          plugins: {{ ansible_facts.iocage_plugins.keys() | list }}
          templates: {{ ansible_facts.iocage_templates.keys() | list }}
          jails: {{ ansible_facts.iocage_jails.keys() | list }}

Playbook output - Clone jails

(env) > ansible-playbook pb-iocage-clone.yml -i iocage.ini
PLAY [iocage] ******************************************************************

TASK [Clone from basejail] *****************************************************
changed: [iocage_04] => (item=test_131 ansible_client)
changed: [iocage_04] => (item=test_132 ansible_client)
changed: [iocage_04] => (item=test_133 ansible_client)
changed: [iocage_02] => (item=test_111 ansible_client)
changed: [iocage_02] => (item=test_112 ansible_client)
changed: [iocage_02] => (item=test_113 ansible_client)

TASK [Display lists of bases, plugins, templates, and jails.] ******************
ok: [iocage_04] => 
    msg: |-
        releases: ['14.3-RELEASE', '15.0-RELEASE']
        plugins: []
        templates: ['ansible_client_apache', 'ansible_client_pull']
        jails: ['ansible_client', 'test_131', 'test_132', 'test_133']
ok: [iocage_02] => 
    msg: |-
        releases: ['14.2-RELEASE', '14.3-RELEASE']
        plugins: []
        templates: []
        jails: ['ansible_client', 'test_111', 'test_112', 'test_113']

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

Playbook pb-all.yml

- hosts: all

  tasks:

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

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

Playbook output - Display variables and groups

(env) > ansible-playbook pb-all.yml -i hosts
PLAY [all] *********************************************************************

TASK [debug] *******************************************************************
ok: [ansible_client] => 
    msg: |-
        inventory_hostname: ansible_client
        ansible_host: 10.1.0.198
        release: 15.0
        iocage_tags: {'vmm': 'iocage_04'}
ok: [test_111] => 
    msg: |-
        inventory_hostname: test_111
        ansible_host: 10.1.0.111
        release: 14.3
        iocage_tags: {'vmm': 'iocage_02'}
ok: [test_112] => 
    msg: |-
        inventory_hostname: test_112
        ansible_host: 10.1.0.112
        release: 14.3
        iocage_tags: {'vmm': 'iocage_02'}
ok: [test_113] => 
    msg: |-
        inventory_hostname: test_113
        ansible_host: 10.1.0.113
        release: 14.3
        iocage_tags: {'vmm': 'iocage_02'}
ok: [test_131] => 
    msg: |-
        inventory_hostname: test_131
        ansible_host: 10.1.0.131
        release: 15.0
        iocage_tags: {'vmm': 'iocage_04'}
ok: [test_132] => 
    msg: |-
        inventory_hostname: test_132
        ansible_host: 10.1.0.132
        release: 15.0
        iocage_tags: {'vmm': 'iocage_04'}
ok: [test_133] => 
    msg: |-
        inventory_hostname: test_133
        ansible_host: 10.1.0.133
        release: 15.0
        iocage_tags: {'vmm': 'iocage_04'}

TASK [debug] *******************************************************************
ok: [ansible_client] => 
    msg: |-
        groups:
          all: [ansible_client, test_111, test_112, test_113, test_131, test_132, test_133]
          distro_02_14_3_RELEASE_p8: [ansible_client, test_111, test_112, test_113]
          distro_04_15_0_RELEASE_p3: [ansible_client, test_131, test_132, test_133]
          state_02_down: [ansible_client, test_111, test_112, test_113]
          state_04_down: [ansible_client, test_131, test_132, test_133]
          test_02: [test_111, test_112, test_113]
          test_04: [test_131, test_132, test_133]
          ungrouped: []
          vmm_iocage_02: [ansible_client, test_111, test_112, test_113]
          vmm_iocage_04: [ansible_client, test_131, test_132, test_133]

PLAY RECAP *********************************************************************
ansible_client             : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_111                   : ok=1    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   
test_131                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_132                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_133                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Note

  • The inventory files in the directory hosts are evaluated in alphabetical order.

  • The jail ansible_client from iocage_02 overrides the one from iocage_01

  • See the special variable groups

Playbook pb-ansible-client.yml

- hosts: ansible_client

  tasks:

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

          iocage_tags:
            {{ iocage_tags | to_nice_yaml(indent=2) | indent(2) }}
          group_names:
            {{ group_names | to_nice_yaml(indent=2) | indent(2) }}

Playbook output - Display iocage_tags and group_names

(env) > ansible-playbook pb-ansible-client.yml -i hosts
PLAY [ansible_client] **********************************************************

TASK [debug] *******************************************************************
ok: [ansible_client] => 
    msg: |-
        inventory_hostname: ansible_client
        ansible_host: 10.1.0.198
        release: 15.0

        iocage_tags:
          vmm: iocage_04

        group_names:
          - distro_02_14_3_RELEASE_p8
          - distro_04_15_0_RELEASE_p3
          - state_02_down
          - state_04_down
          - vmm_iocage_02
          - vmm_iocage_04

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

Note

  • The structure of the inventory hosts and groups is flat. The jail ansible-client is the same in all groups.

  • See the special variable group_names

Warning

There are no internal checks of the hosts overriding each other. The consistency is up to you.

Playbook pb-test.yml

- hosts: all

  tasks:

    - debug:
        msg: "{{ inventory_hostname }} running at {{ iocage_tags.vmm | d('UNDEFINED') }}"

Playbook output - Display all jails

(env) > ansible-playbook pb-test.yml -i hosts
PLAY [all] *********************************************************************

TASK [debug] *******************************************************************
ok: [ansible_client] => 
    msg: ansible_client running at iocage_04
ok: [test_111] => 
    msg: test_111 running at iocage_02
ok: [test_112] => 
    msg: test_112 running at iocage_02
ok: [test_113] => 
    msg: test_113 running at iocage_02
ok: [test_131] => 
    msg: test_131 running at iocage_04
ok: [test_132] => 
    msg: test_132 running at iocage_04
ok: [test_133] => 
    msg: test_133 running at iocage_04

PLAY RECAP *********************************************************************
ansible_client             : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_111                   : ok=1    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   
test_131                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_132                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_133                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0