Ansible wait_for module examples - How to | Devops Junction

Introduction to Ansible wait_for module

Ansible wait_for module can be used to pause your playbook execution and to wait for many different things or conditions before continuing with the execution. The wait_for module of ansible is to make your playbook or task execution halt or pause for various reasons and for numerous conditions.

You can compare it with the sleep of any given programming language but it is more than that. Yes, it does have a conditional validation.

Take our real-life examples.

We Sleep When we are expecting our friend who is always late, We Sleep till mom kicks us out of bed, We Sleep till our spouse spill water at our face and angrily say "WAKE UP"

Besides all,  there are few like me. We Sleep for no specific reason.

Ansible Wait_for module is capable to make your playbook Sleep for no specific reason ( Simply Sleep) as well as while we wait for something ( A Conditional Sleep)

Like people, Our playbooks also have different conditions to wait for and sleep and we have listed some of the most known and used conditions where ansible playbook has to go sleep or wait for.

ansible wait_for examples

  • wait_for the port to be available or not available
  • wait_for the file to be created with a state, present or absent
  • wait_for some period of time, Simply sleep for a specified time (in seconds)
  • wait_for the server to come up or get rebooted.
  • wait_for a String to be available in the log file  Like Log Parsing or Searching 
  • wait_for SSH to be ready at the remote servers

 

 

We are going to see all these aforementioned usage scenarios (or) test cases of ansible wait_for module with the examples (playbooks) I have written. one by one.

 

Ansible wait_for examples

We have given short snippets of ansible task and playbooks for each of the aforementioned scenarios.

These are examples we have covered in this post

  1. ansible wait_for the port to open
  2. ansible wait_for the port to close
  3. ansible wait_for the port to drain and close active connections
  4. ansible Wait_for file to be created
  5. ansible Wait_for file to be deleted or lock file to be removed
  6. ansible wait_for seconds or sleep for seconds
  7. ansible Wait_for reboot ( wait_for SSH )
  8. ansible Wait_for the string to be available in the log file
  9. ansible wait_for the process to finish

 

Ansible wait for the port to open

Using ansible wait_for module along with host and port, we can wait a maximum of timeout seconds for the port to be available or not available.

Consider the following task snippet which waits for the port to be available.  Actually, this task is validating if the server has come up and RUNNING by validating that the port is open.

The Playbook Snippet

- name: Validating if the WebServer is UP and OPENED the PORT
    tags: amvalidate1
    wait_for:
        host: "{{inventory_hostname}}"
        port: "{{webserver_port}}"
        delay: 10
        timeout: 30
        state: started
        msg: "WebServer PORT is not Listening"
    when: ansible_hostname == "{{inventory_hostname}}"
    register: amvalidate1
    ignore_errors: true

Explanation:

host: The Hostname
port: The port to listen
delay: Delay in seconds before starting the validation
timeout: timeout after defined seconds.
state:  Make sure the Port if OPEN
msg: A Custom message to be printed in case of failure after the allocated time(timeout) elapsed.

While the previous snippet was designed to run in the remote node, Here we present another way around to accomplish the same using local_action module.

Running the same task Local ( An Another Approach)

The Playbook Snippet ( local_action)

- name: Wait for webserver to start.
  local_action: 
    module: wait_for
    host: "{{ inventory_hostname }}"
    port: "{{ webserver_port }}"
    delay: 10
    timeout: 300
    state: started

 

 

ansible wait for the port to close

If you modify the playbook given in Example 1 a little bit. you would be able to achieve the requirement of waiting till the port to close

- name: Validating if the WebServer port is closed.
    tags: amvalidate1
    wait_for:
        host: "{{inventory_hostname}}"
        port: "{{webserver_port}}"
        delay: 10
        timeout: 30
        state: stopped
        msg: "WebServer PORT is not yet stopped"
    when: ansible_hostname == "{{inventory_hostname}}"
    register: amvalidate1
    ignore_errors: true

 

ansible wait_for the port to drain and close active connections

you can wait_for the port to drain its active connections (or) close its active connections  using the state: drained argument

- name: Validating if the port is drained 
    tags: portvalidate
    wait_for:
        host: "{{inventory_hostname}}"
        port: "{{webserver_port}}"
        delay: 10
        timeout: 30
        state: drained

 

 

ansible Wait_for file to be created

The following task snippet is to validate if the file is present in other it will validate if the file is created already using state: present

If you change the state argument of wait_for to state: absent it will make sure that the file is not present (absent) in other words removed or deleted.

The Playbook Snippet

- name: Making sure that the Log file is present in the corresponding directory
  tags: filepresensevalidation
  register: filepresensevalidation
  wait_for:
    path:  "{{logfile}}"
    delay: 10
    timeout: 30
    state: present
    msg: "Specified LOG FILE is not present"
  when: ansible_hostname == "{{groups['app'][0]}}" and adminlogfile is defined
  ignore_errors: true

Explanation:

path: The fully qualified location of the file we are validating.
delay: Delay in seconds before starting the validation
timeout: timeout after defined seconds.
state:  Make sure the file is available(present)
msg: A Custom message to be printed in case of failure. which is when the file is not present.

 

ansible Wait_for file to be deleted or lock file to be removed

we can use wait_for module to wait for the file deletion as well. such as waiting for the lock file to be deleted before starting the instance

- name: Making sure that the lock file is not present (or) removed
  wait_for:
    path:  "{{lockfile}}"
    delay: 10
    timeout: 30
    state: absent
    msg: "Specified LOCK FILE is still present"

 

ansible wait for seconds or sleep for seconds

wait_for module can also be used to simply make the execution of the play to sleep for certain seconds. in other words, simply pause the playbook execution.

This can be done with simply setting the delay and timeout arguments. Consider the following playbook with the task to sleep for

The Playbook Snippet

---
  - name: Sleep Playbook
    hosts: app
    gather_facts: no
    tasks:
       -  name: Sleep for 60 seconds and timeout
          tags: sleep60
          wait_for:
            delay: 60
            timeout: 0

Explanation:

delay: Delay in seconds before starting the validation (or) processing
timeout: timeout after defined seconds.

Here no validation is being performed like file presence or port status. The task is just to pause the execution for 60 seconds just like sleep statement  in any programming language

ansible Wait_for reboot ( wait_for SSH )

There are cases where we want our remote nodes to be rebooted or restarted. For example, Take the Patching as an example. As part of quarterly patching, we upgrade the installed software and packages and do various other stuff along with a final reboot to make the changes effective.

When we reboot the box. you might get your ansible play failed with the error "Shared connection closed"

But this can be avoided and you can reboot the box and wait for the server to come back up and execute the post-reboot validations or checks.

There are many methods to accomplish this

For Ansible 2.7 and more - There is a dedicated reboot module
For previous versions -  Either use ansible wait_for or ansible wait_for_connection 

Since this post is about ansible wait_for module. Let us go with the same option. Consider the following playbook I have created for linux patching. It performs yum update and reboot the box and print the uptime

The Playbook

---
  - name: Patch the server and Reboot
    hosts: app
    gather_facts: no
    tasks:
      - name: Patch the server
        become: yes
        become_user: root
        tags: Patch
        shell: "yum -y update"
        register: patchresult

      - name: Reboot the server
        tags: reboot
        become: yes
        become_user: root
        shell: "sleep 5 & reboot"
        async: 1
        poll: 0
    
      - name: Wait for the reboot and reconnect 
        wait_for:
          port: 22
          host: '{{ (ansible_ssh_host|default(ansible_host))|default(inventory_hostname) }}'
          search_regex: OpenSSH
          delay: 10
          timeout: 60
        connection: local

      - name: Check the Uptime of the servers
        shell: "uptime"
        register: Uptime

      - debug: var=Uptime

 

Explanation

In the preceding playbook, we have four tasks.

The first task is running a single command "yum -y update" over the shell module, which is responsible for updating the packages and software in the boxes.

The Second task is to reboot the server. we execute the reboot command over shell module. The task contains two important arguments which are async and poll

async:  By default, the tasks in playbook block the execution till it gets completed.  If you mention async in the task. It will be run asynchronously, in other words, it runs detached and in the background.  ansible master keeps track of this task by using the poll interval.  it accepts the time in seconds it should keep the connection open before times out
poll: Time in seconds, at what interval the ansible master should poll the Job/task to know whether it is completed.

when the poll is set to 0 seconds, Ansible will fire the task and forget it. which is used specifically in here so that despite the remote servers shutdown the playbook will still be on

The Third task is wait_for. which is our primary focus so let me explain all the arguments of this task

port:  we are waiting for the port 22 (SSH Default port) to be open
host:  we are using the ansible built-in variables here inventory_hostname or ansible_host which will represent the current host from of the host group defined in the playbook (app)
search_regex:  we are looking for a word OpenSSH once the Port is open.
delay: Delay in seconds before starting the validation
timeout: timeout the execution after defined seconds.
connection:  Execute the connection from local (master)

When the connection is set to local. The Master will try to connect to the remote boxes from the master. It is more like executing  nc or telnet command to make sure the port is open

 

ansible Wait_for the string to be available in the log file

Log files are the Swiss Army Knife of every IT analyst. We rely on the logs for various things in our day to day life. Let it be for troubleshooting or for quick validation like making sure the server is UP and RUNNING.

Let us take some real-time examples, The task snippet given below is created to validate if the Weblogic AdminServer is successfully started.

Weblogic will write clear information in the log file similar to what is given below.

<Dec 28, 2018 3:23:07,661 PM IST> <Notice> <WebLogicServer> <Saravanans-MacBook-Air.local> <AdminServer> <[STANDBY] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <d5ba0f5f-250c-4991-aa59-e6d3f3cb0ec7-0000001a> <1545990787661> <[severity-value: 32] [rid: 0] [partition-id: 0] [partition-name: DOMAIN] > <BEA-000360> <The server started in RUNNING mode.>

So here our search string is The server started in RUNNING mode

The Playbook Snippet

- name: Validating if the AdminServer state is RUNNING
  tags: validatestart
  wait_for:
    path: "{{serverlogfile}}"
    search_regex: "The server started in RUNNING mode"
    delay: 10
    timeout: 60
    msg: "Not able to find the String RUNNING in the Logfile"
  when: ansible_hostname == "{{groups['app'][0]}}" and serverlogfile is defined
  register: validatestart

Explanation

path:  Fully Qualified log file name including the path
search_regex: The Search String we are going look for in the log file, Also support regular expressions
delay:  Start the task after a defined second of initial delay
timeout: When to stop and time out the task, in seconds
msg: Custom message in case of failure

in the when conditional statement, you can also see that we have pre-validation to make sure that the serverlogfile variable is defined

this example can also be interpreted for ansible wait_for service to start. you can use ansible wait_for till the service is starting. Here we have taken weblogic application server. you can choose any other and apply the same example. Hope it helps.

 

ansible wait_for some process to finish

In Linux based Operating System, if you want to wait for the process to finish. The best approach to get that done is using the PID and the proc file.

Whenever the process is started in the Linux based os, there will be a PID assigned to it and the pid will have a reference in the /proc directory of linux. in other words, there will be a new file created in the /proc directory with the pid.

All you have to do is wait for that file to be removed. When the file is removed you can consider the process is died or finished.

let us say our process has the PID 8798 and here is the playbook snippet you could use to wait for it to get completed (or) finish.

- name: Wait until the process is finished and pid was destroyed
  wait_for:
    path: /proc/8798/status
    state: absent

 

Further References:  Ansible Wait_for module - Ansible documentation

Rate this article [ratings]

 

Thanks,
SaravAK

Follow me on Linkedin My Profile
Follow DevopsJunction onFacebook orTwitter
For more practical videos and tutorials. Subscribe to our channel

Buy Me a Coffee at ko-fi.com

Signup for Exclusive "Subscriber-only" Content

Loading