Ansible 单个项目和项目列表的循环和with_项目行为之间的差异

Ansible 单个项目和项目列表的循环和with_项目行为之间的差异,ansible,Ansible,在这里看一个问题时,遇到了另一个问题 让我们假设一个变量有一个dict列表,如下所示: 一些变量: -k:键1 m:价值1 -k:键2 m:价值2 -k:键3 m:价值3 使用下面的代码在some\u var上循环,得到预期的每个项目 -调试: msg:“{{item}}” 循环:{{some_var}展平(1)}” 但是,当将循环变量作为如下列表放置时,它不会循环遍历单个dict项,而是打印整个列表 -调试: msg:“{{item}}” 循环: -“{some_var | flatten

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

让我们假设一个变量有一个dict列表,如下所示:

一些变量:
-k:键1
m:价值1
-k:键2
m:价值2
-k:键3
m:价值3
使用下面的代码在
some\u var
上循环,得到预期的每个项目

-调试:
msg:“{{item}}”
循环:{{some_var}展平(1)}”
但是,当将循环变量作为如下列表放置时,它不会循环遍历单个dict项,而是打印整个列表

-调试:
msg:“{{item}}”
循环:
-“{some_var | flatten(1)}”

与在这两种情况下都能正常工作的
项目
相比,
循环
行为的差异是什么原因。

您观察到的
项目
循环
行为的差异实际上是由于
项目
为您平展列表的方式造成的,这使得它发生的时间比Ansible文档建议的在
循环中显式展平它的时间晚

所以,这里的区别就在于列表变平的时刻:

  • 与_items
    一起使用时,列表在内部由Ansible展平,因此它相当于:

    [some_var]|展平(1)
    
  • 在Ansible的
    循环
    文档中,正如您所看到的,您必须自己将列表展平,但通过引入一个更高级别的列表,您的展平发生得太早,因此相当于:

    [some_var|flatten(1)]
    
因此,如果您希望通过循环中的_items
准确、明确地再现与
相同的行为,则必须执行以下操作:

-主机:所有
收集事实:不
任务:
-调试:
msg:“{{item}}”
循环:{{[some_var | flatten(1)]| flatten(1)}”
变量:
一些风险:
-k:键1
m:价值1
-k:键2
m:价值2
-k:键3
m:价值3
正如预期的那样,这是可行的:

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

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

因此,您的第一个工作playbook相当于在下面调试的变量上循环:

-主机:所有
收集事实:不
任务:
-调试:
msg:{{some_var | flatten(1)}}”
变量:
一些风险:
-k:键1
m:价值1
-k:键2
m:价值2
-k:键3
m:价值3
这就产生了:

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 
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  
不过,您的第二个示例相当于:

-主机:所有
收集事实:不
任务:
-调试:
味精:
-“{some_var | flatten(1)}”
##请注意,上述语法实际上相当于:
#msg:{{[some_var | flatten(1)]}”
变量:
一些风险:
-k:键1
m:价值1
-k:键2
m:价值2
-k:键3
m:价值3
这就产生了:

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 
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”:“键1”,
“m”:“值1”
},
{
“k”:“键2”,
“m”:“价值2”
},
{
“k”:“键3”,
“m”:“价值3”
}
]

感谢@β.εηοτ.βε,+1提供详细信息。在回答这个问题时,我注意到了这部分细节。很抱歉,我遗漏了问题中与_项目相关的重要措辞,这些措辞本可以使问题更加准确。基本上,我不清楚with_项是如何工作的,但对于第二种场景,我不清楚with_项是如何工作的。也更正了问题的措辞。@Moon这是因为在
with_items
模块内部和隐式进行展平的方式,在循环中,必须显式展平。请参见编辑后答案的开头。太好了!这就解释了。