Read a file and extract specific lines using Native Ansible Modules
I never realised that reading a file on a remote host and extracting specific lines from that file would be such an arduous task. As part of one of my projects, I had this requirement and without using "cat" or other shell utilities, it was quite cumbersome to read and extract the information that I was looking for. Read on to find out how it can be done using Ansible native commands.
Note that I have suggested only one out of a possible many methods. Feel free to explore yourself and update the comments here!
$ cat /tmp/IP_and_hostnames.txt $ cat /tmp/IP_and_hostnames.txt 192.168.230.165:example-host-1.example.com 192.168.230.166:example-host-2.example.com 192.168.230.167:example-host-3.example.com 192.168.230.175:example-host-1-vip.example.com 192.168.230.176:example-host-2-vip.example.com 192.168.230.177:example-host-3-vip.example.com 192.168.230.185:example-host-1-priv.example.com 192.168.230.186:example-host-2-priv.example.com 192.168.230.187:example-host-3-priv.example.com 192.168.230.195:oracle-rac-scan.example.com 192.168.230.196:oracle-rac-scan.example.com 192.168.230.197:oracle-rac-scan.example.com
REQUIREMENT
From the above file, fetch only the hostnames (with and without domain name and only hostnames that don’t contain the “-vip”, “-scan” and “-priv” strings) and the corresponding IP Addresses
- extract only the hostnames without “-vip”, “-scan” and “-priv” strings and without IP Address (see below)
example-host-1.example.com example-host-2.example.com example-host-3.example.com
- extract only the hostnames without domain and without “-vip”, “-scan” and “-priv” strings and without IP Address (see below)
example-host-1 example-host-2 example-host-3
- extract only the IP Addresses corresponding to the hostnames and without “-vip”, “-scan” and “-priv” strings (see below)
192.168.230.165 192.168.230.166 192.168.230.167
## Get the list of hosts (with and without the domain name) ## and the list of IP addresses and write to the temp hosts list file. IP_AND_HOSTNAMES_FILE=/tmp/IP_and_hostnames.txt DOMAIN_NAME=example.com TEMP_HOST_LIST_FILE=/tmp/specific_IP_and_hostnames.txt awk -F':' '! /scan/ && ! /priv/ && ! /vip/ {print $2}' ${IP_AND_HOSTNAMES_FILE} | sed -e "s,\.${DOMAIN_NAME},,g" >> ${TEMP_HOST_LIST_FILE} ## Hostnames without domain awk -F':' '! /scan/ && ! /priv/ && ! /vip/ {print $2}' ${IP_AND_HOSTNAMES_FILE} >> ${TEMP_HOST_LIST_FILE} ## Hostnames with domain awk -F':' '! /scan/ && ! /priv/ && ! /vip/ {print $1}' ${IP_AND_HOSTNAMES_FILE} >> ${TEMP_HOST_LIST_FILE} ## IP Addresses of hostnames
--- - hosts: all gather_facts: False vars: IP_AND_HOSTNAMES_FILE: /tmp/IP_and_hostnames.txt DOMAIN_NAME: example.com HOST_DETAILS_FILE: /tmp/specific_IP_and_hostnames.txt tasks: - name: Read the IP_AND_HOSTNAMES_FILE using slurp module ansible.builtin.slurp: src: "{{ IP_AND_HOSTNAMES_FILE }}" register: ip_and_hostnames_file_contents_in_base_64 - name: Print the output of the file - IP_AND_HOSTNAMES_FILE that was read using slurp - into register variable ip_and_hostnames_file_contents_in_plain_text debug: msg: "{{ ip_and_hostnames_file_contents_in_base_64['content'] | b64decode }}" register: ip_and_hostnames_file_contents_in_plain_text - name: Write the hosts with the domain name using the variable - ip_and_hostnames_file_contents_in_plain_text - to a file lineinfile: path: "{{ HOST_DETAILS_FILE }}" line: "{{ item.split(':')[1] }}" create: True with_items: "{{ ip_and_hostnames_file_contents_in_plain_text.msg.split('\n') }}" when: - "'scan' not in item" - "'priv' not in item" - "'vip' not in item" - "item != ''" - name: Write the hosts without the domain name using the variable - ip_and_hostnames_file_contents_in_plain_text - to a file lineinfile: path: "{{ HOST_DETAILS_FILE }}" line: "{{ item.split(':')[1].split('.')[0] }}" create: True with_items: "{{ ip_and_hostnames_file_contents_in_plain_text.msg.split('\n') }}" when: - "'scan' not in item" - "'priv' not in item" - "'vip' not in item" - "item != ''" - name: Write the IP Address of the RAC hosts using the variable - ip_and_hostnames_file_contents_in_plain_text - to a file lineinfile: path: "{{ HOST_DETAILS_FILE }}" line: "{{ item.split(':')[0] }}" create: True with_items: "{{ ip_and_hostnames_file_contents_in_plain_text.msg.split('\n') }}" when: - "'scan' not in item" - "'priv' not in item" - "'vip' not in item" - "item != ''"
Comments