Pull to refresh

Comments 7

У меня вопрос (я не уверен, что его надо адресовать Redhat Russia, правда) — почему ansible не даёт возможности пост-обработки register?


У нас есть два метода выставить переменную (три, если считать include_vars): set_fact, register. При этом set_fact очень суровый (приоритетный) — он перезаписывает к чертям почти всё, и это не всегда желаемо, а ещё он загаживает лог выполнения, т.к. set_fact — отдельная таска.


У нас есть register, но мы не можем повлиять на структуру того, что register. Там обязательно будет простыня всего output, rc, и stderr и т.д.


А вот что бы хотелось — это возможность сделать register для переменной с результатом вычисления относительно результата.


Я сейчас буду изобретать:


- command: foobar
  register:
    input_name: in_foo
    name: result_foo
    expression: '{{ in_foo.stdout[3]|int }}'
- debug: var=result_foo

Я бы сказал, что это мелочь, но я напоминаю, что в ansible невозможно сделать так:


var:
   foo : ''{{foo.bar}}"

потому что это рекурсия в jinja2, и это сильно осложняет адекватное использование чужого register...

Да, я тоже иногда жалел, что нет поддержки такого функционала. Можно сделать Pull-Request :)


Я иногда пользуюсь переменными, как макросами. Т.к. Ansible запускает шаблонизацию переменных в момент использования, то можно делать так:


- hosts: dest
  vars:
    my_macro: "{{ result_foo.stdout[3] | int }}"
  tasks:
    - command: foobar
      register: result_foo
    - debug:
        msg: "{{ my_macro }}"
Да, так можно, но это leaky abstraction. Например, если мы сделаем delegate для роли, у которой такое написано, то можем получить, что result_foo не определён, потому что хост поменялся (хотя мы передали my_macro) как переменную в роль.

Вторая leaky abstraction — это использование variable_end_string/variable_start_string у `template`. Некоторые особо го-шные приложения (вроде капаситора) используют {{}} в своих шаблонах, так что приходится переключаться. В этой ситуации, любая переменная, ссылающаяся на другую переменную, превращается в plain-text `{{ result_foo }}` прямо в получившемся файле.
Register выдает варьирующийся в зависимости от модуля объем данных, который доступен для дальнейшей работы (https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#register-variables).
Сохранение в переменную выполняет именно set fact модуль — поэтому свое место в логе.
Можно эффективно обойтись уже имеющимися средствами, в том числе не всем известным новым циклам (https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html#) и «magic variables» (https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#accessing-information-about-other-hosts-with-magic-variables), и всегда можно обратиться в сообщество Ansible.

Первый вариант — то, что сейчас, и с чем приходится жить.
Второй вариант — set_fact очень verbose, если у меня тривиальная обработка register, то либо она где-то под капотом, (через предопределённые переменные), либо множество set_fact. Главная печаль состоит в том, что если у меня что-то пришло через register, оно отличается от ситуации, что я его сделал через -e в командной строке.

а еще, можно писать кастомные фильтры, под каждый чих)

Sign up to leave a comment.