在 Ansible 中使用 if 条件将 True 或 False 分配给 gather_facts 不起作用

using if condition to assign True or False to gather_facts in Ansible doesnt work

---
- 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

库存文件:

[mysql_cluster_sql]
10.200.1.191 migrated=yes

变量根据条件具有真值和假值,但即使 gather_facts 为假,它也会收集事实。

gather_facts 将在播放循环开始之前进行评估,因此 ansible 无法知道在这种情况下应该加载哪个 group/host 变量。 connection 属性的问题完全相同。

我只看到一种方法可以满足您的要求,即明确收集事实并为每个主机设置连接。 Ini 格式不能很好地用于库存,所以我转换为 yaml。我还修改了剧本中的默认 hosts 表达式,以便它直接从清单中获取主机名。如果需要,您可以保留自己的。

库存:

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

剧本:

---
- 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

简化并修复条件。使用默认值。这将涵盖这两个测试,例如

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

将在未定义变量 migrated 的情况下收集事实

shell> ansible-playbook pb.yml

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

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

,或者当变量设置为 'yes'

以外的其他值时
shell> ansible-playbook pb.yml -e migrated=no

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

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

当变量设置为 'yes' 时,将不会收集任何事实

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

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

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

金贾

如果你坚持Jinja下面的剧本给出相同的结果

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

布尔值

您可以通过显式转换为 Boolean 来进一步简化测试,例如

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

Truthy/Falsy

确保您了解布尔转换和测试的工作原理。查看任务结果

    - 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]

问:"从清单中传递变量 'migrated' 不起作用。"

答:你说得对。似乎 gather_facts 是 运行 时库存变量不可用。使用 setup 作为解决方法。例如

- hosts: localhost
  gather_facts: false
  tasks:
    - setup:
      when: (migrated|default('no')|bool)|ternary(false, true)