310 Role vbotka.freebsd.postinstall

Use case

Audit basic configuration of Ansible clients using the role vbotka.freebsd.postinstall. The role is idempotent. Successful result means no changes are reported. Implement the same configuration like the example 202 Create Ansible client templates and clone DHCP Ansible client jails

Tree

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

Synopsis

  • 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-hosts.ini is needed when a task is delegated to an iocage host.

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

Warning

Please make sure the versions are the same before you switch between them.

List jails at iocage_02

[iocage_02]# iocage list -l
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| JID |   NAME   | BOOT | STATE | TYPE |     RELEASE     |        IP4         | IP6 |    TEMPLATE    | BASEJAIL |
+=====+==========+======+=======+======+=================+====================+=====+================+==========+
| 12  | afa9e515 | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.122 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 11  | c1670497 | off  | up    | jail | 14.1-RELEASE-p6 | epair0b|10.1.0.135 | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+
| 10  | test_111 | off  | up    | jail | 14.1-RELEASE-p6 | em0|10.1.0.111/24  | -   | ansible_client | no       |
+-----+----------+------+-------+------+-----------------+--------------------+-----+----------------+----------+

Configuration ansible.cfg

Do not display skipped hosts. See the option display_skipped_hosts

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

[connection]
pipelining = true

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', '='))

Inventory hosts/99_constructed.yml

plugin: ansible.builtin.constructed
groups:
    up: iocage_state == 'up'

Variables group_vars/all/ansible-client.yml

ansible_python_interpreter: auto_silent

freebsd_install_method: packages
freebsd_install_retries: 3
freebsd_install_delay: 5

# Ansible client template defaults
act_pkg:
  - security/sudo
  - lang/python311
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

# 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-hosts.ini --graph
@all:
  |--@ungrouped:
  |--@up:
  |  |--afa9e515
  |  |--c1670497
  |  |--test_111
  |--@iocage:
  |  |--iocage_01
  |  |--iocage_02

Playbook pb-test-01.yml

- name: Test role vbotka.freebsd.postinstall.
  hosts: up
  gather_facts: true
  remote_user: admin
  become: true
    
  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: [afa9e515]
ok: [c1670497]
ok: [test_111]

PLAY RECAP ************************************************************************************
afa9e515: ok=2    changed=0    unreachable=0    failed=0    skipped=305  rescued=0    ignored=0
c1670497: ok=2    changed=0    unreachable=0    failed=0    skipped=305  rescued=0    ignored=0
test_111: ok=2    changed=0    unreachable=0    failed=0    skipped=305  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
    
  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.

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

(env) > ansible-playbook pb-test-02.yml -i hosts -i iocage-hosts.ini

PLAY [Install packages in jails.] *************************************************************

TASK [Gathering Facts] ************************************************************************
ok: [test_111]
ok: [c1670497]
ok: [afa9e515]

TASK [Install packages] ***********************************************************************
ok: [test_111 -> iocage_02(10.1.0.73)]
ok: [c1670497 -> iocage_02(10.1.0.73)]
ok: [afa9e515 -> iocage_02(10.1.0.73)]

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

PLAY RECAP ************************************************************************************
afa9e515: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
c1670497: ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
test_111: 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
    
  tasks:

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

Playbook output. Import vbotka.freebsd_postinstall packages.yml

(env) > ansible-playbook pb-test-03.yml -i hosts -i iocage-hosts.ini 

PLAY [Install packages in jails.] ********************************************************************************

TASK [Gathering Facts] *******************************************************************************************
ok: [test_111]
ok: [c1670497]
ok: [afa9e515]

TASK [vbotka.freebsd.postinstall : Packages: Set _fp_pkg_enabled and _fp_pkg_dict for amd64] *********************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Assert all items in _fp_pkg_enabled are available in _fp_pkg_dict] **
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Assert freebsd_install_method in [packages, ports]] *****************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Installation by pkgng required when fp_install_delegate] ************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Required variable fp_pkg_jail when fp_install_delegate] *************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

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

TASK [vbotka.freebsd.postinstall : Packages-install: Install packages list custom] *******************************
ok: [test_111 -> iocage_02(10.1.0.73)]
ok: [afa9e515 -> iocage_02(10.1.0.73)]
ok: [c1670497 -> iocage_02(10.1.0.73)]

PLAY RECAP *******************************************************************************************************
afa9e515: ok=8    changed=0    unreachable=0    failed=0    skipped=5    rescued=0    ignored=0
c1670497: ok=8    changed=0    unreachable=0    failed=0    skipped=5    rescued=0    ignored=0
test_111: 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-hosts.ini -t fp_packages -e fp_install=true

Try the standalone role if the role vbotka.freebsd_postinstall is installed

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

Both options should give the same results.

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-hosts.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-hosts.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: [afa9e515]
ok: [test_111]
ok: [c1670497]

TASK [vbotka.freebsd.postinstall : Sanity: Unknown run tags] **********************************************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Dhclient: Create hooks.] ***********************************************
ok: [afa9e515] => (item=dhclient-exit-hooks)
ok: [c1670497] => (item=dhclient-exit-hooks)
ok: [test_111] => (item=dhclient-exit-hooks)

TASK [vbotka.freebsd.postinstall : Packages: Set _fp_pkg_enabled and _fp_pkg_dict for amd64] **************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Assert all items in _fp_pkg_enabled are available in _fp_pkg_dict] ***
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Assert freebsd_install_method in [packages, ports]] **********
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Installation by pkgng required when fp_install_delegate] *****
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Required variable fp_pkg_jail when fp_install_delegate] ******
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Packages: Install packages] ********************************************
included: ../roles/postinstall/tasks/packages-install.yml for afa9e515, c1670497, test_111 => (item=custom)

TASK [vbotka.freebsd.postinstall : Packages-install: Install packages list custom] ************************
ok: [test_111 -> iocage_02(10.1.0.73)]
ok: [c1670497 -> iocage_02(10.1.0.73)]
ok: [afa9e515 -> iocage_02(10.1.0.73)]

TASK [vbotka.freebsd.postinstall : Users: Manage user accounts] *******************************************
ok: [c1670497] => (item=None)
ok: [afa9e515] => (item=None)
ok: [c1670497]
ok: [afa9e515]
ok: [test_111] => (item=None)
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Authorized-key: Get passwd] ********************************************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Authorized-key: Set local_list_users] **********************************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Authorized-key: Sanity: All users exist.] ******************************
ok: [afa9e515]
ok: [c1670497]
ok: [test_111]

TASK [vbotka.freebsd.postinstall : Authorized-key: Configure authorized keys individually] ****************
ok: [test_111] => (item=admin)
ok: [afa9e515] => (item=admin)
ok: [c1670497] => (item=admin)

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

PLAY RECAP ************************************************************************************************
afa9e515: ok=16   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0
c1670497: ok=16   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0
test_111: ok=16   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-hosts.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: ../roles/postinstall/tasks/packages-install.yml for afa9e515, c1670497, test_111 => (item=custom)

PLAY RECAP ************************************************************************************************
afa9e515: ok=16   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0
c1670497: ok=16   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0
test_111: ok=16   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. The import provides a faster execution at the cost of flexibility.