Регистрация переменных из словаря при помощи register и их последующая итерация в Ansible.
Registering variables from a dictionary and then iterating them in Ansible.
По-русски звучит не сильно понятно, проще показать в коде.
Описание
Есть простой словарь с переменными:
dictionary:
key_1:
name: key_1
some_var: some_value_1
key_2:
name: key_2
some_var: some_value_2
По нему надо прогнать несколько тасок в loop'е. Проверить, существует ли файл:
- name: "Check if {{ item.value.name }} file exists"
stat:
path: "/path_to/{{ item.value.name }}.dat"
register: register_file_exist
loop: "{{ variables_name | dict2items }}"
loop_control:
label: "{{ item.key }}"
И если нет, создать его:
- name: "Create {{ item.item.key }} file if not exists"
shell: "touch /path_to/{{ item.item.key }}.dat"
when: register_file_exist.stat.exists == false
loop: "{{ variables_name | dict2items }}"
loop_control:
label: "{{ item.key }}"
Но в таком виде итерация не работает и падает с ошибкой:
The conditional check 'register_file_exist.stat.exists == false' failed.
The error was: error while evaluating conditional (register_file_exist.stat.exists == false): 'dict object' has no attribute 'stat'
Дебаг
Такое происходит, поскольку внутри действительно нет атрибута stat. Это можно увидеть, если включить дебаг и вывести значение register:
- debug:
msg: "{{ register_file_exist }}"
Вывод:
TASK [loop : debug] **********************************************
ok: [test_server] => {
"msg": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": false,
"get_mime": true,
"path": "/path_to/key_1.dat"
}
},
"item": {
"key": "key_1",
"value": {
"name": "key_1",
"some_var": "some_value_1"
}
},
"stat": {
"exists": false
}
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": false,
"get_mime": true,
"path": "/path_to/key_2.dat"
}
},
"item": {
"key": "key_2",
"value": {
"name": "key_2",
"some_var": "some_value_2"
}
},
"stat": {
"exists": false
}
}
],
"skipped": false
}
}
Видно, что stat
все же есть, но уже внутри этого нового словаря. Поэтому далее итерировать надо по нему.
Решение
Замена итерируемого словаря на новый
- name: "Create {{ item.item.key }} file if not exists"
shell: "touch /path_to/{{ item.item.key }}.dat"
when: item.stat.exists == false
loop: "{{ register_file_exist.results }}"
К тому же, другие переменные тоже существуют в новом словаре и к ним можно обратиться как item.item.value.some_var
Итог
В конечном итоге должно выглядеть так:
- name: "Check if {{ item.value.name }} file exists"
stat:
path: "/path_to/{{ item.value.name }}.dat"
register: register_file_exist
loop:
"{{ variables_name | dict2items }}"
loop_control:
label: "{{ item.key }}"
- name: "Create {{ item.item.key }} file if not exists"
shell: "touch /path_to/{{ item.item.key }}.dat"
when: item.stat.exists == false
loop: "{{ register_file_exist.results }}"