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