Select with_items 以 Ansible 任务中的每个项目为条件?
Select with_items with conditional on each item in Ansible task?
我有一个需要根据群集位置 selected 的代理列表。例如,我的集群名称是 'abc' 和 'def'。集群上的所有节点都以集群名称开头(例如 abc1023.net 表示 abc 等)
我想 select 基于当前 inventory_hostname
的 pip 代理,并在参数中提供它。我尝试按照以下代码在地图中使用 with_items 和 'creating' 的 when 条件:
- name: run pip on proxy
pip:
name: <package_name>
extra_args: "--proxy item.proxy"
when: "item.when"
with_items:
- {proxy: 'http:abc_proxy:port', when: "'abc' in {{inventory_hostname|lower}}"}
- {proxy: 'http:def_proxy:port', when: "'def' in {{inventory_hostname|lower}}"}
我面临的问题是这种情况总是被认为是正确的。我尝试将 when: "'abc' in {{inventory_hostname|lower}}"
替换为 when: false
,这确实有效。也就是说,使它成为一个明确的 false 实际上 returns false 但当我检查字符串引号中的条件时却不是。我认为如果它包含任何值,则在地图内时被认为是真实的。
如何在 when 映射中明确检查此条件?删除引号无济于事,因为它会引发语法错误:
We could be wrong, but this one looks like it might be an issue
with missing quotes. Always quote template expression brackets when
they start a value. For instance:
with_items:
- {{ foo }}
Should be written as:
with_items:
- "{{ foo }}"
exception type: <class 'yaml.parser.ParserError'>
尝试了其他解决方案
- 在任务中添加了变量
- name: run pip on proxy
vars:
abc_status: "{{ true if 'abc' in {{inventory_hostname|lower}} else false }}"
def_status: "{{ true if 'def' in {{inventory_hostname|lower}} else false }}"
pip:
name: <package_name>
extra_args: "--proxy item.proxy"
when: "item.when"
with_items:
- {proxy: 'http:abc_proxy:port', when: abc_status}
- {proxy: 'http:def_proxy:port', when: def_status}
2.Added任务set_fact
- set_fact:
abc_status: true
when: inventory_hostname|lower is match('abc.*')
- set_fact:
def_status: true
when: inventory_hostname|lower is match('def.*')
- 测试了错误案例
我在abc集群上通过以下方式测试了false case:
- name: run pip on proxy
vars:
abc_status: "{{ true if 'abc' in {{inventory_hostname|lower}} else false }}"
def_status: "{{ true if 'def' in {{inventory_hostname|lower}} else false }}"
pip:
name: <package_name>
extra_args: "--proxy item.proxy"
when: "item.when"
with_items:
- {proxy: 'http:def_proxy:port', when: def_status}
这应该总是失败,因为代理以及 when 条件正在检查 def 集群,而它是 运行 在 abc 集群上。但我得到以下 Ansible 输出:
TASK [<project> : run pip on proxy] ************************************************
changed: [abc1023.net] => (item={u'when': u'def_status', u'proxy': u'http:def_proxy:port'})
这也是我使用其他尝试过的解决方案时总是得到的结果。
问题
即使尝试了上述不同的解决方案,when: "item.when"
始终 return 正确(即使它应该 return 错误)。我怎样才能解决这个问题?有没有更好的解决方案来实现我的用例?
为了完整起见,我使用的是 ansible 2.4.1.0.
TL;DR;
在这里,您试图评估 string "item.when"
是一个布尔值 true
,因为它是一个非空的字符串将导致 true
语句。
删除 when
条件周围的双引号,您应该可以开始了。
你从 Ansible 得到的警告是关于 when
并且只有这个语句,它总是一个原始的 Jinja2 表达式。
This is easy to do in Ansible with the when clause, which contains a raw Jinja2 expression without double curly braces (see group_by – Create Ansible groups based on facts).
来源:https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#the-when-statement,强调,我的。
根据您的实际操作手册,可能的解决方案可能是:
- name: run pip on proxy
pip:
name: <package_name>
extra_args: "--proxy {{ item.proxy }}"
when: item.proxy_ref in inventory_hostname|lower
with_items:
- proxy: 'http:abc_proxy:port'
proxy_ref: 'abc'
- proxy: 'http:def_proxy:port'
proxy_ref: 'def'
另一个可能是:
- name: run pip on proxy
pip:
name: <package_name>
extra_args: "--proxy {{ item.proxy }}"
when: item.when
with_items:
- proxy: 'http:abc_proxy:port'
when: "{{ 'abc' in inventory_hostname|lower }}"
- proxy: 'http:def_proxy:port'
when: "{{ 'def' in inventory_hostname|lower }}"
所以,简而言之,在这里,你试图评估 string "item.when"
是一个布尔值,即 true
,它是,因为,非空字符串将导致 true
语句。
删除 when
条件周围的双引号,您应该可以开始了。
PS:尽可能不要将 JSON 语法与 YAML 语法混合使用
Q: "Is there any better solution to implement my use case?"
A: 连接代理可能会更好。例如
- name: run pip on proxy
pip:
name: "{{ package_name }}"
extra_args: "--proxy {{ my_proxy }}"
vars:
my_prefix: "{{ inventory_hostname[0:3] }}"
my_proxy: "{{ 'http:' ~ my_prefix ~ '_proxy:port' }}"
我有一个需要根据群集位置 selected 的代理列表。例如,我的集群名称是 'abc' 和 'def'。集群上的所有节点都以集群名称开头(例如 abc1023.net 表示 abc 等)
我想 select 基于当前 inventory_hostname
的 pip 代理,并在参数中提供它。我尝试按照以下代码在地图中使用 with_items 和 'creating' 的 when 条件:
- name: run pip on proxy
pip:
name: <package_name>
extra_args: "--proxy item.proxy"
when: "item.when"
with_items:
- {proxy: 'http:abc_proxy:port', when: "'abc' in {{inventory_hostname|lower}}"}
- {proxy: 'http:def_proxy:port', when: "'def' in {{inventory_hostname|lower}}"}
我面临的问题是这种情况总是被认为是正确的。我尝试将 when: "'abc' in {{inventory_hostname|lower}}"
替换为 when: false
,这确实有效。也就是说,使它成为一个明确的 false 实际上 returns false 但当我检查字符串引号中的条件时却不是。我认为如果它包含任何值,则在地图内时被认为是真实的。
如何在 when 映射中明确检查此条件?删除引号无济于事,因为它会引发语法错误:
We could be wrong, but this one looks like it might be an issue with missing quotes. Always quote template expression brackets when they start a value. For instance: with_items: - {{ foo }} Should be written as: with_items: - "{{ foo }}" exception type: <class 'yaml.parser.ParserError'>
尝试了其他解决方案
- 在任务中添加了变量
- name: run pip on proxy
vars:
abc_status: "{{ true if 'abc' in {{inventory_hostname|lower}} else false }}"
def_status: "{{ true if 'def' in {{inventory_hostname|lower}} else false }}"
pip:
name: <package_name>
extra_args: "--proxy item.proxy"
when: "item.when"
with_items:
- {proxy: 'http:abc_proxy:port', when: abc_status}
- {proxy: 'http:def_proxy:port', when: def_status}
2.Added任务set_fact
- set_fact:
abc_status: true
when: inventory_hostname|lower is match('abc.*')
- set_fact:
def_status: true
when: inventory_hostname|lower is match('def.*')
- 测试了错误案例
我在abc集群上通过以下方式测试了false case:
- name: run pip on proxy
vars:
abc_status: "{{ true if 'abc' in {{inventory_hostname|lower}} else false }}"
def_status: "{{ true if 'def' in {{inventory_hostname|lower}} else false }}"
pip:
name: <package_name>
extra_args: "--proxy item.proxy"
when: "item.when"
with_items:
- {proxy: 'http:def_proxy:port', when: def_status}
这应该总是失败,因为代理以及 when 条件正在检查 def 集群,而它是 运行 在 abc 集群上。但我得到以下 Ansible 输出:
TASK [<project> : run pip on proxy] ************************************************
changed: [abc1023.net] => (item={u'when': u'def_status', u'proxy': u'http:def_proxy:port'})
这也是我使用其他尝试过的解决方案时总是得到的结果。
问题
即使尝试了上述不同的解决方案,when: "item.when"
始终 return 正确(即使它应该 return 错误)。我怎样才能解决这个问题?有没有更好的解决方案来实现我的用例?
为了完整起见,我使用的是 ansible 2.4.1.0.
TL;DR;
在这里,您试图评估 string "item.when"
是一个布尔值 true
,因为它是一个非空的字符串将导致 true
语句。
删除 when
条件周围的双引号,您应该可以开始了。
你从 Ansible 得到的警告是关于 when
并且只有这个语句,它总是一个原始的 Jinja2 表达式。
This is easy to do in Ansible with the when clause, which contains a raw Jinja2 expression without double curly braces (see group_by – Create Ansible groups based on facts).
来源:https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#the-when-statement,强调,我的。
根据您的实际操作手册,可能的解决方案可能是:
- name: run pip on proxy
pip:
name: <package_name>
extra_args: "--proxy {{ item.proxy }}"
when: item.proxy_ref in inventory_hostname|lower
with_items:
- proxy: 'http:abc_proxy:port'
proxy_ref: 'abc'
- proxy: 'http:def_proxy:port'
proxy_ref: 'def'
另一个可能是:
- name: run pip on proxy
pip:
name: <package_name>
extra_args: "--proxy {{ item.proxy }}"
when: item.when
with_items:
- proxy: 'http:abc_proxy:port'
when: "{{ 'abc' in inventory_hostname|lower }}"
- proxy: 'http:def_proxy:port'
when: "{{ 'def' in inventory_hostname|lower }}"
所以,简而言之,在这里,你试图评估 string "item.when"
是一个布尔值,即 true
,它是,因为,非空字符串将导致 true
语句。
删除 when
条件周围的双引号,您应该可以开始了。
PS:尽可能不要将 JSON 语法与 YAML 语法混合使用
Q: "Is there any better solution to implement my use case?"
A: 连接代理可能会更好。例如
- name: run pip on proxy
pip:
name: "{{ package_name }}"
extra_args: "--proxy {{ my_proxy }}"
vars:
my_prefix: "{{ inventory_hostname[0:3] }}"
my_proxy: "{{ 'http:' ~ my_prefix ~ '_proxy:port' }}"