How to use Ansible module 'wait_for' together with 'loop'?
Question:
In Ansible 2.7.11 and wanted to use the module waif_for together with loops for connection test to my System Center Operations Manager (SCOM) servers.
Currently I’m using a task
- name: "Test connection to SCOM_MGMT_SRV_PROD: {{ SCOM_MGMT_SRV_PROD }}"
wait_for:
host: "{{ item }}"
port: "{{ SCOM_PORT }}"
state: drained # Port should be open
delay: 0 # No wait before first check (sec)
timeout: 3 # Stop checking after timeout (sec)
active_connection_states: SYN_RECV
with_items:
- server1
- server2
- server3
- server4
ignore_errors: yes
tags: connectionTest,testSCOM
where the variable SCOM_PORT
is set to 1270
and SCOM_MGMT_SRV_PROD
to a list of servers "server1,server2,server3,server4"
.
This approach is working but I wanted to have a variable list of servers maintained at a central place, like a global variable SCOM_MGMT_SRV_PROD
in inventory file.
It is possible to iterate over such a list via
- debug:
msg="{{ item }}"
loop: "{{ [SCOM_MGMT_SRV_PROD] }}"
but when using this approach in the task
- name: "Test connection to SCOM_MGMT_SRV_PROD: {{ SCOM_MGMT_SRV_PROD }}"
wait_for:
host: "{{ item }}"
port: "{{ SCOM_PORT }}"
state: drained # Port should be open
delay: 0 # No wait before first check (sec)
timeout: 3 # Stop checking after timeout (sec)
active_connection_states: SYN_RECV
loop: "{{ [SCOM_MGMT_SRV_PROD] }}"
ignore_errors: yes
tags: connectionTest,testSCOM
I’m getting an error
failed: [host] (item=server1,server2,server3,server4) => ... /tmp/ansible_wait_for_payload_zNj2ac/__main__.py", line 380, in _convert_host_to_hexrn File "/tmp/ansible_wait_for_payload_zNj2ac/__main__.py", line 354, in _convert_host_to_iprnsocket.gaierror: [Errno -2] Name or service not knownrn", "msg": "MODULE FAILUREnSee stdout/stderr for the exact error", "rc": 1}
which for me indicates that the module wait_for
got the full list as item instead of one server from the list. The reason for the described behavior seems to be answered @https://stackoverflow.com/questions/48351187/.
Any idea how to get the module wait_for
working with a variable list of servers?
Other Components
Answers:
After consulting with colleagues it turned out that the list (of servers) wasn’t defined correctly in inventory, just a classical syntax error. Please see Ansible, how to define a list in host inventory?.
To get it working it is necessary to define in inventory file the variable as
SCOM_MGMT_SRV_PROD="['server1','server2','server3','server4']"
instead of an just comma separated list of strings and use for loop
loop: "{{ SCOM_MGMT_SRV_PROD }}"
By doing this I’ve realized that actually the debug message wasn’t iterating over the list either. Now it is working properly
TASK [debug] ************************************************************************************************************************
ok: [host] => (item=server1) => {
"msg": "server1"
}
ok: [host] => (item=server2) => {
"msg": "server2"
}
ok: [host] => (item=server3) => {
"msg": "server3"
}
ok: [host] => (item=server4) => {
"msg": "server4"
}
TASK [Test connection to SCOM_MGMT_SRV_PROD: ['server1','server2','server3','server4']] ***
ok: [host] => (item=server1)
ok: [host] => (item=server2)
ok: [host] => (item=server3)
ok: [host] => (item=server4)
Meanwhile I’ve found out also that it is possible to Looping over inventory and if I use
with_items: "{{ groups['SCOM_MGMT_SRV_PROD'] }}"
together with a group in inventory file
[SCOM_MGMT_SRV_PROD]
server1
server2
server3
server4
Since the monitoring servers are not part of infrastructure which is maintained by Ansible, Linux admins, etc., I do not like to include them in the inventory other than in a variable.
Are there any other options to loop over a variable list of servers? … if not, it might be necessary to go with this as solution.
In Ansible 2.7.11 and wanted to use the module waif_for together with loops for connection test to my System Center Operations Manager (SCOM) servers.
Currently I’m using a task
- name: "Test connection to SCOM_MGMT_SRV_PROD: {{ SCOM_MGMT_SRV_PROD }}"
wait_for:
host: "{{ item }}"
port: "{{ SCOM_PORT }}"
state: drained # Port should be open
delay: 0 # No wait before first check (sec)
timeout: 3 # Stop checking after timeout (sec)
active_connection_states: SYN_RECV
with_items:
- server1
- server2
- server3
- server4
ignore_errors: yes
tags: connectionTest,testSCOM
where the variable SCOM_PORT
is set to 1270
and SCOM_MGMT_SRV_PROD
to a list of servers "server1,server2,server3,server4"
.
This approach is working but I wanted to have a variable list of servers maintained at a central place, like a global variable SCOM_MGMT_SRV_PROD
in inventory file.
It is possible to iterate over such a list via
- debug:
msg="{{ item }}"
loop: "{{ [SCOM_MGMT_SRV_PROD] }}"
but when using this approach in the task
- name: "Test connection to SCOM_MGMT_SRV_PROD: {{ SCOM_MGMT_SRV_PROD }}"
wait_for:
host: "{{ item }}"
port: "{{ SCOM_PORT }}"
state: drained # Port should be open
delay: 0 # No wait before first check (sec)
timeout: 3 # Stop checking after timeout (sec)
active_connection_states: SYN_RECV
loop: "{{ [SCOM_MGMT_SRV_PROD] }}"
ignore_errors: yes
tags: connectionTest,testSCOM
I’m getting an error
failed: [host] (item=server1,server2,server3,server4) => ... /tmp/ansible_wait_for_payload_zNj2ac/__main__.py", line 380, in _convert_host_to_hexrn File "/tmp/ansible_wait_for_payload_zNj2ac/__main__.py", line 354, in _convert_host_to_iprnsocket.gaierror: [Errno -2] Name or service not knownrn", "msg": "MODULE FAILUREnSee stdout/stderr for the exact error", "rc": 1}
which for me indicates that the module wait_for
got the full list as item instead of one server from the list. The reason for the described behavior seems to be answered @https://stackoverflow.com/questions/48351187/.
Any idea how to get the module wait_for
working with a variable list of servers?
Other Components
After consulting with colleagues it turned out that the list (of servers) wasn’t defined correctly in inventory, just a classical syntax error. Please see Ansible, how to define a list in host inventory?.
To get it working it is necessary to define in inventory file the variable as
SCOM_MGMT_SRV_PROD="['server1','server2','server3','server4']"
instead of an just comma separated list of strings and use for loop
loop: "{{ SCOM_MGMT_SRV_PROD }}"
By doing this I’ve realized that actually the debug message wasn’t iterating over the list either. Now it is working properly
TASK [debug] ************************************************************************************************************************
ok: [host] => (item=server1) => {
"msg": "server1"
}
ok: [host] => (item=server2) => {
"msg": "server2"
}
ok: [host] => (item=server3) => {
"msg": "server3"
}
ok: [host] => (item=server4) => {
"msg": "server4"
}
TASK [Test connection to SCOM_MGMT_SRV_PROD: ['server1','server2','server3','server4']] ***
ok: [host] => (item=server1)
ok: [host] => (item=server2)
ok: [host] => (item=server3)
ok: [host] => (item=server4)
Meanwhile I’ve found out also that it is possible to Looping over inventory and if I use
with_items: "{{ groups['SCOM_MGMT_SRV_PROD'] }}"
together with a group in inventory file
[SCOM_MGMT_SRV_PROD]
server1
server2
server3
server4
Since the monitoring servers are not part of infrastructure which is maintained by Ansible, Linux admins, etc., I do not like to include them in the inventory other than in a variable.
Are there any other options to loop over a variable list of servers? … if not, it might be necessary to go with this as solution.