Ansible::when:: 如何在 jinja 结果和注册变量状态之间应用"and"



当主机IP位于给定网络时,我正在尝试运行任务如果任务还没有配置,那么,我尝试这样做:

when: "{{ ansible_facts['ansible_all_ipv4_addresses'] | ansible.utils.reduce_on_network( '172.20.0.0/24' ) }}" and chrony_is_configured is skipped

问题是我得到了一个指向and的错误:

The offending line appears to be:
force: true
when: "{{ lenght( ansible_facts['ansible_all_ipv4_addresses'] | ansible.utils.reduce_on_network( '172.20.0.0/24' ) ) > 0 }}" and ( chrony_is_configured is skipped )
                                                             ^ here

这个包含and的Jinja表达式有什么问题?
更一般地说,我如何将逻辑操作数、Jinja表达式的输出和注册变量的状态结合起来?

Q:"在某个条件下,如何将'and'应用于Jinja表达式的输出和注册变量的状态?">

A:要么创建一个项目列表,要么显式地使用操作符'and'。在条件中,列表中的项创建逻辑连接('and')。例如,声明变量

_network: 172.17.0.0/24
_network_reduced: "{{ ansible_all_ipv4_addresses|
ansible.utils.reduce_on_network(_network) }}"

和注册chrony_is_configured

- command: echo "chrony is configured"
register: chrony_is_configured
when: false

看看你得到了什么

- debug:
msg: |
ansible_all_ipv4_addresses: {{ ansible_all_ipv4_addresses }}
_network_reduced: {{ _network_reduced }}
chrony_is_configured:
{{ chrony_is_configured|to_nice_yaml|indent(2) }}

。例如,

msg: |-
ansible_all_ipv4_addresses: ['172.17.0.1', '10.1.0.184']
_network_reduced: ['172.17.0.1']
chrony_is_configured:
changed: false
skip_reason: Conditional result was False
skipped: true

测试变量

- debug:
msg: |
network not empty: {{ _network_reduced|length > 0 }}
crony is skipped: {{ chrony_is_configured is skipped }}

msg: |-
network not empty: True
crony is skipped: True

并创建条件,或者作为项列表

- assert:
that:
- _network_reduced|length > 0
- chrony_is_configured is skipped

或显式地使用and操作符

- assert:
that: _network_reduced|length > 0 and
chrony_is_configured is skipped

两个选项给出相同的结果。


用于测试的完整剧本示例

shell> cat pb.yml
- hosts: localhost
vars:
_network: 172.17.0.0/24
_network_reduced: "{{ ansible_all_ipv4_addresses|
ansible.utils.reduce_on_network(_network) }}"
tasks:
- command: echo "chrony is configured"
register: chrony_is_configured
when: false
- debug:
msg: |
ansible_all_ipv4_addresses: {{ ansible_all_ipv4_addresses }}
_network_reduced: {{ _network_reduced }}
chrony_is_configured:
{{ chrony_is_configured|to_nice_yaml|indent(2) }}
- debug:
msg: |
network not empty: {{ _network_reduced|length > 0 }}
crony is skipped: {{ chrony_is_configured is skipped }}
- assert:
that:
- _network_reduced|length > 0
- chrony_is_configured is skipped
- assert:
that: _network_reduced|length > 0 and
chrony_is_configured is skipped

shell> ansible-playbook pb.yml 
PLAY [localhost] *****************************************************************************
TASK [Gathering Facts] ***********************************************************************
ok: [localhost]
TASK [command] *******************************************************************************
skipping: [localhost]
TASK [debug] *********************************************************************************
ok: [localhost] => 
msg: |-
ansible_all_ipv4_addresses: ['172.17.0.1', '10.1.0.184']
_network_reduced: ['172.17.0.1']
chrony_is_configured:
changed: false
skip_reason: Conditional result was False
skipped: true
TASK [debug] *********************************************************************************
ok: [localhost] => 
msg: |-
network not empty: True
crony is skipped: True
TASK [assert] ********************************************************************************
ok: [localhost] => changed=false 
msg: All assertions passed
TASK [assert] ********************************************************************************
ok: [localhost] => changed=false 
msg: All assertions passed
PLAY RECAP ***********************************************************************************
localhost: ok=5    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0

你可以在Ansible文档中读到:

when子句是一个没有双花括号的原始Jinja2表达式(参见group_by_module)。当您运行任务或剧本时,Ansible为所有主机评估测试。

因此,作为Jinja2表达式,两个双引号或单引号之间的所有内容都是字符串。所以,你的when语句看起来像:'a string'后面跟着and关键字,然后是另一个要求值的条件。

但是when语句在and关键字语句之前和另一个条件之后等待第一个条件求值。这就是它失败的原因。尽量不要在when语句中使用双引号或将所有语句包装在其中。

试试这段代码:

- name: debug
debug:
msg: "{{ ansible_facts['ansible_all_ipv4_addresses'] }}"
when:
- ansible_facts['ansible_all_ipv4_addresses'] | default([]) | ansible.utils.reduce_on_network( '172.20.0.0/24' ) | length > 0
- chrony_is_configured.skipped

最新更新