Определение
В Ansible lookup плагины — это специфичные для Ansible расширения шаблонизатора Jinja2, которые используются для получения какой-либо информации на узле, который является контроллером (обычно это ваш ПК) Примеры lookup плагинов:
community.hashi_vault.vault_kv2_get
— для получения значения ключа из Hashicorp Vaultansible.builtin.file
— для чтения файлаansible.builtin.env
— значение переменной окружения
Вот полный список lookup плагинов из ansible-galaxy
использование
delegate_to
не позволит выполнить lookup плагин на управляемом узле, его можно выполнить только на узле-контроллере
Приведу наипростейший пример, выведем содержимое переменной окружения $HOME
на моем компьютере:
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Display $HOME
ansible.builtin.debug:
msg: "{{ lookup('env', 'HOME') }}"
Результат:
TASK [Display $HOME]
ok: [localhost] =>
msg: /home/alexander
Интерполяция
Однако логика работы lookup
отличается от привычной логики работы модулей, потому что их определение происходит в момент интерполяции:
---
- hosts: localhost
become: false
gather_facts: false
vars:
current_time: "{{ lookup('pipe','date +%H:%M:%S') }}"
tasks:
- name: Display time 1/2
ansible.builtin.debug:
msg: Current time {{ current_time }}
- name: Pause for 3 seconds
ansible.builtin.pause:
seconds: 3
- name: Display time 2/2
ansible.builtin.debug:
msg: Current time is {{ current_time }}
В примере выше может показаться, что обе таски выведут один и тот же результат, но как и я сказал — результат работы будет получен в момент интерполяции:
TASK [Display current time 1/2]
ok: [localhost] =>
msg: Current time 21:21:44
TASK [Pause for 3 seconds]
Pausing for 3 seconds
(ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort)
ok: [localhost]
TASK [Display current time 2/2]
ok: [localhost] =>
msg: Current time is 21:21:47
until:
Еще один интересный пример работы вместе с директивой until:
(напомню, что until:
позволяет перезапускать модуль до получения нужного результата)
Предположим, что нам нужно сгенерировать UUID, который начинается с нуля и мы написали вот такой простой плей:
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Generate random UUID
ansible.builtin.set_fact:
random_uuid: "{{ lookup('pipe', 'uuidgen') }}"
until: random_uuid.startswith('0')
delay: 1
retries: 20
С первого взгляда все выглядит правильно: мы получаем значение random_uuid
из lookup
плагина и далее проверяем не начинается ли он с нуля, но на самом деле значение random_uuid
будет получено один раз при первой интерполяции плагина и дальше until:
будет проверять одно и то же значение
Как обойти такое ограничение? Никак, совместить until:
+lookup
и “поймать” получившееся значение не получится, значение lookup
генерируется один раз до выполнения самого модуля, правильнее всего в таком случае подобрать нужный плагин (или написать самому)
Можно добиться правильной работы условия until:
+lookup
подставив lookup
плагин прямо в условие, но получить нужное значение все равно не получится, поскольку в модуле set_fact
будет сохранено значение, которое он получил еще в момент вызова (см. пикрил)
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Generate random UUID
vars:
_random_uuid: "{{ lookup('pipe', 'uuidgen') }}"
ansible.builtin.set_fact:
random_uuid: "{{ _random_uuid }}"
until: _random_uuid.startswith('0')
delay: 1
retries: 20