首页 > 解决方案 > 以 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'> 

尝试了其他解决方案

  1. 在任务中添加了变量
- 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.*')
  1. 测试假案例
    我在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。

标签: ansibleyamlansible-2.x

解决方案


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 混合在一起


推荐阅读