Пишем свои фильтры для Ansible
Ansible "из коробки" имеет множество встроенных фильтров, как реализованных в jinja2, так и собственных. Подробное описание существующих фильтров можно найти на странице документации. Однако, бывают ситуации, в которых подходящего дефолтного фильтра нет (а очень хочется). В этой короткой статье мы научимcя писать свои плагины-фильтры для ansible.
Задача...
Задача следующая: написать плагин, который будет преобразовывать переменную, представляющую собой дату и время в строковом формате в другой произвольный формат.
Например, имея на входе дату в строке вида "2017-10-14T15:39:22Z" хочу получить "14.10.2017".
... и ее решение
Подготовим следующую структуру:
- inventory
- filter_plugins
-- filters.py
- test.yml
В плейбуке test.yml опишем вызов нашего будущего фильтра:
---
- hosts: localhost
gather_facts: no
tasks:
- name: Print formatted time
debug:
msg: "{{'2017-10-14T15:39:22Z'|format_time}}"
В файле filters.py опишем сам фильтр:
#!/usr/bin/python
import time
class FilterModule(object):
def filters(self):
return {
'format_time': self.format_time
}
def format_time(self, time_string):
result = time.strftime('%d.%m.%Y', time.strptime(time_string, '%Y-%m-%dT%H:%M:%SZ'))
return result
Пробуем запустить плейбук:
$ ansible-playbook -i inventory/test test.yml
PLAY [localhost] ***************************************************************************************************
TASK [Print formatted time] ****************************************************************************************************
ok: [localhost] => {
"msg": "14.10.2017"
}
Неплохо, но мы хотим большего - задавать любой входной и выходной форматы. Немного доработаем filters.py:
#!/usr/bin/python
import time
class FilterModule(object):
def filters(self):
return {
'format_time': self.format_time
}
def format_time(self, time_string, in_format, out_format):
if time_string == '':
return ''
else:
return time.strftime(out_format, time.strptime(time_string, in_format))
Кроме входных параметров я добавил обработку пустого входного time_string, чтобы не возникало ошибки, если фильтр применен к не заданной переменной.
И плейбук:
---
- hosts: localhost
gather_facts: no
tasks:
- name: Print formatted time
debug:
msg: "{{'2017-10-14T15:39:22Z'|format_time('%Y-%m-%dT%H:%M:%SZ','%d.%m.%Y')}}"
Проверяем...работает!
Подход в целом хорош, но наш фильтр в директори filter_plugins не будет работать в других плейбуках (находящихся в других директориях), если такая необходимость возникнет.
Чтобы решить эту проблему, можно добавить в ansible.cfg путь к filters.py в значение переменной filter_plugins.