This is a short quick tip about Ansible. TL;DR: it’s possible to use a wildcard in the target hosts specifier. This became useful to me when I dynamically created the inventory based on Ansible facts.
Date | Change description |
---|---|
2018-03-30 | The first release |
My scenario was, that I wanted to document the installation procedure of a tool I wrote. I needed to document that for at least CentOS and Ubuntu. That tool depends on operating system packages, which are named differently for Ubuntu and CentOS. To avoid that the documentation goes out of sync with reality, I decided to write Ansible code, which can be executed and therefore tested continuously, and include that code in my documentation.
To test that, I had a local Vagrant environment and wanted to ensure that
it works on Ubuntu 16.04 and CentOS 7.4 for the start.
As I expected that this will grow over time with different distributions
and each distribution with a set of major-minor releases, I wanted to
avoid to control the Ansible targets with an inventory file and also don’t
bind them to host names. So I decided to use the gather_facts
option,
to read specifics about the hosts, and dynamically group them based on
distribution, major release number, minor release number.
When doing that,
I discovered that the facts gather the major release number and the full
release number, which is 16.04
for Ubuntu, but 7.4.1708
for CentOS.
1 2 3 4 5 6 7 8 | [root@centos ~]# ansible localhost -m setup | grep ansible_distri
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.4.1708",
|
My expectation was, that I somehow get 7.4
, without the patch level,
but I couldn’t find a way. I also wanted to avoid to do string split magic
in Ansible.
As I was worried that I have to change the playbook when the patch level
changes when updating the CentOS 7 Vagrant Box I wanted to have a way
to ignore the patch level. And apparently, Ansible can do that with a
wildcard *
in the target hosts specifier. I ended up with this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ---
- hosts: all
become: true
gather_facts: true
tasks:
- name: "Group the servers by operating system and version."
group_by:
key: os_{{ ansible_distribution }}_{{ ansible_distribution_version }}
- hosts: os_Ubuntu_16.04
become: true
tasks:
- include: ubuntu_1604_install_tasks.yml
- hosts: os_CentOS_7.4*
become: true
tasks:
- include: centos_74_install_tasks.yml
|
The specifier os_CentOS_7.4*
accepts, that the actual key is
os_CentOS_7.4.1708
, which solves my problem perfectly.
For my user documentation with Sphinx I could then do this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Below are examples of *Ansible tasks*, which show the operating system
dependencies which must be fulfilled.
Ubuntu 16.04
------------
.. literalinclude:: ubuntu_1604_install_tasks.yml
:language: yaml
CentOS 7.4
----------
.. literalinclude:: centos_74_install_tasks.yml
:language: yaml
|
This enables me to only document working examples, which can easily be changed. Either by adding a new target, or removing a target which reached its end of life or support level.
For details about Sphinx you can read my previous post Project documentation with reStructuredText and Sphinx. I thought this might be worth sharing.