gpt4 book ai didi

ansible - 单个项目和项目列表的循环和 with_items 行为之间的区别

转载 作者:行者123 更新时间:2023-12-04 09:30:49 31 4
gpt4 key购买 nike

在这里看一个问题时,遇到了另一个问题。

让我们假设一个带有字典列表的变量,如下所示:

some_var:
- k: key1
m: value1
- k: key2
m: value2
- k: key3
m: value3

使用下面的代码遍历 some_var 会按预期给出每个项目。

- debug:
msg: "{{ item }}"
loop: "{{ some_var | flatten(1) }}"

但是,当将循环变量作为如下列表放置时,它不会遍历单个字典项,而是打印整个列表。

- debug:
msg: "{{ item }}"
loop:
- "{{ some_var | flatten(1) }}"

loop 行为与 with_items 在两种情况下都按预期工作的行为相比,这种差异的原因是什么。

最佳答案

您在 with_itemsloop 之间观察到的行为差异实际上是由于 with_items 为您扁平化列表的方式,隐含地,正如 Ansible 文档所建议的,这使得它发生的时间比您在 loop 中显式展平它的时间晚。

所以,这里的区别就在于列表被展平的那一刻:

  • 使用 with_items,列表在 Ansible 内部被展平,所以它等同于:

    [ some_var ] | flatten(1)
  • 在 Ansible 的 loop 文档中,如您所见,您必须自己展平列表,但是通过引入上一级列表,展平发生得太早了,因此,相当于:

    [ some_var | flatten(1) ]

因此,如果您希望在循环中准确、明确地重现与 with_items 相同的行为,您必须这样做:

- hosts: all
gather_facts: no

tasks:
- debug:
msg: "{{ item }}"
loop: "{{ [ some_var | flatten(1) ] | flatten(1) }}"
vars:
some_var:
- k: key1
m: value1
- k: key2
m: value2
- k: key3
m: value3

如预期的那样有效:

PLAY [all] **********************************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => (item={'k': 'key1', 'm': 'value1'}) => {
"msg": {
"k": "key1",
"m": "value1"
}
}
ok: [localhost] => (item={'k': 'key2', 'm': 'value2'}) => {
"msg": {
"k": "key2",
"m": "value2"
}
}
ok: [localhost] => (item={'k': 'key3', 'm': 'value3'}) => {
"msg": {
"k": "key3",
"m": "value3"
}
}

PLAY RECAP **********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

这是因为您在第二个示例中创建了一个列表列表,而循环仅在列表的第一级上循环。

因此,您的第一个工作剧本相当于在此处调试的变量上循环:

- hosts: all
gather_facts: no

tasks:
- debug:
msg: "{{ some_var | flatten(1) }}"
vars:
some_var:
- k: key1
m: value1
- k: key2
m: value2
- k: key3
m: value3

这给出了:

PLAY [all] **********************************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
"msg": [
{
"k": "key1",
"m": "value1"
},
{
"k": "key2",
"m": "value2"
},
{
"k": "key3",
"m": "value3"
}
]
}

PLAY RECAP **********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

不过,您的第二个示例等效于:

- hosts: all
gather_facts: no

tasks:
- debug:
msg:
- "{{ some_var | flatten(1) }}"
## Note that this above syntax is actually an equivalent to:
# msg: "{{ [ some_var | flatten(1) ] }}"
vars:
some_var:
- k: key1
m: value1
- k: key2
m: value2
- k: key3
m: value3

这给出了:

PLAY [all] **********************************************************************************************************

TASK [debug] ********************************************************************************************************
ok: [localhost] => {
"msg": [
[
{
"k": "key1",
"m": "value1"
},
{
"k": "key2",
"m": "value2"
},
{
"k": "key3",
"m": "value3"
}
]
]
}

PLAY RECAP **********************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

在第二个示例中看到您如何获得列表列表了吗?


所以,第一个例子的第一个元素是

{'k': 'key1', 'm': 'value1'}

如您所料,虽然第二个元素的第一个元素只是一个包含所有元素的列表:

[   
{
"k": "key1",
"m": "value1"
},
{
"k": "key2",
"m": "value2"
},
{
"k": "key3",
"m": "value3"
}
]

关于ansible - 单个项目和项目列表的循环和 with_items 行为之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62856503/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com