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 }}"
I have a problem in my playbook, actually I want to do a ping test on some Windows hosts and I want to send the result via Slack. I have done all of this now the problem is the message that I want to send is just the list of what is ok and what's not.
This is the role of the ping :
---
- name: get powershell version
ignore_unreachable: true
raw: $PSVersionTable
- name: ping
ignore_unreachable: true
win_ping:
register: ping_results
just to have a vision this is the ping_results output :
ok: [frsv000003.local.cloud.com] => {
"msg": {
"changed": false,
"failed": false,
"ping": "pong"
}
}
ok: [frsv000023.local.cloud.com] => {
"msg": {
"changed": false,
"failed": false,
"ping": "pong"
}
}
ok: [besv000075.local.cloud.com] => {
"msg": {
"changed": false,
"msg": "psrp connection failure during runspace open: Received a broken RunspacePoolState message: Requested registry access is not allowed.",
"skip_reason": "Host besv000075.local.cloud.com is unreachable",
"unreachable": true
}
}
ok: [frsv000007.local.cloud.com] => {
"msg": {
"changed": false,
"msg": "psrp connection failure during runspace open: Received a WSManFault message. (Code: 2150858811, Machine: 172.9.1.xxx, Reason: The WS-Management service cannot process the request. The resource URI (http://schemas.microsoft.com/powershell/Microsoft.PowerShell) was not found in the WS-Management catalog. The catalog contains the metadata that describes resources, or logical endpoints.)",
"skip_reason": "Host frsv000007.local.cloud.com is unreachable",
"unreachable": true
}
}
Now for the message to send for slack, I have created a condition to put hosts that are ok and non ok in two different lists
- name: set fact
set_fact:
ok_list: []
- name: set fact2
set_fact:
ok_list: "{{ ok_list + [item.value] }}"
when: item.value is match('pong')
with_dict: "{{ ping_results }}"
- name: set fact
set_fact:
nok_list: []
- name: set fact2
set_fact:
nok_list: "{{ nok_list + [item.value] }}"
when:
- item.value is not match('pong')
with_items: "{{ ping_results | dict2items }}"
The problem I got is this :
TASK [Hello-windows : Print variable ok] ***************************************
ok: [frsv000003.local.cloud.com] => {
"msg": [
"pong"
]
}
ok: [frsv000023.local.cloud.com] => {
"msg": [
"pong"
]
}
ok: [besv000075.local.cloud.com] => {
"msg": []
}
ok: [frsv000007.local.cloud.com] => {
"msg": []
}
I need to get only hostname to print it in Slack the problem is how to get these hosts from one list and without the empty values. Thanks.
Edited Part :
#larsks i will put this as a answer the inventory is based on ansible tower contains a lot of hosts like the first example :
frsv000003.local.cloud.com
frsv000004.local.cloud.com
frsv000005.local.cloud.com
frsv000006.local.cloud.com
frsv000007.local.cloud.com
frsv000008.local.cloud.com
frsv000009.local.cloud.com
frsv000010.local.cloud.com
...
For the playbook i use a role so the main file for the role is the same as you
- name: set ok_list
set_fact:
ok_list: "{{ ok_list + [item] }}"
when: hostvars[item].ping_results.ping|default('') == "pong"
loop: "{{ groups.all }}"
- name: set nok_list
set_fact:
nok_list: "{{ nok_list + [item] }}"
when: hostvars[item].ping_results.ping|default('') != "pong"
loop: "{{ groups.all }}"
- debug:
msg:
- "ok_list: {{ ok_list }}"
- "nok_list: {{ nok_list }}"
and also for the main file (not the role) i have this :
- name: Test windows Connectivity
hosts: all
gather_facts: no
vars:
ping_results:
slack_msg:
ok_list: []
nok_list: []
roles:
- Hello-windows
So when i run the job using jobtemplate with 5 hosts the problem is that i got a list like this means that the nok list contains all hosts :
TASK [Hello-windows : debug] ***************************************************
ok: [frsv000003.local.cloud.com] => {
"msg": [
"ok_list: [u'frsv000003.local.cloud.com', u'frsv000023.local.cloud.com']",
"nok_list: [u'frsv005207.local.cloud.com', u'frsv005336.local.cloud.com', u'uksv000232.local.cloud.com', u'frsv001871.local.cloud.com', u'frsv005090.local.cloud.com', u'frsv005333.local.cloud.com', u'frsv002043.local.cloud.com', u'frsv001811.local.cloud.com', u'frsv005150.local.cloud.com', u'frsv000928.local.cloud.com', u'frsv005529.local.cloud.com', u'frsv001606.local.cloud.com', u'frsv000236.local.cloud.com', u'frsv000929.local.cloud.com', u'frsv000363.local.cloud.com', u'frsv000539.local.cloud.com', u'frsv000653.local.cloud.com', u'frsv000508.local.cloud.com', u'frsv000654.local.cloud.com', u'frsv000205.local.cloud.com', u'frsv000632.local.cloud.com', u'frsv000516.local.cloud.com', u'frsv000427.local.cloud.com', u'frsv000137.local.cloud.com', u'frsv000466.local.cloud.com', u'frsv000324.local.cloud.com', u'frsv000974.local.cloud.com', u'frsv001451.local.cloud.com', u'frsv005432.local.cloud.com', u'besv005627.local.cloud.com',
]
}
ok: [frsv000023.local.cloud.com] => {
"msg": [
"ok_list: [u'frsv000003.local.cloud.com', u'frsv000023.local.cloud.com']",
"nok_list: [u'frsv005207.local.cloud.com', u'frsv005336.local.cloud.com', u'uksv000232.local.cloud.com', u'frsv001871.local.cloud.com', u'frsv005090.local.cloud.com', u'frsv005333.local.cloud.com', u'frsv002043.local.cloud.com', u'frsv001811.local.cloud.com', u'frsv005150.local.cloud.com', u'frsv000928.local.cloud.com', u'frsv005529.local.cloud.com', u'frsv001606.local.cloud.com', u'frsv000236.local.cloud.com', u'frsv000929.local.cloud.com', u'frsv000363.local.cloud.com', u'frsv000539.local.cloud.com', u'frsv000653.local.cloud.com', u'frsv000508.local.cloud.com', u'frsv000654.local.cloud.com', u'frsv000205.local.cloud.com', u'frsv000632.local.cloud.com', u'frsv000516.local.cloud.com', u'frsv000427.local.cloud.com', u'frsv000137.local.cloud.com', u'frsv000466.local.cloud.com', u'frsv000324.local.cloud.com', u'frsv000974.local.cloud.com', u'frsv001451.local.cloud.com', u'frsv005432.local.cloud.com', u'besv005627.local.cloud.com',
]
}
ok: [besv000075.local.cloud.com] => {
"msg": [
"ok_list: [u'frsv000003.local.cloud.com', u'frsv000023.local.cloud.com']",
"nok_list: [u'frsv005207.local.cloud.com', u'frsv005336.local.cloud.com', u'uksv000232.local.cloud.com', u'frsv001871.local.cloud.com', u'frsv005090.local.cloud.com', u'frsv005333.local.cloud.com', u'frsv002043.local.cloud.com', u'frsv001811.local.cloud.com', u'frsv005150.local.cloud.com', u'frsv000928.local.cloud.com', u'frsv005529.local.cloud.com', u'frsv001606.local.cloud.com', u'frsv000236.local.cloud.com', u'frsv000929.local.cloud.com', u'frsv000363.local.cloud.com', u'frsv000539.local.cloud.com', u'frsv000653.local.cloud.com', u'frsv000508.local.cloud.com', u'frsv000654.local.cloud.com', u'frsv000205.local.cloud.com', u'frsv000632.local.cloud.com', u'frsv000516.local.cloud.com', u'frsv000427.local.cloud.com', u'frsv000137.local.cloud.com', u'frsv000466.local.cloud.com', u'frsv000324.local.cloud.com', u'frsv000974.local.cloud.com', u'frsv001451.local.cloud.com', u'frsv005432.local.cloud.com', u'besv005627.local.cloud.com',
]
}
ok: [frsv000007.local.cloud.com] => {
"msg": [
"ok_list: [u'frsv000003.local.cloud.com', u'frsv000023.local.cloud.com']",
"nok_list: [u'frsv005207.local.cloud.com', u'frsv005336.local.cloud.com', u'uksv000232.local.cloud.com', u'frsv001871.local.cloud.com', u'frsv005090.local.cloud.com', u'frsv005333.local.cloud.com', u'frsv002043.local.cloud.com', u'frsv001811.local.cloud.com', u'frsv005150.local.cloud.com', u'frsv000928.local.cloud.com', u'frsv005529.local.cloud.com', u'frsv001606.local.cloud.com', u'frsv000236.local.cloud.com', u'frsv000929.local.cloud.com', u'frsv000363.local.cloud.com', u'frsv000539.local.cloud.com', u'frsv000653.local.cloud.com', u'frsv000508.local.cloud.com', u'frsv000654.local.cloud.com', u'frsv000205.local.cloud.com', u'frsv000632.local.cloud.com', u'frsv000516.local.cloud.com', u'frsv000427.local.cloud.com', u'frsv000137.local.cloud.com', u'frsv000466.local.cloud.com', u'frsv000324.local.cloud.com', u'frsv000974.local.cloud.com', u'frsv001451.local.cloud.com', u'frsv005432.local.cloud.com', u'besv005627.local.cloud.com',
]
}
PLAY RECAP *********************************************************************
besv000075.local.cloud.com : ok=3 changed=0 unreachable=1 failed=0 skipped=1 rescued=0 ignored=0
frsv000003.local.cloud.com : ok=10 changed=1 unreachable=0 failed=0 skipped=10 rescued=0 ignored=0
frsv000007.local.cloud.com : ok=3 changed=0 unreachable=1 failed=0 skipped=1 rescued=0 ignored=0
frsv000023.local.cloud.com : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Your problem is that ping_results isn't a list of results; it's a single result for a single host. When you run:
- name: ping
ignore_unreachable: true
win_ping:
register: ping_results
This runs once on each host, and registers a variable named
ping_results for that host. You can see that in your debug output.
To get two lists, one of hosts that were reachable and one of hosts
that were not, you would need a play that runs on a single host (e.g.,
localhost) and loops over all the target hosts to look up the
ping_results variable. For example:
- hosts: localhost
gather_facts: false
tasks:
- name: set ok_list
set_fact:
ok_list: "{{ ok_list + [item] }}"
when: hostvars[item].ping_results.ping|default('') == "pong"
vars:
ok_list: []
loop: "{{ groups.all }}"
- name: set nok_list
set_fact:
nok_list: "{{ nok_list + [item] }}"
when: hostvars[item].ping_results.ping|default('') != "pong"
vars:
nok_list: []
loop: "{{ groups.all }}"
- debug:
msg:
- "ok_list: {{ ok_list }}"
- "nok_list: {{ nok_list }}"
Running this with your sample data produces the following out:
PLAY [localhost] ***************************************************************
TASK [set ok_list] *************************************************************
ok: [localhost] => (item=frsv000003.local.cloud.com)
ok: [localhost] => (item=frsv000023.local.cloud.com)
skipping: [localhost] => (item=besv000075.local.cloud.com)
skipping: [localhost] => (item=frsv000007.local.cloud.com)
TASK [set nok_list] ************************************************************
skipping: [localhost] => (item=frsv000003.local.cloud.com)
skipping: [localhost] => (item=frsv000023.local.cloud.com)
ok: [localhost] => (item=besv000075.local.cloud.com)
ok: [localhost] => (item=frsv000007.local.cloud.com)
TASK [debug] *******************************************************************
ok: [localhost] => {
"msg": [
"ok_list: ['frsv000003.local.cloud.com', 'frsv000023.local.cloud.com']",
"nok_list: ['besv000075.local.cloud.com', 'frsv000007.local.cloud.com']"
]
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
And I think that's what you're looking for.
NB: I tested the above playbook using this inventory file in
hosts.yml:
all:
hosts:
frsv000003.local.cloud.com:
ansible_host: localhost
ping_results:
changed: false
failed: false
ping: pong
frsv000023.local.cloud.com:
ansible_host: localhost
ping_results:
changed: false
failed: false
ping: pong
besv000075.local.cloud.com:
ansible_host: localhost
ping_results:
changed: false
msg: "psrp connection failure during runspace open: Received a broken RunspacePoolState message: Requested registry access is not allowed."
skip_reason: "Host besv000075.local.cloud.com is unreachable"
unreachable: true
frsv000007.local.cloud.com:
ansible_host: localhost
ping_results:
changed: false
msg: "psrp connection failure during runspace open: Received a WSManFault message. (Code: 2150858811, Machine: 172.9.1.xxx, Reason: The WS-Management service cannot process the request. The resource URI (http://schemas.microsoft.com/powershell/Microsoft.PowerShell) was not found in the WS-Management catalog. The catalog contains the metadata that describes resources, or logical endpoints.)"
skip_reason: "Host frsv000007.local.cloud.com is unreachable"
unreachable: true
Running it like this:
ansible-playbook -i hosts.yml playbook.yml
I'm stuck to get data from gathered fact, using calculated data as part of query.
I am using 2.9 ansible and here is my task
---
- hosts: ios
connection: network_cli
gather_facts: true
tasks:
- name: CEF OUTPUT
ios_command:
commands: sh ip cef 0.0.0.0 0.0.0.0 | i nexthop
register: cef
- set_fact:
reg_result: "{{ cef.stdout |string| regex_search('Tunnel[0-9]+')}}"
- name: IT WORKS!
debug:
msg: "{{ reg_result }}"
- name: MANUAL LIST
debug:
var: ansible_facts.net_interfaces.Tunnel3.description
- name: AUTO LIST
debug:
var: ansible_facts.net_interfaces.[reg_result].description
and here is output
PLAY [ios] **********************************************
TASK [Gathering Facts] **********************************
ok: [10.77.3.1]
TASK [CEF OUTPUT] ***************************************
ok: [10.77.3.1]
TASK [set_fact] *****************************************
ok: [10.77.3.1]
TASK [IT WORKS!] ****************************************
ok: [10.77.3.1] => {
"msg": "Tunnel3"
}
TASK [MANUAL LIST] **************************************
ok: [10.77.3.1] => {
"ansible_facts.net_interfaces.Tunnel3.description": "DMVPN via MTS"
}
TASK [AUTO LIST] ****************************************
fatal: [10.77.3.1]: FAILED! => {"msg": "template error while templating string: expected name or number. String: {{ansible_facts.net_interfaces.[reg_result].description}}"}
to retry, use: --limit #/home/user/ansible/retry/ios_find_gw_int.retry
PLAY RECAP **********************************************
10.77.3.1 : ok=5 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
You see. Now I know that my default gateway is pointing to "Tunnel3", and it is possible to get some data placing this "Tunnel3" in {{ ansible_facts.net_interfaces.Tunnel3.description }} but how to get this automatically? And I feel such nested variable in the list is a very handy tool.
Remove the dot if you use the indirect addressing
- name: AUTO LIST
debug:
var: ansible_facts.net_interfaces[reg_result].description
See Referencing key:value dictionary variables.
I am using below code snippet where image details would be printed:
- set_fact:
image_name: "{{ load.results|map(attribute='stdout_lines')|list }}"
- debug:
var: image_name
Output:
TASK [set_fact] ***************************************************************************************************************************************************************************
ok: [xx.xx.xx.xx]
TASK [debug] ******************************************************************************************************************************************************************************
ok: [xx.xx.xx.xx] => {
"image_name": [
[
"Loaded image(s): localhost/cim:v1.5"
],
[
"Loaded image(s): localhost/cim:v1.8"
]
]
}
Is there a way I can store the image name and tag in two separate variables under set_fact itself or in any other form so I can reuse those 2 variables for the next task?
You can use a regex_findall filter in order to achieve this.
The regex used here is (\S*):(\S+). if needed, more explanation on it can be found here
Given the playbook:
- hosts: all
gather_facts: no
vars:
load:
results:
- stdout_lines:
- "Loaded image(s): localhost/cim:v1.5"
- stdout_lines:
- "Loaded image(s): localhost/cim:v1.8"
tasks:
- set_fact:
images: "{{ images | default([]) + item | regex_findall('(\\S*):(\\S+)') }}"
loop: "{{ load.results | map(attribute='stdout_lines') | flatten }}"
- debug:
msg: "This image repository is `{{ item.0 }}` and its tag is `{{ item.1 }}`"
loop: "{{ images }}"
This yields the recap:
PLAY [all] *********************************************************************************************************
TASK [set_fact] ****************************************************************************************************
ok: [localhost] => (item=Loaded image(s): localhost/cim:v1.5)
ok: [localhost] => (item=Loaded image(s): localhost/cim:v1.8)
TASK [debug] *******************************************************************************************************
ok: [localhost] => (item=['localhost/cim', 'v1.5']) => {
"msg": "This image repository is `localhost/cim` and its tag is `v1.5`"
}
ok: [localhost] => (item=['localhost/cim', 'v1.8']) => {
"msg": "This image repository is `localhost/cim` and its tag is `v1.8`"
}
PLAY RECAP *********************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
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]$