Extract IP addresses from a text file with other values - ansible

Let's say you have a variable file on your localhost. We can call it values.txt, and its contents are:
isjwidywiudywdiuwqoq10.110.195.108xxsxww/ed/swqqwfdfwef8.8.8.8
You want to extract only the IP address values from all of this junk. I have made multiple attempts at this using the file lookup and the ipaddr filter. What I'm doing looks like this:
- name: extract IPs only
debug:
msg: "{{ query('file', 'values.txt') | ipaddr }}"
However, this does not work! How can I go about doing this to where I get only the IP's?

You can do this with a regular expression filter. To extract all the ip addresses from a string, it sounds like you want to find everything that matches [0-9]+\.[0-9]+\.[0-9]+\.[0-9]). To extract all matches of an expression from a string, Ansible provides us with the regex_findall filter.
For example:
- hosts: localhost
gather_facts: false
tasks:
- debug:
msg: >-
{{ "isjwidywiudywdiuwqoq10.110.195.108xxsxww/ed/swqqwfdfwef8.8.8.8" | regex_findall("[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+") }}
The above playbook will output:
TASK [debug] ******************************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"10.110.195.108",
"8.8.8.8"
]
}

Here's one example
# // Ansible playbook to Extract IP addresses from a text file
- hosts: localhost
gather_facts: false
tasks:
- name: Extract IP addresses from a text file
set_fact:
ips: "{{ lookup('file', '/tmp/tmpdir/test.txt') | regex_findall('(?<!\\d)(?:\\d{1,3}\\.){3}\\d{1,3}(?!\\d)') }}"
register: result
- debug:
msg: "{{ result }}"
Sample run
╰─ cat test.txt
hello
12.14.34.45asdfadsf234234
asdfasldfkj23.34.45.23alsdjfwerk
fafn aslkdfj vahsdifadk 23.43.34.232 asldkvvnasdfads
╰─ ansible-playbook test.yaml
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ********************************************************************************************************************************************************************************
TASK [Extract IP addresses from a text file] ****************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": {
"ansible_facts": {
"ips": [
"12.14.34.45",
"23.34.45.23",
"23.43.34.232"
]
},
"changed": false,
"failed": false
}
}
PLAY RECAP **************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

Related

Fetch hosts without domain from inventory file

I have following inventory file
$ cat hosts
[web]
server1.example.com
server2.example.com
I would like to fetch the hostname, without the part of domain (.example.com).
I tried with the following playbook, however, it is still fetching with the entire hostname..
$ playbook.yaml
- hosts: localhost
tasks:
- debug:
msg: "{{ groups['web'] }}"
Output
PLAY [localhost] *************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [localhost]
TASK [debug] *****************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"server1.example.com"
"server2.example.com"
]
}
PLAY RECAP *******************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Expected output
PLAY [localhost] *************************************************************************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************************************************************************
ok: [localhost]
TASK [debug] *****************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
"server1"
"server2"
]
}
PLAY RECAP *******************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You can get what you want from a magic variable called inventory_hostname_short which basically returns anything before the first . found in the inventory_hostname.
To get this in a normal play host loop, it's as easy as:
- hosts: all
tasks:
- name: show target short name
debug:
var: inventory_hostname_short
If you need to get that for hosts not in the host loop, you will have to go through hostvars. Here is an example to get all those names in a list for a given group running from localhost:
- hosts: localhost
gather_facts: false
tasks:
- name: show list of shortnames for group 'toto'
debug:
msg: "{{ groups['toto'] | map('extract', hostvars, 'inventory_hostname_short') }}"
An other example to get that name only for the first server in group 'toto'
- hosts: localhost
gather_facts: false
tasks:
- name: show shortnames for first server in group 'toto'
vars:
server_name: "{{ groups['toto'][0] }}"
debug:
msg: "{{ hostvars[server_name].inventory_hostname_short }}"

Ansible hosts to be set to a substring of a passed variable

I have a play like this:
- name: Perform an action on a Runtime
hosts: all
roles:
- role: mule_action_on_Runtime
A variable at invocation (--extra-vars 'mule_runtime=MuleS01-3.7.3-Testing') has a prefix of the host needed (MuleS01). I want to set hosts: MuleS01. How do I do this?
Given that your pattern is always PartIWant-PartIDonCareAbout-AnotherPartAfterOtherDash you could use the split method of Python, then get the first item of the list via the Jinja filter first.
Here is full working playbook as example:
- hosts: local
gather_facts: no
tasks:
- debug:
msg: "{{ mule_runtime.split('-') | first }}"
This yield the recap:
play.yml --extra-vars 'mule_runtime=MuleS01-3.7.3-Testing'
PLAY [local] *******************************************************************
TASK [debug] *******************************************************************
ok: [local] => {
"msg": "MuleS01"
}
PLAY RECAP *********************************************************************
local : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
With the inventory
shell> cat hosts
MuleS01
MuleS02
MuleS03
this playbook
shell> cat pb.yml
- hosts: all
tasks:
- debug:
msg: Set {{ mule_runtime }}
when: mule_runtime.split('-').0 == inventory_hostname
gives
skipping: [MuleS02]
ok: [MuleS01] => {
"msg": "Set MuleS01-3.7.3-Testing"
}
skipping: [MuleS03]

Ansbile get the substring from task output

I have this URL string server https://test.example.com:6443. I need to extract only hostname test from it using Ansible task.
came up with this playbook, Is there a better way of doing this with-out using sed?
- hosts: localhost
connection: local
gather_facts: no
tasks:
- name: get the URL
shell: echo 'server https://test.example.com:6443' |sed -e 's/^.*https...//' -e 's/\..*$//'
register: result
- name: Print the var
debug:
msg: "{{ result.stdout }}"
Output
PLAY [localhost] *********************************************************************************************************************
TASK [get the URL] *******************************************************************************************************************
changed: [localhost]
TASK [Print the var] *****************************************************************************************************************
ok: [localhost] => {
"msg": "test"
}
PLAY RECAP ***************************************************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You can use split on the URL name and get the desired value, Ideally hostname should be test.example.com in your case. However, you can customize the split function based on your need also as below.
- hosts: localhost
connection: local
gather_facts: no
vars:
url: "https://test.example.com:6443"
tasks:
- name: Print the hostname var
debug:
msg: "{{ url.split(':')[1].split('//')[1] }}"
- name: Print the subdomain prefix
debug:
msg: "{{ url.split(':')[1].split('//')[1].split('.')[0] }}"

ansible: create a list from comma separated string

I want to create a list from comma separated string to pass to loop in ansible, sometime variable can have only one value also
var1=test1,test2 and it can be var1=test1 also
here is my code
- name: Separate facts
set_fact: groups="{{ var1.split(',') }}"
- name: delete
gcp_compute_instance_group:
name: "{{ item }}"
zone: xxx
project: xxx
auth_kind: serviceaccount
service_account_file: xxx
state: absent
loop: "{{ groups }}"
this doesn't work, how can i achieve my requirement
your filter is correct, you do get a list variable. please see below PB and output:
---
- hosts: localhost
gather_facts: false
vars:
var1: test1,test2
var2: test3
tasks:
- name: Create the list
set_fact:
list_var1: "{{ var1.split(',') }}"
list_var2: "{{ var2.split(',') }}"
- debug:
var: list_var1
- debug:
var: list_var2
result:
[is#orangehat-29 temp]$ ansible-playbook test.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [localhost] ***********************************************************************************************************************************************************************************************************************
TASK [Create the list] *****************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"list_var1": [
"test1",
"test2"
]
}
TASK [debug] ***************************************************************************************************************************************************************************************************************************
ok: [localhost] => {
"list_var2": [
"test3"
]
}
PLAY RECAP *****************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[is#orangehat-29 temp]$

Ansible json_query outputs list when using a filter expression

I'm running ansible 2.4.0 on OSX.
The following playbook...
---
- hosts: localhost
connection: local
gather_facts: False
vars:
data:
- name: thing1
desc: I am thing 1
- name: thing2
desc: I am thing 2
tasks:
- debug: msg="{{ data|json_query(\"[1].desc\") }}"
- debug: msg="{{ data|json_query(\"[?name=='thing2'].desc\") }}"
Produces the following output:
PLAY [localhost] ***************************************************************
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": "I am thing 2"
}
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
"I am thing 2"
]
}
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
My question is, why, in the second debug task is the output in a list ([])?
You can add ansible filter first, like so:
tasks:
- debug: msg="{{ data | json_query(\"[?name=='thing2'].desc\") | first }}"
It'll return scalar value.
That's because in JMESPath, which is the implementation behind json_query, an index expression is defined to always return a single value, possibly null (see [1]).
While for the filter expression, which is a projection, an array is assumed to be returned after evaluating the LHS of your query, which may be empty in case no values are matched (see: [2]).

Resources