310 Role vbotka.freebsd.postinstall

Use case

Use the role vbotka.freebsd.postinstall to audit basic configuration of Ansible clients. The role is idempotent. Successful result means no changes are reported. This example implements the same configuration as the example 200 Create iocage templates. Clone jails..

Tree

shell> tree .
.
├── ansible.cfg
├── extra-vars.yml
├── files
│   └── pk_admins.txt
├── group_vars
│   └── all
│       └── ansible-client.yml
├── hosts
│   ├── 04_iocage.yml
│   └── 99_constructed.yml
├── iocage.ini
├── pb-test-01.yml
├── pb-test-02.yml
└── pb-test-03.yml

Synopsis

At all running jails:

  • playbook pb-test-01.yml: test the role does nothing by default

  • playbook pb-test-02.yml: install packages using the module community.general.pkgng

  • playbook pb-test-03.yml: Install packages importing vbotka.freebsd.postinstall

  • playbook pb-test-01.yml:

    • install packages

    • create user

    • configure public keys

    • configure sudo

    • configure dhclient.

Requirements

  • running jails at the iocage host.

Notes

  • Jail name doesn’t work in the parameter name of the module community.general.pkgng if the jail was created by iocage. Use JID instead.

  • The below plays run at the jails. The inventory iocage.ini is needed when a task is delegated to an iocage host.

  • The public key in files/pk_admins.txt is sanitized.

Note

vbotka.freebsd.postinstall is the role postinstall in the collection vbotka.freebsd.
vbotka.freebsd_postinstall is the role freebsd_postinstall in the namespace vbotka.
Please make sure the versions are the same before you switch between them.

See also

Jails at iocage_04

[iocage_04]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID |   NAME   | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 81  | test_131 | off  | up    | jail | 15.0-RELEASE-p3 | epair0b|10.1.0.224 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 80  | test_132 | off  | up    | jail | 15.0-RELEASE-p3 | epair0b|10.1.0.185 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 82  | test_133 | off  | up    | jail | 15.0-RELEASE-p3 | epair0b|10.1.0.225 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

ansible.cfg

Do not display skipped hosts. See the option display_skipped_hosts

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

[connection]
pipelining = true

Inventory iocage.ini

iocage_01 ansible_host=10.1.0.18
iocage_02 ansible_host=10.1.0.73
iocage_03 ansible_host=10.1.0.17
iocage_04 ansible_host=10.1.0.29

[iocage]
iocage_04

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

Inventory hosts

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
groups:
    up: iocage_state == 'up'

group_vars

group_vars/all/ansible-client.yml
freebsd_install_method: packages
freebsd_install_retries: 3
freebsd_install_delay: 5

# Ansible client template defaults
act_user: admin
act_pk: pk_admins.txt
act_sudo: true
act_rcconf:
  iocage_enable: "YES"
  sshd_enable: "YES"
act_dhclient:
  dhclient-exit-hooks: |
    case "$reason" in
        "BOUND"|"REBIND"|"REBOOT"|"RENEW")
        echo $new_ip_address > /var/db/dhclient-hook.address.$interface
        ;;
    esac
act_pkg:
  - security/sudo
  - lang/python311

# Install packages
fp_packages:
  - {list: custom, enabled: true}
pkg_dict_amd64_dict:
  custom: "{{ act_pkg }}"
fp_pkg_use_globs: false
fp_pkg_cached: true
fp_install_delegate: "{{ iocage_tags.vmm }}"
fp_pkg_jail: "{{ iocage_jid }}"

# Create user
fp_users_conf:
  - name: "{{ act_user }}"
    shell: /bin/sh

# Configure public keys
fp_authorized_key_conf:
  - user: "{{ act_user }}"
    key: "{{ lookup('file', act_pk) }}"

# Configure sudo
fp_sudoers_conf:
  - key: "{{ act_user }}"
    value: "ALL=(ALL) NOPASSWD: ALL"

# Configure dhclient hooks
fp_dhclient_hooks: "{{ act_dhclient }}"

Display inventory

(env) > ansible-inventory -i hosts -i iocage.ini --graph
@all:
  |--@ungrouped:
  |  |--iocage_01
  |  |--iocage_02
  |  |--iocage_03
  |--@up:
  |  |--test_131
  |  |--test_132
  |  |--test_133
  |--@iocage:
  |  |--iocage_04

Playbook pb-test-01.yml

- name: Test role vbotka.freebsd.postinstall
  hosts: up
  gather_facts: true
  remote_user: admin
  become: true

  vars:
    ansible_python_interpreter: auto_silent

  roles:
    - vbotka.freebsd.postinstall

Playbook output - By default do nothing

(env) > ansible-playbook pb-test-01.yml -i hosts
PLAY [Test role vbotka.freebsd.postinstall] ************************************

TASK [Gathering Facts] *********************************************************
ok: [test_132]
ok: [test_133]
ok: [test_131]

PLAY RECAP *********************************************************************
test_131                   : ok=1    changed=0    unreachable=0    failed=0    skipped=327  rescued=0    ignored=0   
test_132                   : ok=1    changed=0    unreachable=0    failed=0    skipped=327  rescued=0    ignored=0   
test_133                   : ok=1    changed=0    unreachable=0    failed=0    skipped=327  rescued=0    ignored=0   

Playbook pb-test-02.yml

Use the module community.general.pkgng to demonstrate the installation in a jail.

- name: Install packages in jails.
  hosts: up
  gather_facts: true
  remote_user: admin
  become: true

  vars:

    ansible_python_interpreter: auto_silent
    
  tasks:

    - name: Install packages
      delegate_to: "{{ iocage_tags.vmm }}"
      register: out
      community.general.pkgng:
        name: "{{ act_pkg }}"
        jail: "{{ iocage_jid }}"
        use_globs: false
        cached: true

    - ansible.builtin.debug:
        var: out

Playbook output - Install packages by community.general.pkgng

The inventory iocage.ini is needed to delegate the tasks Install packages.

(env) > ansible-playbook pb-test-02.yml -i hosts -i iocage.ini
PLAY [Install packages in jails.] **********************************************

TASK [Gathering Facts] *********************************************************
ok: [test_133]
ok: [test_132]
ok: [test_131]

TASK [Install packages] ********************************************************
ok: [test_133 -> iocage_04(10.1.0.29)]
ok: [test_131 -> iocage_04(10.1.0.29)]
ok: [test_132 -> iocage_04(10.1.0.29)]

TASK [ansible.builtin.debug] ***************************************************
ok: [test_131] => 
    out:
        changed: false
        failed: false
        msg: package(s) already present
        stderr: ''
        stderr_lines: []
        stdout: ''
        stdout_lines: []
ok: [test_132] => 
    out:
        changed: false
        failed: false
        msg: package(s) already present
        stderr: ''
        stderr_lines: []
        stdout: ''
        stdout_lines: []
ok: [test_133] => 
    out:
        changed: false
        failed: false
        msg: package(s) already present
        stderr: ''
        stderr_lines: []
        stdout: ''
        stdout_lines: []

PLAY RECAP *********************************************************************
test_131                   : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_132                   : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
test_133                   : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Playbook pb-test-03.yml

Use the imported tasks packages.yml from the role vbotka.freebsd.postinstall

- name: Install packages in jails.
  hosts: up
  gather_facts: true
  remote_user: admin
  become: true

  vars:

    ansible_python_interpreter: auto_silent
    
  tasks:

    - name: Install packages.
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: packages

Playbook output - Import vbotka.freebsd_postinstall packages.yml

(env) > ansible-playbook pb-test-03.yml -i hosts -i iocage.ini
PLAY [Install packages in jails.] **********************************************

TASK [Gathering Facts] *********************************************************
ok: [test_133]
ok: [test_132]
ok: [test_131]

TASK [vbotka.freebsd.postinstall : Packages: Set _fp_pkg_enabled and _fp_pkg_dict for amd64] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Assert all items in _fp_pkg_enabled are available in _fp_pkg_dict] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Assert freebsd_install_method in [packages, ports]] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Installation by pkgng required when fp_install_delegate] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Required variable fp_pkg_jail when fp_install_delegate] ***
ok: [test_132]
ok: [test_131]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Install packages] *****************
included: /scratch/collections/ansible_collections/vbotka/freebsd/roles/postinstall/tasks/packages-install.yml for test_131, test_132, test_133 => (item=custom)

TASK [vbotka.freebsd.postinstall : Packages-install: Install packages list custom] ***
ok: [test_132 -> iocage_04(10.1.0.29)]
ok: [test_131 -> iocage_04(10.1.0.29)]
ok: [test_133 -> iocage_04(10.1.0.29)]

PLAY RECAP *********************************************************************
test_131                   : ok=8    changed=0    unreachable=0    failed=0    skipped=5    rescued=0    ignored=0   
test_132                   : ok=8    changed=0    unreachable=0    failed=0    skipped=5    rescued=0    ignored=0   
test_133                   : ok=8    changed=0    unreachable=0    failed=0    skipped=5    rescued=0    ignored=0   

Hint

Try pb-test-01.yml, set tags -t fp_packages, and enable the import -e fp_install=true

(env) > ansible-playbook pb-test-01.yml -i hosts -i iocage.ini -t fp_packages -e fp_install=true

If the role vbotka.freebsd_postinstall is installed, try it

- name: Install packages
  ansible.builtin.import_role:
    name: vbotka.freebsd_postinstall
    tasks_from: packages

Both options should give the same result.

Install packages, create user, configure public keys, sudo, and dhclient hooks

Test the configuration step by step. Run the below plays with options --check --diff first.

  • Install packages

    (env) > ansible-playbook pb-test-01.yml -i hosts -i iocage.ini -t fp_packages -e fp_install=true
    
  • Create user

    (env) > ansible-playbook pb-test-01.yml -i hosts -t fp_users -e fp_users=true
    
  • Configure public keys

    (env) > ansible-playbook pb-test-01.yml -i hosts -t fp_authorized_key -e fp_authorized_key=true
    
  • Configure sudo

    (env) > ansible-playbook pb-test-01.yml -i hosts -t fp_sudoers -e fp_sudoers=true
    
  • Configure dhclient hooks:

    (env) > ansible-playbook pb-test-01.yml -i hosts -t fp_dhclient_hooks -e fp_dhclient=true
    

Put the extra variables into the file extra-vars.yml

fp_install: true
fp_users: true
fp_authorized_key: true
fp_sudoers: true
fp_dhclient: true

Run the play

(env) > ansible-playbook pb-test-01.yml \
        -i hosts -i iocage.ini \
        -t fp_packages,fp_users,fp_authorized_key,fp_sudoers,fp_dhclient_hooks \
        -e @extra-vars.yml
PLAY [Test role vbotka.freebsd.postinstall] ************************************

TASK [Gathering Facts] *********************************************************
ok: [test_132]
ok: [test_133]
ok: [test_131]

TASK [vbotka.freebsd.postinstall : Sanity: Unknown run tags] *******************
ok: [test_131]
ok: [test_133]
ok: [test_132]

TASK [vbotka.freebsd.postinstall : Dhclient: Create hooks.] ********************
ok: [test_132] => (item=dhclient-exit-hooks)
ok: [test_133] => (item=dhclient-exit-hooks)
ok: [test_131] => (item=dhclient-exit-hooks)

TASK [vbotka.freebsd.postinstall : Packages: Set _fp_pkg_enabled and _fp_pkg_dict for amd64] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Assert all items in _fp_pkg_enabled are available in _fp_pkg_dict] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Assert freebsd_install_method in [packages, ports]] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Installation by pkgng required when fp_install_delegate] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Required variable fp_pkg_jail when fp_install_delegate] ***
ok: [test_132]
ok: [test_131]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Packages: Install packages] *****************
included: /scratch/collections/ansible_collections/vbotka/freebsd/roles/postinstall/tasks/packages-install.yml for test_131, test_132, test_133 => (item=custom)

TASK [vbotka.freebsd.postinstall : Packages-install: Install packages list custom] ***
ok: [test_132 -> iocage_04(10.1.0.29)]
ok: [test_133 -> iocage_04(10.1.0.29)]
ok: [test_131 -> iocage_04(10.1.0.29)]

TASK [vbotka.freebsd.postinstall : Users: Manage user accounts] ****************
ok: [test_133] => (item=(censored due to no_log))
ok: [test_132] => (item=(censored due to no_log))
ok: [test_131] => (item=(censored due to no_log))

TASK [vbotka.freebsd.postinstall : Authorized-key: Get passwd] *****************
ok: [test_132]
ok: [test_133]
ok: [test_131]

TASK [vbotka.freebsd.postinstall : Authorized-key: Set local_list_users] *******
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Authorized-key: Sanity: All users exist.] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Authorized-key: Sanity: All keys are valid.] ***
ok: [test_131]
ok: [test_132]
ok: [test_133]

TASK [vbotka.freebsd.postinstall : Authorized-key: Configure authorized keys individually] ***
ok: [test_131] => (item=admin)
ok: [test_132] => (item=admin)
ok: [test_133] => (item=admin)

TASK [vbotka.freebsd.postinstall : Sudoers: Configure /usr/local/etc/sudoers] ***
ok: [test_133] => (item={'key': 'admin', 'value': 'ALL=(ALL) NOPASSWD: ALL'})
ok: [test_132] => (item={'key': 'admin', 'value': 'ALL=(ALL) NOPASSWD: ALL'})
ok: [test_131] => (item={'key': 'admin', 'value': 'ALL=(ALL) NOPASSWD: ALL'})

PLAY RECAP *********************************************************************
test_131                   : ok=17   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   
test_132                   : ok=17   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   
test_133                   : ok=17   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   

Optionally, disable the option display_ok_hosts

(env) > ANSIBLE_DISPLAY_OK_HOSTS=false \
        ansible-playbook pb-test-01.yml \
        -i hosts -i iocage.ini \
        -t fp_packages,fp_users,fp_authorized_key,fp_sudoers,fp_dhclient_hooks \
        -e @extra-vars.yml
PLAY [Test role vbotka.freebsd.postinstall] ************************************

TASK [vbotka.freebsd.postinstall : Packages: Install packages] *****************
included: /scratch/collections/ansible_collections/vbotka/freebsd/roles/postinstall/tasks/packages-install.yml for test_131, test_132, test_133 => (item=custom)

PLAY RECAP *********************************************************************
test_131                   : ok=17   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   
test_132                   : ok=17   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   
test_133                   : ok=17   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   

The above plays show that, depending on a use case, it’s possible to:

  • Use tags to select tasks-groups from the role.

  • Import selected tasks-groups from the role.

  • Create tasks using modules.

The first option is flexible in briefly selecting the functionality from the command line. On the other hand, the import provides a faster execution at the cost of flexibility.