Note: This section requires a new server running a different distribution. As such, I've added an Ubuntu server to our mix. We now have ubuntu1 (192.168.6.30) that we will add to our inventory file.
Since we would like to run commands that do effectively the same thing to servers running different distributions, and those distributions use different commands to accomplish the same task, we will need a way to instruct Ansible to run different commands on different distributions. This is where the 'when' clause comes in handy. In fact, there are a few things we need to know:
- How do we identify the different distributions?
- How do we tell Ansible about the target distribution?
- How do we tell Ansible about each command we need to run?
It turns out, we have already done this. Ansible's gather-facts module captures a great deal of data about each host that is a target for Ansible automation. Among the details in the gather-facts output is one called ansible_distribution, which captures the OS's common name. After adding the new IP address to our inventory file, we can tell Ansible to gather facts from our inventory, and use grep to filter out anything except the ansible_distribution keyword:
[ansadm@rocky-1 ansible]$ ansible all -m gather_facts | grep ansible_distribution\""ansible_distribution": "Ubuntu",
"ansible_distribution": "Rocky",
"ansible_distribution": "Rocky",
(There are multiple facts that begin with "ansible_distribution." We only want the literal ansible_distribution, excluding things such as ansible_distribution_somevalue, so we add an escaped quote to the end of the string to filter out any thing where the character after 'distribution' is not a quote.) This answers question 1 above. We can use the strings Rocky and Ubuntu to identify which distribution each host is running.
To instruct Ansible to target one distribution or the other, we add the string above to the when clause:
- name: Install Nginx Web Service
dnf:
name: nginx
state: latest
when: ansible_distribution == "Rocky"
This would have no effect on our playbook, until after we add the Ubuntu server to the inventory file, as both of our servers, rocky-2 and rocky-3 are Rocky servers. Once we add the Ubuntu server, we'll see the command execute with the Ubuntu server being skipped:
![]() |
Figure 6.1: Ubuntu servers are skipped for all tasks targeted toward Rocky servers. |
We have now addressed the second question, instructing Ansible what to do with the string to target a specific distribution.
We still want to install Nginx on the Ubuntu server, so we'll need to do some additional work which involves answering question 3 above. Since Ubuntu uses a different command to handle package management (apt), we now need two commands to update the cache, and two commands to install Nginx. This will double the size of our playbook, but will then make it distribution-independent (well, at least as long as we use only RHEL and Debian downstream distributions). Here is the example with just the cache update tasks:
- name: Update RHEL/Rocky/CentOS Repo Cache
dnf:
update_cache: true
when: ansible_distribution == "Rocky"
- name: Update Debian/Ubuntu Repo Cache
apt:
update_cache: true
when: ansible_distribution == "Ubuntu"
The authors of Ansible maintained the same name for the action (update_cache) between the two distributions, but we do need to tell it which distribution employs which command, thus the dnf and apt commands are used explicitly in each task.
One more change is required to our playbook for this to work. The packages provided by each distribution are rarely named the same. So, we need to be explicit with Ansible about what it is we want to install. Rocky Linux uses "nginx" as the package name, and Ubuntu uses "nginx-core." Following demonstrates the change:
- name: Install Nginx Web Service
dnf:
name: nginx
state: latest
when: ansible_distribution == "Rocky"
- name: Install Nginx Web Service
apt:
name: nginx-core
state: latest
when: ansible_distribution == "Ubuntu"
Now, when we run our playbook, dnf will be used to update the cache on any Rocky server, apt will be used on any Ubuntu server, and each distribution will be requested to install Nginx using the distribution-specific package name. This shows in the output as Ubuntu servers being skipped over when using the dnf command, and likewise, the Rocky servers will be skipped over when using the apt command. Figure 6.2 shows this (though for additional tasks):
![]() |
Figure 6.2: Results of running our updated playbook. |
No comments:
Post a Comment