ansible - 以 Ansible 任务中的每个项目为条件选择 with_items?
问题描述
我有一个需要根据集群位置选择的代理列表。例如,我的集群名称是“abc”和“def”。集群上的所有节点都以集群名称开头(例如 abc1023.net 用于 abc 等)
我想根据当前选择 pip 的代理inventory_hostname
并在参数中提供它。我尝试使用 with_items 的地图并按照以下代码在地图中“创建” 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 实际上会返回 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.将任务添加到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集群上通过以下方式测试了假案例:
- 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"
也总是返回 true(即使它应该返回 false)。我怎样才能解决这个问题?有没有更好的解决方案来实现我的用例?为了完整起见,我使用的是 ansible 2.4.1.0。
解决方案
TL;博士;
在这里,您试图评估该字符串 "item.when"
是一个布尔值,即true
,它是,因为非空字符串将导致一个true
语句。
删除条件周围的双引号when
,你应该很高兴。
你从 Ansible 得到的警告是关于when
并且只有这个语句,它总是一个原始的 Jinja2 表达式。
在 Ansible 中使用when子句很容易做到这一点,该子句包含一个没有双花括号的原始 Jinja2 表达式(请参阅group_by – 基于事实创建 Ansible 组)。
来源: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 }}"
因此,简而言之,在这里,您试图评估该字符串 "item.when"
是一个布尔值,即true
,它是,因为非空字符串将导致一个true
语句。
删除条件周围的双引号when
,你应该很高兴。
PS:尽可能不要将 JSON 语法与 YAML 混合在一起
推荐阅读
- javascript - Onclick 事件无法生成新标题
- react-native - 如何在 CustomDrawerContent 中传递导航
- r - 在 R 中的自定义函数上使用 sapply
- excel - Excel - 通过增加文本中的数字来自动生成列
- angular - 如何在 TypeScript 中过滤另一个对象数组的对象数组?
- javascript - 禁用 no-use-before-declare
- reactjs - 反应大日历行大小变化?
- c++ - 如何在 C++ 中使用 scanf 读取一行?
- python - 玩家在pygame中不动
- perl - 卷曲到 Perl HTTP 请求