6
---
- hosts: "{{ run_on_node|default('mysql_cluster_sql[0]')}}"
  connection: "{% if migrated is defined and migrated == 'yes' %}local{% else %}ssh{% endif %}" # This works as we are assigning non boolean value
  gather_facts: "{% if migrated is defined and migrated == 'yes' %}false{% else %}true{% endif %}" #This doesnt work well
  tasks:
    - debug: var=ansible_all_ipv4_addresses
    - debug: var=ansible_default_ipv4.address

Inventory File:

[mysql_cluster_sql]
10.200.1.191 migrated=yes

The variable has the value as true and false based on condition but even when gather_facts is false, it gathers the facts.

Zeitounator
  • 38,476
  • 7
  • 53
  • 66
Shubham Saroj
  • 290
  • 2
  • 12

2 Answers2

4

gather_facts will be evaluted before the play loop has started so ansible cannot know which group/host var it should load in this case. The problem is exactly the same for the connection attribute.

I only see one way to fulfill your requirement by gathering facts explicitly and setting the connection for each host. Ini format does not play well with this for the inventory so I transformed to yaml. I also modified your default hosts expression in playbook so that it directly get the host name from inventory. You can keep yours if it suits your needs if you wish.

Inventory:

---
all:
  children:
    mysql_cluster_sql:
      hosts:
        10.200.1.191:
          migrated: yes
      vars:
        ansible_connection: "{{ migrated | default(false) | bool | ternary('local', 'ssh') }}"

Playbook:

---
- hosts: "{{ run_on_node | default(groups['mysql_cluster_sql'][0]) }}"
  gather_facts: false

  tasks:

    - name: gather_facts if not migrated
      setup:
      when: not (migrated | default(false) | bool)

    - debug:
        var: ansible_all_ipv4_addresses

    - debug:
        var: ansible_default_ipv4.address
Zeitounator
  • 38,476
  • 7
  • 53
  • 66
  • How do i keep the inventory file in the same format because there are many more aprox 60 groups. – Shubham Saroj Jul 06 '21 at 14:46
  • Put the `ansible_connection` varialbe inside a `group_vars/mysql_cluster_sql.yml` file adjacent to your inventory. See [organizing group and host vars](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#organizing-host-and-group-variables) – Zeitounator Jul 06 '21 at 14:51
  • Is this possible to use in the playbook itself? `gather_facts: "{{ migrated | default(false) | bool | ternary('True', 'False') }}"` or is there a way to run setup module keeping the gather_facts: False before calling the roles – Shubham Saroj Jul 06 '21 at 15:04
  • Please do not multiply questions on the same subject or choose where to answer. I already replied to this in a comment in your [other question](https://stackoverflow.com/questions/68272569/how-to-run-setup-module-before-calling-ansible-roles) – Zeitounator Jul 06 '21 at 15:12
  • Thanks I got it, but as i am using rds endpoint then again I face the issue where true or false has to be assigned to a variable. I am unable to understand. Let me try out this code the way you have suggested. – Shubham Saroj Jul 06 '21 at 15:20
3

Simplify and fix the condition. Use the default value. This will cover both tests, e.g.

shell> cat pb.yml
- hosts: localhost
  gather_facts: "{{ (migrated|default('no') == 'yes')|ternary(false, true) }}"
  tasks:
    - meta: noop

will gather facts without the variable migrated defined

shell> ansible-playbook pb.yml

PLAY [localhost] ********************************************************

TASK [Gathering Facts] **************************************************
ok: [localhost]

, or when the variable is set to other value than 'yes'

shell> ansible-playbook pb.yml -e migrated=no

PLAY [localhost] ********************************************************

TASK [Gathering Facts] **************************************************
ok: [localhost]

When the variable is set to 'yes' no facts will be gathered

shell> ansible-playbook pb.yml -e migrated=yes

PLAY [localhost] ********************************************************

PLAY RECAP **************************************************************

Jinja

If you insist on Jinja the playbook below gives the same results

shell> cat pb.yml
- hosts: localhost
  gather_facts: "{% if migrated|default('no') == 'yes' %}
                 false
                 {% else %}
                 true
                 {% endif %}"
  tasks:
    - meta: noop

Boolean

You can further simplify the test by explicit conversion to Boolean, e.g.

- hosts: localhost
  gather_facts: "{{ (migrated|default('no')|bool)|ternary(false, true) }}"
  tasks:
    - meta: noop

Truthy/Falsy

Make sure you understand how Boolean conversion and testing work. See results of the tasks

    - debug:
        msg: "True"
      loop: [yes, Yes, true, True, xxx]
      when: item|bool

    - debug:
        msg: "False"
      loop: [no, No, false, False, xxx]
      when: not item|bool

    - debug:
        msg: "{{ item|bool|ternary(True, False) }}"
      loop: [yes, Yes, true, True, xxx,
             no, No, false, False, xxx]

    - debug:
        msg: "{{ item|ternary(True, False) }}"
      loop: [yes, Yes, true, True, xxx,
             no, No, false, False, xxx]

Q: "Passing the variable 'migrated' from within the inventory does not work."

A: You're right. It seems that the inventory variables are not available at the time gather_facts is running. Use setup as a workaround. For example

- hosts: localhost
  gather_facts: false
  tasks:
    - setup:
      when: (migrated|default('no')|bool)|ternary(false, true)
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63
  • This following suggestion works for me, `shell> cat pb.yml - hosts: localhost gather_facts: "{{ (migrated|default('no') == 'yes')|ternary(false, true) }}" tasks: - meta: noop` But only when i pass the variable via command line with -e option. But i am passing the variable migrated from within the inventory which is not working well. It gathers facts even when its 'yes' – Shubham Saroj Jul 07 '21 at 08:36
  • You're right. I wasn't aware of this limitation. Use setup as a workaround. I've added the details in the answer. – Vladimir Botka Jul 07 '21 at 09:19
  • I understood the logic now and everything is now working well for me. Thanks for your help. – Shubham Saroj Jul 07 '21 at 09:45