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!

REMOTE FILE CONTENTS
$ 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

  1. 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

 

  1. 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
  1. 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

 

SOLUTION IN SHELL
## 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

 

SOLUTION IN ANSIBLE
---
  - 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

Popular posts from this blog

java.lang.ExceptionInInitializerError while trying to Access login page

Solution to "End Program - WMS Idle"

WGET shell Script for downloading patches