So, I have a playbook using a hosts file template to update or revert hosts files on 18 specific Linux VMs. The entry which goes at the end of the file looks like:
10.x.x.66 fooconnect
This above example would be on the 1st of 18 VMs, the 18th VM would look like:
10.x.x.83 fooconnect
Normally, that hostname resolves to a VIP. However, we found during some load testing that it may be beneficial to point each front-end VM to a back-end VM directly. So, my goal is to have a playbook that can update what the hostname resolves to with the above mentioned range, or revert it back to the VIP (reverting back is done using a template only--this part works fine).
What I am unsure about is how to implement this in Ansible. Is there a way to loop through the IPs using jinja2 template "for loops?" Or maybe using lineinfile with some loop magic?
Here is my Ansible role example. For the moment I am using a dirty shell command to create my IP list...open to suggestions for a better way to implement this.
- name: Add a line to a hosts file using a template
template:
src: "{{ srcfile }}"
dest: "{{ destfile }}"
owner: "{{ own_var }}"
group: "{{ grp_var }}"
mode: "{{ mode_var }}"
backup: yes
- name: Get the IPs
shell: "COUNTER=66;for i in {66..83};do echo 10.x.x.$i;((COUNTER++));done"
register: pobs_ip
- name: Add a line
lineinfile:
path: /etc/hosts
line: "{{item}} fooconnect" #Ideally would want "item" to just be one IP and not
insertafter: EOF #the entire list as it would be like this.
loop: "{{pobsips}}"
VARs file:
pobsips:
- "{{pobs_ip.stdout}}"
Instead of using a shell
task, we can improvise it and create the range of IP addresses using set_fact
with range
. Once we have the range of IP addresses in a "list", we can loop lineinfile
with that and achieve this.
Example:
- name: create a range of IP addresses in a variable my_range
set_fact:
my_range: "{{ my_range|default([]) + [ '10.1.1.' ~ item ] }}"
loop: "{{ range(66, 84)|list }}"
- name: Add a line to /etc/hosts
lineinfile:
path: /etc/hosts
line: "{{ item }} fooconnect"
insertafter: EOF
loop: "{{ my_range }}"
Updated answer:
There is another approach if we want to append only 1 line into the /etc/hosts
file of each host with incrementing IP addresses.
ipmath
of ipaddr filter to get the next IP address for given IP address.ansible_play_hosts
to get the list of hosts on which play is runningindex_var
and when
condition to update file only when the ansible_hostname
or inventory_hostname
matches.serial
and run_once
flags.Let's consider an example inventory file like:
[group_1]
host1
host2
host3
host4
...
Then in playbook:
- hosts: group_1
serial: 1
vars:
start_ip: 10.1.1.66
tasks:
- name: Add a line to /etc/hosts
lineinfile:
path: "/tmp/hosts"
line: "{{ start_ip|ipmath(my_idx) }} fooserver"
insertafter: EOF
loop: "{{ ansible_play_hosts }}"
loop_control:
index_var: my_idx
run_once: true
when: item == inventory_hostname