在Ansible中一起使用set_facts和with_items

Bru*_*e P 52 ansible

我目前正在使用Ansible 1.7.2.我有以下测试剧本:

---
- hosts: localhost
  tasks:
  - name: set fact 1
    set_fact: foo="[ 'zero' ]"

  - name: set fact 2
    set_fact: foo="{{ foo }} + [ 'one' ]"

  - name: set fact 3
    set_fact: foo="{{ foo }} + [ 'two', 'three' ]"

  - name: set fact 4
    set_fact: foo="{{ foo }} + [ '{{ item }}' ]"
    with_items:
      - four
      - five
      - six

  - debug: var=foo
Run Code Online (Sandbox Code Playgroud)

第一个任务设置一个事实,即列表中包含一个项目.后续任务将附加更多值附加到该列表.前三个任务按预期工作,但最后一个没有.这是我运行时的输出:

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [set fact 1] ************************************************************
ok: [localhost]

TASK: [set fact 2] ************************************************************
ok: [localhost]

TASK: [set fact 3] ************************************************************
ok: [localhost]

TASK: [set fact 4] ************************************************************
ok: [localhost] => (item=four)
ok: [localhost] => (item=five)
ok: [localhost] => (item=six)

TASK: [debug var=foo] *********************************************************
ok: [localhost] => {
    "foo": [
        "zero",
        "one",
        "two",
        "three",
        "six"
    ]
}

PLAY RECAP ********************************************************************
localhost                  : ok=6    changed=0    unreachable=0    failed=0
Run Code Online (Sandbox Code Playgroud)

鉴于任务4中的with_items以及输出显示任务在该列表中的项目上正确迭代的事实,我希望结果包含从0到6的所有数字.但是最后一个任务似乎只是用列表中的最后一项来评估set_fact.这可能是Ansible的一个错误吗?

编辑:我也刚刚在ansible 1.8上测试过,输出结果相同.

小智 79

有一种解决方法可能有所帮助.您可以为每个set_fact迭代"注册"结果,然后将结果映射到列表:

---
- hosts: localhost
  tasks:
  - name: set fact
    set_fact: foo_item="{{ item }}"
    with_items:
      - four
      - five
      - six
    register: foo_result

  - name: make a list
    set_fact: foo="{{ foo_result.results | map(attribute='ansible_facts.foo_item') | list }}"

  - debug: var=foo
Run Code Online (Sandbox Code Playgroud)

输出:

< TASK: debug var=foo >
 ---------------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||


ok: [localhost] => {
    "var": {
        "foo": [
            "four", 
            "five", 
            "six"
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个将在ansible v2上失败.任何想法如何使其在V2上运行? (2认同)
  • 就我而言,我必须测试以查看该属性是否也存在。这可以通过`foo_result.results | 来实现。selectattr('ansible_facts', 'defined') | 地图(属性='ansible_facts.foo_item')| 列表` (2认同)

小智 12

正如其他人的评论中所提到的,这里给出的最佳解决方案在Ansible 2.2中并不适用于我,特别是在使用时with_items.

似乎OP的预期方法现在可以正常工作,引用略有变化item.

- set_fact: something="{{ something + [ item ] }}"
  with_items:
    - one
    - two
    - three
Run Code Online (Sandbox Code Playgroud)

还有一个较长的例子,我处理了列表的初始情况未定义并添加了一个可选项,when因为这也让我感到悲伤:

- set_fact: something="{{ something|default([]) + [ item ] }}"
  with_items:
    - one
    - two
    - three
  when: item.name in allowed_things.item_list
Run Code Online (Sandbox Code Playgroud)


Gra*_*han 10

我正在四处寻找这个问题的答案。我发现这很有帮助。该模式在 with_items 的文档中并不明显。

https://github.com/ansible/ansible/issues/39389

- hosts: localhost
  connection: local
  gather_facts: no

  tasks:
    - name: set_fact
      set_fact:
        foo: "{{ foo }} + [ '{{ item }}' ]"
      with_items:
        - "one"
        - "two"
        - "three"
      vars:
        foo: []

    - name: Print the var
      debug:
        var: foo
Run Code Online (Sandbox Code Playgroud)


Rus*_*ley 7

Jinja 2.6没有map功能.所以另一种方法是:

set_fact: foo="{% for i in bar_result.results %}{{ i.ansible_facts.foo_item }}{%endfor%}"
Run Code Online (Sandbox Code Playgroud)


小智 6

以下对我有用:

- name: set fact
  set_fact: 
    foo_item: "{{foo_item | default([]) + [item]}}" 
  loop: 
    - four
    - five
    - six
Run Code Online (Sandbox Code Playgroud)


Bru*_*e P 0

看起来这种行为就是 Ansible 目前的工作方式,尽管人们对修复它以使其按预期工作很感兴趣。目前有一个具有所需功能的拉取请求,因此希望最终能够将其合并到 Ansible 中。