Reputation: 331
I have a role that creates a service that should bind to a unique port from within a specific range defined in a vars file.
---
ports:
- 9200
- 9201
- 9202
- 9203
- 9204
I do a quick check if these ports are bound already on the remote machine using wait_for
before executing the role:
- hosts: all
become: yes
vars_files:
- ports.yml
pre_tasks:
- wait_for:
host: 127.0.0.1
port: "{{ item }}"
state: started # Port should be open
delay: 0 # No wait before first check (sec)
timeout: 1 # Stop checking after timeout (sec)
ignore_errors: yes
register: echo
with_items: "{{ ports }}"
roles:
- azure_exporter
I would like to iterate through the ports, run the check above, and exits the loop once the port is found available. Then store that port in a variable and pass it to the role so that the service is gauranteed a unique port everytime the playbook executes.
I am stuck at finding a way to:
wait_for
when port is availableUpvotes: 2
Views: 878
Reputation: 39169
Exiting a loop in Ansible is not really something you can achieve, this said, you can skip values you don't want to process as soon has you have found the port you were looking for.
So what you can do is loop on your ports, and skip all other values as soon as there is indeed a port that is not present
. Then, with the rescue
of a block
, you can assign the port you found to a fact that you can then use later.
Given the playbook:
- hosts: all
gather_facts: no
pre_tasks:
- block:
- wait_for:
host: 127.0.0.1
port: "{{ item }}"
state: present
timeout: 1
register: ports_status
loop: "{{ ports }}"
when: ports_status is not defined or ports_status is not failed
vars:
ports:
- 9200
- 9201
- 9202
- 9203
- 9204
rescue:
- set_fact:
port: "{{ (ports_status.results | select('failed') | first).item }}"
tasks:
- debug:
var: port
PLAY [all] *******************************************************************************************************
TASK [wait_for] **************************************************************************************************
failed: [localhost] (item=9200) => changed=false
ansible_loop_var: item
elapsed: 1
item: 9200
msg: Timeout when waiting for 127.0.0.1:9200
skipping: [localhost] => (item=9201)
skipping: [localhost] => (item=9202)
skipping: [localhost] => (item=9203)
skipping: [localhost] => (item=9204)
TASK [set_fact] **************************************************************************************************
ok: [localhost]
TASK [debug] *****************************************************************************************************
ok: [localhost] =>
port: '9200'
PLAY RECAP *******************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0
9200
with a simple nc -l -p 9200
then it starts giving:
PLAY [all] *******************************************************************************************************
TASK [wait_for] **************************************************************************************************
ok: [localhost] => (item=9200)
failed: [localhost] (item=9201) => changed=false
ansible_loop_var: item
elapsed: 1
item: 9201
msg: Timeout when waiting for 127.0.0.1:9201
skipping: [localhost] => (item=9202)
skipping: [localhost] => (item=9203)
skipping: [localhost] => (item=9204)
TASK [set_fact] **************************************************************************************************
ok: [localhost]
TASK [debug] *****************************************************************************************************
ok: [localhost] =>
port: '9201'
PLAY RECAP *******************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0
Upvotes: 2