MyTetra Share
Делитесь знаниями!
Как в Ansible написать фильтр, который можно использовать до старта плейбука
Время создания: 29.05.2023 09:48
Текстовые метки: ansible, кастомный, самописный, самодельный, фильтр, старт, плейбук, обработка, python, код, перед, стартом, all.yml
Раздел: Компьютер - Linux - Оркестрация - Ansible
Запись: xintrea/mytetra_syncro/master/base/1685342908wb9tuzaj9z/text.html на raw.github.com

Иногда в Ansible необходимо иметь возможность выполнить какой-либо Python-код до старта плейбука. Например, надо иметь возможность выставить значение какой-либо переменной еще на этапе обработки файла переменных /group_vars/all.yml, то есть на этапе, когда задачи в самом плейбуке еще не запустились.


Как это сделать?


Для решения подобной задачи в Ansible можно писать собственные функции фильтров, которые можно использовать при установке значений переменных в файле all.yml или в других файлах, содержащих настроечные данные. Самописный фильтр пишется на языке Python, что позволяет включить в данный код любую функциональность.


Такой фильтр можно использовать и как действительно настоящий фильтр, а кроме того и как функцию, которой передается какое-то значение, и которая на основе этого значения возвращает какой-то результат. В эту функцию может передаваться только одно значение, но если нужно передать несколько переменных, то их просто можно оформить в список прямо в Jinja-выражении.


Все вышенаписанное проще показать на примере.



Задача: в all.yml создан список списков, причем первый элемент каждого вложенного списка имеет значение True или False. Необходимо написать такой фильтр, который оставит внутри основного списка только те вложенные списки, у которых первый элемент равняется True. С помощью этого фильтра установить значение переменной, содержащей отфильтрованный список.



Решение будет следующим.


В файле all.yml прописан исходный список ( gitRepos ) и список, который должен быть получен путем обработки исходного списка ( onlyEnabledRepos ):



gitRepos:

- [ true, "doxygen_documentation.git", "master", "doxygen_doc" ]

- [ false, "idk.git", "qt5", "idk" ]

- [ true, "binke.git", "master", "binke_plugin" ]


onlyEnabledRepos: "{{ gitRepos | exclude_disabled_repos }}"


Здесь видно, что для обработки gitRepos используется фильтр exclude_disabled_repos. Как его создать? Для создания фильтра надо в директории плейбуков создать поддиректорию /filter_plugins, а в ней создать файл core.py. В нем прописывается функция, работающая как фильтр, и описывается сам фильтр:



Файл <playbooks-dir>/filter_plugins/core.py


# Функция фильтра

def exclude_disabled_repos(repolist):

return [repo for repo in repolist if repo[0] == True]



# Класс описания кастомных фильтров

class FilterModule(object):

def filters(self):

return {

'exclude_disabled_repos': exclude_disabled_repos

}



Когда используется фильтр (в выражении Jinja через символ вертикальной четры "|"), то значение, стоящее слева от вертикальной черты (фильтруемое значение) передается в функцию-фильтр в качестве первого аргумента.


А как передать в фильтр несколько аргументов? Очень просто! Второй и последующие аргументы передаются как параметры, записанные в круглых скобках после имени фильтра. Синтаксис такого использования чем-то похож на вызов функции, однако следует помнить, что первый аргумент передается в функцию из переменной, записанной слева от символа фильтра "|". Вот пример:



def our_filter(firstArg, secondArg, threeArg):

return firstArg+secondArg*threeArg



# Класс описания кастомных фильтров

class FilterModule(object):

def filters(self):

return {

'our_filter': our_filter

}



Использование фильтра следующее:



anyVar: "{{ firstVar | our_filter(secondVar, threeVar) }}"



Вот и все! В функции фильтра может быть сокрыта совершенно разная логика работы. По-сути, там размещается произвольный Python-код, который выполняется на заданных в задаче хостах (проверить это утверждение, возможно только на оркестраторе).


Так же в этом разделе:
 
MyTetra Share v.0.60
Яндекс индекс цитирования