LeXaNZ
LeXaNZ

Reputation: 47

Ansible - How to 'wait_for' DNS to be available or How using lookup('dig') with 'until'

I made something that is working but I look for something more 'elegant' ;)

- name: Wait for DNS propagation
  ansible.builtin.shell:
    cmd: host "{{ vm_fqdn }}"
  register: dns_result
  until: dns_result.rc == 0
  retries: 30
  delay: 10

But previously I tried with a lookup and the community.general.dig

- name: Wait for DNS propagation
  ansible.builtin.set_fact:
    dns_result: "{{ lookup('community.general.dig', vm_fqdn)}}"
  until: dns_result == vm_ip
  retries: 30
  delay: 10

Unfortunately, even I added a register I couldn't get the dns_result variable updated after multiple tries. It's like the lookup happens only once on the first iteration, but is not 're-triggered' on the next try. So maybe it is the behavior of lookup or something else, but I'm curious to know.

Upvotes: 3

Views: 2597

Answers (3)

U880D
U880D

Reputation: 12063

I couldn't get the dns_result variable updated after multiple tries ... but is not 're-triggered' on the next try.

Right, that is the expected behavior for your given example.

It's like the lookup happens only once on the first iteration

But this caused by the way variables becomes registered and handled internally. For the retries loop run the variable content for until condition will stay at the initial value since it is set (registered) at "compile time" and not "re-set during run time".

The following example will show the behavior.

---
- hosts: localhost
  become: false
  gather_facts: false

  vars:

    RETRIES: [1, 2, 3]

  tasks:

  - name: Set Facts in loop
    set_fact:
      RESULT: "{{ ansible_loop.index }}"
    # Inner loop
    until: RESULT == '3'
    retries: 3
    delay: 1
    # Outer loop
    loop: "{{ RETRIES }}"
    loop_control:
      extended: true
      label: "{{ item }}"

As one can see from the result output, the retries behaves like an loop for the inner object, which is a single outer loop state here.

PLAY [localhost] *************************************
FAILED - RETRYING: Set Facts in loop (3 retries left).
FAILED - RETRYING: Set Facts in loop (2 retries left).
FAILED - RETRYING: Set Facts in loop (1 retries left).

TASK [Set Facts in loop] *****************************
failed: [localhost] (item=1) => changed=false
  ansible_facts:
    RESULT: '1'
...
  ansible_loop_var: item
  attempts: 3
  item: 1
FAILED - RETRYING: Set Facts in loop (3 retries left).
FAILED - RETRYING: Set Facts in loop (2 retries left).
FAILED - RETRYING: Set Facts in loop (1 retries left).
failed: [localhost] (item=2) => changed=false
  ansible_facts:
    RESULT: '2'
...
  ansible_loop_var: item
  attempts: 3
  item: 2
ok: [localhost] => (item=3)

To summarize, the construct set_fact - lookup('dig') - retries - until can't work unless the initial condition is already true. This is shown in the example run #3.

Documentation

  • Retrying a task until a condition is met

    When you run a task with until and register the result as a variable, the registered variable will include a key called “attempts”, which records the number of the retries for the task.

Further Q&A


Possible Solutions

You may

Upvotes: 0

Mohammed Noureldin
Mohammed Noureldin

Reputation: 16836

The cleanest and most ansible-native approach I use is:

- name: Getting ready to start
  hosts: all
  gather_facts: false
  tasks:   
    - name: Wait for DNS propagation
      delegate_to: localhost
      when: not inventory_hostname is ansible.utils.resolvable
      ansible.builtin.debug:
        msg: Waiting...
      until: inventory_hostname is ansible.utils.resolvable
      retries: 900
      delay: 10

Here is the bonus also that it will not be printing "Waiting..." for the FQDNs which are already resolvalble.

Upvotes: 1

flowerysong
flowerysong

Reputation: 2939

You're using the lookup at the wrong point. It should be directly in the until, so that it is evaluated each time.

- name: Wait for DNS propagation
  debug:
    msg: waiting
  until: lookup('community.general.dig', vm_fqdn) == vm_ip
  retries: 30
  delay: 10

Upvotes: 4

Related Questions