Регистрация переменных из словаря и их последующая итерация в Ansible

Автор: Admin | 06.09.2022

Ansible_logo

Регистрация переменных из словаря при помощи 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 }}"

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *