Различие в поведении, которое вы наблюдаете между with_items
и loop
, на самом деле связано с тем, как with_items
сглаживает список для вас неявно, что делает это позже, чем когда вы сглаживаете его явно в своем loop
, как рекомендовано в документации Ansible.
Итак, здесь разница просто проявляется в момент, когда список сглаживается:
Используя with_items
, список сглаживается внутри Ansible, поэтому он будет эквивалентен:
[ some_var ] | flatten(1)
When, в loop
документации Ansible, как вы это видели , вы должны сгладить список самостоятельно, но, добавив список на один уровень выше, сглаживание произойдет слишком рано и, таким образом, будет эквивалентно:
[ some_var | flatten(1) ]
Итак, если вы хотите точно и явно воспроизвести то же поведение, что и with_items
в вашем l oop, вы должны сделать это:
- 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
Это потому, что вы создаете список списка во втором примере, в то время как l oop перебирает только первый уровень списка.
Итак, ваша первая рабочая книга эквивалентна цикл по переменной, отлаженной здесь:
- 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"
}
]