Ansible - Configuration Modules
Modules provide the configuration capabilities…
- …scripted programs that are executed when running a playbook
Types of modules…
- …core modules are part of Ansible, e.g. “apt”
- …connection modules
- …lookup modules …data access
- …filter modules …transform data
- …callback modules …register events during task execution
- …task modules
- …self contained scripts (language agnostic)
- …copied to target machine (JSON input and output)
command
Read the section about ad-hoc commands above
Execute a command and register its output, execute another commend depending on its output…
- name: Read Apptainer bind path configuration
ansible.builtin.command: 'apptainer config global --get "bind path"'
register: apptainer_bind_path
changed_when: false
- name: Add /lustre to the Apptainer bind path configuration
ansible.builtin.command: 'apptainer config global --set "bind path" /lustre'
when: apptainer_bind_path.stdout.find('lustre') == -1
Users & Groups
ansible.builtin.user and ansible.builtin.group
- name: Set password for the root account
ansible.builtin.user:
name: root
password: '$6$/DILhqdfs3fse5ReEtJaqS...'
- name: Ensure an admin group exists
ansible.builtin.group:
name: admin
- name: Create all admin users
ansible.builtin.user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
group: admin
create_home: true
with_items:
- name: alice_adm
uid: 986
- name: bob_adm
uid: 987
ansible.posix.authorized_key adds or removes an SSH authorized key…
---
- name: Set authorized key for root user removing all the authorized keys already set
ansible.posix.authorized_key:
user: root
key: "{{ lookup('file', 'files/ssh-authorized-keys') }}"
state: present
exclusive: true
Packages
ansible.builtin.dnf …manages packages with the dnf
package manager
- name: Install dependency packages
ansible.builtin.dnf:
name:
- git
- podman
state: installed
Files, Directories & Links
ansible.builtin.file …manage files and their properties
- name: Create a directory
ansible.builtin.file:
path: /path/to/directory
state: directory
mode: '0755'
- name: Create a link
ansible.builtin.file:
path: /path/to/symlink
src: /path/to/link/to
state: link
copy
ansible.builtin.copy …requires src
and dest
- name: Write DNF configuration /etc/dnf/automatic.conf
ansible.builtin.copy:
src: ../files/dnf/automatic.conf
dest: /etc/dnf/automatic.conf
- …
mode
…chmod
configuration - …
owner
andgroup
for the file-system object …defaults to$USER
orroot
- …
backup=true
…create a backup file including timestamp
- name: copy configuration files
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: root
mode: 0644
with_items:
- src: httpd.conf
dest: /etc/httpd/conf/httpd.conf
- src: httpd-vhosts.conf
dest: /etc/httpd/conf/httpd-vhosts.conf
with_items
…iterating over a list of hashes- …reference subkeys with the dot notation, i.e.
item.src
- …described in the Loops documentation
- …reference subkeys with the dot notation, i.e.
get_url
ansible.builtin.get_url …download files from a web site or ftp to one or more hosts…
- ..checksums prevent a file from being re-downloaded if it matches
- get_url:
url: http://site.com/archive.zip
dest: /tmp/archive.zip
mode: 0640
checksum: sha256:f772bd36185515581aa9a2e4b38fb97940ff28764900ba708e68286121770e9a
lineinfile
- …ensure that a line is present in a file
- …line to be modified in a file will be found using a
regexp
- ansible.builtin.blockinfile …insert/update/remove a text block surrounded by marker lines
Modify multiple line in a single file using loop…
- name: Adjust sshd configuration file
ansible.builtin.lineinfile:
dest: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
validate: sshd -T -f %s
with_items:
- regexp: "^PasswordAuthentication"
line: "PasswordAuthentication no"
- regexp: "^PermitRootLogin"
line: "PermitRootLogin no"
- regexp: "^Port"
line: "Port 2849"
notify: restart ssh
Use validate
to execute a command to syntax check a modified configuration file…
- …a temporary file is passed in through
%s
- …expansion and pipes will not work
git
Git Module 1 checkouts of repositories:
- name: Clone Git repository
ansible.builtin.git:
repo: # repository URL
dest: /src/linux
Using a GitLab project access token:
- name: Clone Git repository
vars:
# project token name is used for "user"
gitlab_user: '<your-proect-token-name>'
# create a token in the repository under Access Tokens
gitlab_token: '<your-project-token>'
ansible.builtin.git:
repo: 'https://{{ gitlab_user }}:{{ gitlab_token }}@gitlab.com/<project-url>.git'
dest: ~ansible/
Templating
Templates are processed by the Jinja2 templating language…
- …enables dynamic expressions and access to variables and facts
- Used to…
- …create a template for a configuration file
- …template task names and more
- …templating happens on the Ansible controller
Default Jinja delimiters…
{% ... %}
…statements{ ... }
…expressions …print to the template output{# ... #}
…comments
ansible.builtin.template module…
- …file name suffix for the templates
.j2
- …templates are loaded with
trim_blocks=True
…newlines removed from blocks
Example templates/smatd.j2
using a registered variable…
DEFAULT -H -m smart-notify@example.org -M once -M exec /usr/libexec/smartmontools/smartdnotify {{ smartctl_scan_open.stdout }}
…using the ansible.builtin.template
module…
#...
- name: Execute smartctl --scan-open
ansible.builtin.command: 'smartctl --scan-open'
register: smartctl_scan_open
changed_when: false
- name: Create configuration file /etc/smartmontools/smartd.conf
ansible.builtin.template:
src: ../templates/smartmontools/smartd.j2
dest: /etc/smartmontools/smartd.conf
notify: smartd_restart
#...
Services
service
ansible.builtin.service module manages service…
- …supports all common init-systems (like Systemd, SysV, etc)
- …acts as a proxy to the underlying service manager module
Restart a service if a configuration file is changes…
handlers:
- name: restart chronyd service
listen: chronyd_restart
ansible.builtin.service:
name: chronyd
state: restarted
tasks:
- name: change NTP server address in chrony.conf
ansible.builtin.lineinfile:
path: /etc/chrony.conf
backup: true
regexp: '^pool '
firstmatch: true
line: 'pool 1.pool.ntp.org iburst'
notify: chronyd_restart
systemd_service
ansible.builtin.systemd_service manages Systemd units…
Create a Systemd service unit file and start the service…
#...
- name: Create systemd set-timezone.service unit file
ansible.builtin.copy:
src: files/set-timezone.ini
dest: /etc/systemd/system/set-timezone.service
- name: Enable/start systemd set-timezone.service
ansible.builtin.systemd_service:
name: set-timezone.service
daemon_reload: yes
enabled: true
state: started
#...
SELinux
Configure SELinux with ansible.posix.selinux…
- ansible.builtin.lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: 'SELINUX=disabled'
#...or...
- name: Disable SELinux
ansible.posix.selinux:
state: disabled
ansible.posix.seboolean …toggle SELinux booleans
community.general.seport …manages SELinux network port type definitions
# ...requirements needed on the host that executes this module
- name: install python packages for selinux
ansible.builtin.dnf:
name:
- python3-libselinux
- python3-policycoreutils
state: installed
# ...allow SSH to listen on another port
- name: Allow sshd to listen on tcp port 2849
community.general.seport:
ports: 2849
proto: tcp
setype: ssh_port_t
state: present
Containers
containers.podman module collection…
containers.podman.podman_image
…pull/build container imagescontainers.podman.podman_container
…manage container instances
---
- hosts: pxesrv_server
become: true
gather_facts: false
vars:
pxesrv_repo: /opt/pxesrv
pxesrv_root: /srv/pxesrv
tasks:
- name: Install dependency packages
ansible.builtin.dnf:
name:
- git
- podman
state: installed
- name: Clone PXESrv source code to {{pxesrv_repo}}
ansible.builtin.git:
repo: "https://github.com/vpenso/pxesrv"
dest: "{{pxesrv_repo}}"
# ...build a container image from the Dockerfile in the source code repository
- name: Build PXESrv container image in {{pxesrv_repo}}
containers.podman.podman_image:
state: build
force: true
name: pxesrv
path: "{{pxesrv_repo}}"
- name: Make sure {{pxesrv_root}} exists
ansible.builtin.file:
state: directory
path: "{{pxesrv_root}}"
# ...configure the container instance and create a systemd unit file
- name: Start PXESrv container
containers.podman.podman_container:
state: present
name: pxesrv
image: localhost/pxesrv:latest
log_opt:
path: /var/log/pxesrv.log
expose:
- 4567
volume:
- "{{pxesrv_root}}"
generate_systemd:
path: /etc/systemd/system
restart_policy: always
# ...make sure the container is started by the systemd unit
- name: Enable/start container-pxesrv.service
ansible.builtin.systemd_service:
name: container-pxesrv.service
enabled: true
state: started
Raw
Use ansible.builtin.raw
2 for an environment without a python
interpreter…
- Executes commands directly on the remote shell and returns standard output/error, and the return code
- Process the command standard output with
ansible.builtin.regex_search
3- …pattern matching is implemented with Python
re.search
4 - …regex can be conveniently tested on https://pythex.org/
- …pattern matching is implemented with Python
- Set variables with information extracted from the command output with
ansible.builtin.set_fact
5
---
- name: Update BIOS firmware
tags: bios_firmware
block:
- name: Gather output version information from the BMC
ansible.builtin.raw: 'ipmcget -d version'
register: ipmcget_version
- name: Extract the active BIOS version information
ansible.builtin.set_fact:
bios_version: "{{ ipmcget_version.stdout | ansible.builtin.regex_search(regex, '\\1', multiline=True) }}"
vars:
regex: '^Active BIOS[ ]*Version:[ (]*U[0-9]*[)](\d{1}\.\d{2}\.\d{2})'
- local_action: ansible.builtin.command scp {{role_path}}/files/fusion/2258V7/bios-2.09.17.hpm {{ansible_user}}@{{inventory_hostname}}:/tmp/bios-2.09.17.hpm
when: bios_version != "2.09.17"
Footnotes
Git Module, Ansible Community Documentation
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/git_module.html↩︎ansible.builtin.raw
module, Ansible Community Documentation
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/raw_module.html↩︎ansible.builtin.regex_search
module, Ansible Community Documentation
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/regex_search_filter.html↩︎re
Regular Expression Operations, Python Standard Library
https://docs.python.org/3/library/re.html↩︎ansible.builtin.set_fact
module, Ansible Community Documentation
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/set_fact_module.html↩︎