ansible - 单个项目和项目列表的循环和 with_items 行为之间的区别
问题描述
在这里看一个问题时,遇到了另一个问题。
让我们假设一个带有字典列表的变量,如下所示:
some_var:
- k: key1
m: value1
- k: key2
m: value2
- k: key3
m: value3
使用下面的代码循环some_var
会按预期给出每个项目。
- debug:
msg: "{{ item }}"
loop: "{{ some_var | flatten(1) }}"
但是,当将循环变量放置为如下列表时,它不会循环遍历单个 dict 项,而是打印整个列表。
- debug:
msg: "{{ item }}"
loop:
- "{{ some_var | flatten(1) }}"
与在两种情况下都按预期工作loop
相比,这种行为差异的原因是什么。with_items
解决方案
正如 Ansible 文档所建议的那样,您在with_items
和之间观察到的行为差异loop
实际上是由于with_items
隐含地为您展平列表的方式,这使得它比在您的 .loop
所以,这里的区别只在于列表被展平的那一刻:
使用
with_items
,列表在 Ansible 内部被展平,所以它相当于:[ some_var ] | flatten(1)
当
loop
您在 Ansible 的文档中看到它时,您必须自己展平列表,但是通过在上一级引入列表,您的展平发生得太早,因此相当于:[ 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"
}
]
推荐阅读
- typescript - Typescript 函数重载不适用于联合类型案例
- java - 在java中使用正确的数据结构返回数组中的最高元素
- android - Unity 视频播放器在 whatsapp 通知上崩溃
- ios - 当应用程序被杀死或未运行时,如何从 IOS 应用程序的推送通知中打开特定视图?
- sap - SAP Vora 1.4 工作者停止
- tensorflow - 使用较小的 CNN 在 Keras 中内存不足
- c++ - 创建新项目时“为防止加载设计器之前可能的数据丢失,必须解决以下错误”
- latex - 未编号的章节标题有一种奇怪的行为
- vhdl - VHDL如何在一句话中使用多个“and”和“or”?
- c# - Linq to sql alias fails