A collection of some of my useful Ansible Tips and Tricks.
In /etc/ansible/ansible.cfg
, under [defaults]
, add:
remote_user=<ansible-user>
interpreter_python=/usr/bin/python3
This will keep the output format.
ansible.builtin.debug: msg="{{ my_var.stdout_lines }}"
Note: To use the variable for other task, only my_var.stdout can be used.
When using when
condition with true/false option, it is better to use:
when: my_var | bool == true
instead of when: my_var == true
when: my_var | bool == false
instead of when: my_var == false
Giving 2 variables, var1
and var2
,
- to compare if their values are equal:
when: 'var1.stdout | string in var2.stdout'
- to compare if their values are NOT equal:
when: 'var1.stdout | string not in var2.stdout'
There are 2 ways to use a and operator for when
condition:
when: ansible_distribution=="Ubuntu" and my_var | bool
, OR- Listing:
when:
- ansible_distribution=="Ubuntu"
- my_var | bool
You can convert any variables to upper / lower cases respectively: {{ my_var | upper }}
OR {{ my_var | lower }}
{{ ansible_default_ipv4.address|default(ansible_all_ipv4_addresses[0]) }}
By default, handlers are only executed at the end of ALL tasks. To execute the handlers immediately, add the following task at the point you want to execute immediately:
- meta: flush_handlers
ansible_distribution
detects the OS correctly as compared to ansible_os_family
.
Using Ubuntu as an example, ansible_distribution
returns Ubuntu while ansible_os_family
returns Debian.
Often you need to execute your playbooks/tasks on specific OS distribution.
For CentOS / Red Hat, use when: ansible_distribution=="CentOS" or ansible_distribution=="RedHat"
.
For Debian / Ubuntu, use when: ansible_distribution=="Ubuntu" or ansible_distribution=="Debian"
.
Ansible detects Raspberry Pi OS as Debian. However, sometimes we need to perform specific Ansible tasks to Raspberry Pi OS.
To better detect Raspberry Pi OS, you can use the following:
when: ansible_distribution == "Debian" and ansible_architecture == "armv7l"
If a restart is required in a Linux instance, it will add a file: /var/run/reboot-required.
It contains the message *** System restart required ***
.
To check using Ansible:
- name: Check if restart is required
hosts: all
tasks:
- name: Check that the reboot-requied exists
ansible.builtin.stat:
path: /var/run/reboot-required
register: reboot_required
- ansible.builtin.debug:
msg: "Reboot required"
when: reboot_required.stat.exists
When triggering a playbook, you can overwrite any existing variable(s):
ansible-playbook playbook.yml --extra-vars "var1=abc var2=xyz"
With postfix service as an example, first populate all the services followed by starting/stopping/restarting postfix service:
- name: Populate service facts
ansible.builtin.service_facts:
- name: Restart postfix service
ansible.builtin.systemd:
name: postfix
state: restarted
when: "'postfix' in services"
With /etc/nginx.conf file as an example, first check /etc/nginx.conf file exists before updating that file:
- name: Check if /etc/nginx.conf exists
ansible.builtin.stat:
path: /etc/nginx.conf
register: nginx_conf_exists
- name: Update /etc/nginx.conf
ansible.builtin.lineinfile:
path: /etc/nginx.conf
...
when: nginx_conf_exists.stat.exists | bool == true
Modify the playbook to run locally on the server itself:
...
hosts: localhost
connection: local
...
Adhoc execute playbook by specifying host(s) and ssh credentials manually:
ansible-playbook -v test1.yml --inventory=<host1>,<host2>, --extra-vars "ansible_user=<user> ansible_password=<password> ansible_sudo_pass=<password>"
Note:
- USER is the variable.
{{ getent_passwd[USER][4] }}
is the variable that contains the user's home directory and can be used for other tasks.
- name: Get user's home directory
ansible.builtin.getent:
database: passwd
key: "{{ USER }}"
split: ":"
- name: Print user's home directory
ansible.builtin.debug:
msg: "{{ getent_passwd[USER][4] }}"
Kubernetes will be used as an example for this case.
The Ansible inventory will be configured as follows:
[k8s-master]
192.168.1.1
[k8s-workers]
192.168.1.2
192.168.1.3
[k8s:children]
k8s-master
k8s-workers
The following playbooks will get the variable from all the worker nodes and execute them on master node:
---
- name: Getting variable from other worker nodes and run on a master node
hosts: k8s
become: true
become_user: root
tasks:
- name: Getting variable from other worker nodes and run on a master node
ansible.builtin.command: "kubectl get node {{ ansible_hostname }}"
delegate_to: "{{ groups['k8s-master'][0] }}"
when: "'k8s-workers' in group_names"
For tags in import_tasks:
- import_tasks: my_task.yml
tags: "1"
For tags in include_tasks:
- include_tasks:
file: my_task_{{ ansible_distribution }}.yml
apply:
tags: "1"
tags: "1"
Reference: ansible/ansible#30882 (comment)