A common task one might want Ansible to perform is to create an /etc/hosts file. This is trivial using Ansible’s lineinfile module.
The problem
A question came up on Stack Overflow today (since removed) which I felt I could contribute to. The member wanted to know how to generate /etc/hosts using a MySQL database and a dynamic inventory script. I do not address the dynamic inventory aspects in this post, but producing /etc/hosts from an Ansible variable is quite trivial using the lineinfile module.
In the modern, connected, world we now live in, the need for servers and desktops to maintain their own lists of hosts in /etc/hosts is rarely required. DNS etc is all we need. Maintaining a hosts file is necessary when working on isolated networks with no DNS. I have plenty of experience doing this for my clients at Discreet Information Technology Services.
The solution – Ansible’s lineinfile module
Unfortunately Ansible doesn’t have a built in module specifically designed to manage /etc/hosts but we can use Ansible’s lineinfile module to output lines to the hosts file. Perhaps I should write one?.
For demo purposes, the Ansible playbook extract I present below uses an inline task variable containing an array of dictionaries. This could also be located in the play variables, Ansible’s host vars file or the group vars file. Each dictionary in the array contains two keys ip
and names
. Needless to say ip
contains an IP address and names
is an array of host names for the associated IP address.
- name: add a list of hosts to /etc/hosts become: yes lineinfile: dest: /etc/hosts regexp: "^{{ item['ip'] }}.*$" line: "{{ item['ip'] }}\t\t{{ item['names'] | join(' ') }}" state: present with_items: - ip: 1.2.3.4 names: - server1 - ip: 4.5.6.7 names: - server2a - server2b
We start by setting the destination file – /etc/hosts, define a regular expression that matches the format of the line we are planning on outputting so we can delete them later, the format of the line we want added to the file, in this case using a Jinja template, and finally make sure the line is present using the state: present
option. The output for this task will be lines added to the hosts file in the following format:
1.2.3.4 server1 4.5.6.7 server2a server2b