Фильтры
- Фильтры для форматирования данных
- Принудительное определение переменных
- Установка значения по умолчанию для неопределенных переменных
- Исключение параметров
- Фильтры для списков
- Фильтры теории множеств
- Фильтр для словарей
- Фильтр items2dict
- Фильтры zip и zip_longest
- Фильтр subelements
- Фильтр случайного MAC-адреса
- Фильтр случайного числа
- Фильтр перемешивания
- Математические
- Фильтр JSON-запроса
- Фильтр IP-адреса
- Фильтры командной строки сети
- Фильтры XML сети
- Фильтры хеширования
- Объединение хешей/словарей
- Извлечение значений из контейнеров
- Фильтр комментариев
- Фильтр разделения URL
- Фильтры регулярных выражений
- Другие полезные фильтры
- Фильтры комбинаций
- Фильтры отладки
Фильтры в Ansible взяты из Jinja2 и используются для преобразования данных внутри выражения шаблона. Jinja2 поставляется со многими фильтрами. См. встроенные фильтры в официальной документации по шаблонам Jinja2.
Учитывайте, что шаблонизация происходит на контроллере Ansible, а не на целевом узле задачи, поэтому фильтры также выполняются на контроллере, так как они обрабатывают локальные данные.
В дополнение к тем, которые предоставляет Jinja2, Ansible поставляется со своими собственными и позволяет пользователям добавлять свои собственные пользовательские фильтры.
Фильтры для форматирования данных
Следующие фильтры возьмут структуру данных в шаблоне и отобразят её в немного другом формате. Иногда это полезно для отладки:
{{ some_variable | to_json }}
{{ some_variable | to_yaml }}
Для удобочитаемого вывода вы можете использовать:
{{ some_variable | to_nice_json }}
{{ some_variable | to_nice_yaml }}
Также возможно изменить отступы обоих (новая функция в версии 2.2):
{{ some_variable | to_nice_json(indent=2) }}
{{ some_variable | to_nice_yaml(indent=8) }}
В качестве альтернативы, вы можете читать некоторые уже отформатированные данные:
{{ some_variable | from_json }}
{{ some_variable | from_yaml }}
например:
tasks:
- shell: cat /some/path/to/file.json
register: result
- set_fact:
myvar: "{{ result.stdout | from_json }}"
Новая функция в версии 2.7.
Для парсинга многодокументных yaml-строк предоставляется фильтр from_yaml_all. Фильтр from_yaml_all вернёт генератор распарсенных yaml-документов.
например:
tasks:
- shell: cat /some/path/to/multidoc-file.yaml
register: result
- debug:
msg: '{{ item }}'
loop: '{{ result.stdout | from_yaml_all | list }}'
Принудительное определение переменных
По умолчанию в ansible и ansible.cfg происходит ошибка, если переменные не определены, но вы можете это отключить.
Это позволяет явно проверить с выключенной функцией:
{{ variable | mandatory }}
Значение переменной будет использоваться как есть, но оценка шаблона вызовет ошибку, если она не определена.
Установка значения по умолчанию для неопределенных переменных
Jinja2 предоставляет полезный фильтр «default», который часто является лучшим подходом к ошибке, если переменная не определена:
{{ some_variable | default(5) }}
В приведенном выше примере, если переменная «some_variable» не определена, используемое значение будет 5, а не ошибка.
Если вы хотите использовать значение по умолчанию, когда переменные имеют значение false или пустую строку, вы должны установить второй параметр в true:
{{ lookup('env', 'MY_USER') | default('admin', true) }}
Исключение параметров
Начиная с Ansible 1.8, можно использовать фильтр default для исключения параметров модуля, используя специальную переменную omit:
- name: touch files with an optional mode
file: dest={{ item.path }} state=touch mode={{ item.mode | default(omit) }}
loop:
- path: /tmp/foo
- path: /tmp/bar
- path: /tmp/baz
mode: "0444"
Для первых двух файлов в списке режим по умолчанию будет определяться маской umask системы, так как параметр mode= не будет отправлен в модуль file, в то время как конечный файл получит опцию mode=0444.
Примечание
Если вы «цепляете» дополнительные фильтры после фильтра default(omit), вы должны сделать что-то вроде этого: “{{ foo | default(None) | some_filter or omit }}”. В этом примере значение по умолчанию None (пустое значение python) приведёт к ошибке последующих фильтров, что вызовет часть логики or omit. Однако использование omit таким образом очень специфично для последующих цепочек фильтров, поэтому будьте готовы к некоторым экспериментам, если вы это сделаете.
Фильтры для списков
Все эти фильтры работают со списками.
Новая функция в версии 1.8.
Для получения минимального значения из списка чисел:
{{ list1 | min }}
Для получения максимального значения из списка чисел:
{{ [3, 4, 2] | max }}
Новая функция в версии 2.5.
Разворачивание списка (то же самое, что делает поиск flatten:
{{ [3, [4, 2] ] | flatten }}
Развернуть только первый уровень списка (аналогично поиску items:
{{ [3, [4, [2]] ] | flatten(levels=1) }}
Фильтры теории множеств
Все эти функции возвращают уникальное множество из множеств или списков.
Новая функция в версии 1.4.
Для получения уникального множества из списка:
{{ list1 | unique }}
Для получения объединения двух списков:
{{ list1 | union(list2) }}
Для получения пересечения 2 списков (уникальный список всех элементов в обоих):
{{ list1 | intersect(list2) }}
Для получения разности 2 списков (элементы в 1, которых нет во 2):
{{ list1 | difference(list2) }}
Для получения симметрической разности 2 списков (элементы, уникальные для каждого списка):
{{ list1 | symmetric_difference(list2) }}
Фильтр для словарей
Новая функция в версии 2.6.
Для преобразования словаря в список элементов, подходящий для цикла, используйте dict2items:
{{ dict | dict2items }}
Что преобразует:
tags: Application: payment Environment: dev
в:
- key: Application value: payment - key: Environment value: dev
Фильтр items2dict
Новая функция в версии 2.7.
Этот фильтр преобразует список словарей с 2 ключами в словарь, отображая значения этих ключей в пары key: value:
{{ tags | items2dict }}
Что преобразует:
tags:
- key: Application
value: payment
- key: Environment
value: dev
в:
Application: payment Environment: dev
Это обратное преобразование фильтра dict2items.
items2dict принимает 2 именованных аргумента, key_name и value_name, которые позволяют настроить имена ключей для преобразования:
{{ tags | items2dict(key_name='key', value_name='value') }}
Фильтры zip и zip_longest
Новая функция в версии 2.3.
Для получения списка, объединяющего элементы других списков, используйте zip:
- name: give me list combo of two lists
debug:
msg: "{{ [1,2,3,4,5] | zip(['a','b','c','d','e','f']) | list }}"
- name: give me shortest combo of two lists
debug:
msg: "{{ [1,2,3] | zip(['a','b','c','d','e','f']) | list }}"
Для исчерпания всех списков используйте zip_longest:
- name: give me longest combo of three lists , fill with X
debug:
msg: "{{ [1,2,3] | zip_longest(['a','b','c','d','e','f'], [21, 22, 23], fillvalue='X') | list }}"
Аналогично выводу фильтра items2dict, эти фильтры могут использоваться для создания dict:
{{ dict(keys_list | zip(values_list)) }}
Что преобразует:
list_one: - one - two list_two: - apple - orange
в:
one: apple two: orange
Фильтр subelements
Новая функция в версии 2.7.
Производит произведение объекта и значений подэлементов этого объекта, аналогично поиску subelements:
{{ users | subelements('groups', skip_missing=True) }}
Что преобразует:
users:
- name: alice
authorized:
- /tmp/alice/onekey.pub
- /tmp/alice/twokey.pub
groups:
- wheel
- docker
- name: bob
authorized:
- /tmp/bob/id_rsa.pub
groups:
- docker
В:
-
- name: alice
groups:
- wheel
- docker
authorized:
- /tmp/alice/onekey.pub
- wheel
-
- name: alice
groups:
- wheel
- docker
authorized:
- /tmp/alice/onekey.pub
- docker
-
- name: bob
authorized:
- /tmp/bob/id_rsa.pub
groups:
- docker
- docker
Пример использования этого фильтра с loop:
- name: Set authorized ssh key, extracting just that data from 'users'
authorized_key:
user: "{{ item.0.name }}"
key: "{{ lookup('file', item.1) }}"
loop: "{{ users | subelements('authorized') }}"
Фильтр случайного MAC-адреса
Новая функция в версии 2.6.
Этот фильтр может использоваться для генерации случайного MAC-адреса из строчного префикса.
Для получения случайного MAC-адреса из строчного префикса, начинающегося с ‘52:54:00’:
"{{ '52:54:00' | random_mac }}"
# => '52:54:00:ef:1c:03'
Обратите внимание, что при ошибках в строке префикса фильтр выдаст ошибку.
Фильтр случайного числа
Новая функция в версии 1.6.
Этот фильтр можно использовать аналогично стандартному фильтру Jinja2 random (возвращающему случайный элемент из последовательности элементов), но также можно сгенерировать случайное число в заданном диапазоне.
Для получения случайного элемента из списка:
"{{ ['a','b','c'] | random }}"
# => 'c'
Для получения случайного числа от 0 до указанного числа:
"{{ 60 | random }} * * * * root /script/from/cron"
# => '21 * * * * root /script/from/cron'
Получить случайное число от 0 до 100, но с шагом 10:
{{ 101 | random(step=10) }}
# => 70
Получить случайное число от 1 до 100, но с шагом 10:
{{ 101 | random(1, 10) }}
# => 31
{{ 101 | random(start=1, step=10) }}
# => 51
Начиная с версии Ansible 2.3, также возможно инициализировать генератор случайных чисел из начального значения. Таким образом, вы можете создать случайные, но идемпотентные числа:
"{{ 60 | random(seed=inventory_hostname) }} * * * * root /script/from/cron"
Фильтр перемешивания
Новая функция в версии 1.8.
Этот фильтр случайным образом перемешает существующий список, давая разный порядок при каждом вызове.
Для получения случайного списка из существующего списка:
{{ ['a','b','c'] | shuffle }}
# => ['c','a','b']
{{ ['a','b','c'] | shuffle }}
# => ['b','c','a']
Начиная с Ansible 2.3, также возможно перемешивание списка идемпотентно. Вам нужно только начальное значение.:
{{ ['a','b','c'] | shuffle(seed=inventory_hostname) }}
# => ['b','a','c']
Обратите внимание, что при использовании с элементом, который не является списком, это действие не выполняется, в противном случае всегда возвращается список
Математические
Новая функция в версии 1.9.
Получить логарифм (по умолчанию e):
{{ myvar | log }}
Получить десятичный логарифм:
{{ myvar | log(10) }}
Вычислить степень 2! (или 5):
{{ myvar | pow(2) }}
{{ myvar | pow(5) }}
Квадратный корень или 5-й:
{{ myvar | root }}
{{ myvar | root(5) }}
Обратите внимание, что jinja2 уже предоставляет некоторые функции, такие как abs() и round().
Фильтр запроса JSON
Новая версия с 2.2.
Иногда вы сталкиваетесь со сложной структурой данных в формате JSON, и вам нужно извлечь только небольшой набор данных в ней. Фильтр json_query позволяет запрашивать сложную структуру JSON и итерироваться по ней с помощью цикла.
Примечание
Этот фильтр основан на jmespath, и вы можете использовать тот же синтаксис. Примеры см. на странице примеров jmespath.
Теперь рассмотрим следующую структуру данных:
domain_definition:
domain:
cluster:
- name: "cluster1"
- name: "cluster2"
server:
- name: "server11"
cluster: "cluster1"
port: "8080"
- name: "server12"
cluster: "cluster1"
port: "8090"
- name: "server21"
cluster: "cluster2"
port: "9080"
- name: "server22"
cluster: "cluster2"
port: "9090"
library:
- name: "lib1"
target: "cluster1"
- name: "lib2"
target: "cluster2"
Чтобы извлечь все кластеры из этой структуры, вы можете использовать следующий запрос:
- name: "Display all cluster names"
debug:
var: item
loop: "{{ domain_definition | json_query('domain.cluster[*].name') }}"
То же самое для всех имён серверов:
- name: "Display all server names"
debug:
var: item
loop: "{{ domain_definition | json_query('domain.server[*].name') }}"
Этот пример показывает порты из кластера cluster1:
- name: "Display all ports from cluster1"
debug:
var: item
loop: "{{ domain_definition | json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster1'].port"
Примечание
Вы можете использовать переменную, чтобы сделать запрос более удобочитаемым.
Или, как альтернатива, вывести порты в строке, разделённой запятыми:
- name: "Display all ports from cluster1 as a string"
debug:
msg: "{{ domain_definition | json_query('domain.server[?cluster==`cluster1`].port') | join(', ') }}"
Примечание
Здесь, используя обратные кавычки для литералов, избегается экранирование кавычек и сохраняется удобочитаемость.
Или, используя YAML экранирование одинарных кавычек:
- name: "Display all ports from cluster1"
debug:
var: item
loop: "{{ domain_definition | json_query('domain.server[?cluster==''cluster1''].port') }}"
Примечание
Экранирование одинарных кавычек внутри одинарных кавычек в YAML выполняется путём удвоения одинарной кавычки.
В этом примере мы получаем хеш-таблицу со всеми портами и именами кластера:
- name: "Display all server ports and names from cluster1"
debug:
var: item
loop: "{{ domain_definition | json_query(server_name_cluster1_query) }}"
vars:
server_name_cluster1_query: "domain.server[?cluster=='cluster2'].{name: name, port: port}"
Фильтр IP-адресов
Новая версия с 1.9.
Чтобы проверить, является ли строка корректным IP-адресом:
{{ myvar | ipaddr }}
Вы также можете потребовать определённую версию протокола IP:
{{ myvar | ipv4 }}
{{ myvar | ipv6 }}
Фильтр IP-адресов также может использоваться для извлечения определённой информации из IP-адреса. Например, чтобы получить сам IP-адрес из CIDR, вы можете использовать:
{{ '192.0.2.1/24' | ipaddr('address') }}
Дополнительную информацию о фильтре ipaddr и полное руководство по использованию можно найти в фильтре ipaddr.
Фильтры командной строки сети
Новая версия с 2.4.
Для преобразования вывода команды CLI сетевого устройства в структурированный вывод JSON используйте фильтр parse_cli:
{{ output | parse_cli('path/to/spec') }}
Фильтр parse_cli загрузит файл спецификаций и пропустит вывод команды через него, вернув вывод в формате JSON. Файл спецификаций YAML определяет способ обработки вывода CLI.
Файл спецификаций должен быть валидным YAML-файлом. Он определяет способ обработки вывода CLI и возвращает данные в формате JSON. Ниже приведен пример валидного файла спецификаций, который будет обрабатывать вывод команды show vlan.
---
vars:
vlan:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
enabled: "{{ item.state != 'act/lshut' }}"
state: "{{ item.state }}"
keys:
vlans:
value: "{{ vlan }}"
items: "^(?P<vlan_id>\\d+)\\s+(?P<name>\\w+)\\s+(?P<state>active|act/lshut|suspended)"
state_static:
value: present
Файл спецификаций выше вернёт структуру данных JSON, представляющую собой список хешей с проанализированной информацией VLAN.
Ту же самую команду можно было бы обработать в виде хеша, используя директивы ключа и значений. Вот пример обработки вывода в хеш-значение с использованием той же команды show vlan.
---
vars:
vlan:
key: "{{ item.vlan_id }}"
values:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
enabled: "{{ item.state != 'act/lshut' }}"
state: "{{ item.state }}"
keys:
vlans:
value: "{{ vlan }}"
items: "^(?P<vlan_id>\\d+)\\s+(?P<name>\\w+)\\s+(?P<state>active|act/lshut|suspended)"
state_static:
value: present
Другой распространённый случай использования для обработки команд CLI — разбить большую команду на блоки, которые можно обработать. Это можно сделать, используя директивы start_block и end_block для разделения команды на обрабатываемые блоки.
---
vars:
interface:
name: "{{ item[0].match[0] }}"
state: "{{ item[1].state }}"
mode: "{{ item[2].match[0] }}"
keys:
interfaces:
value: "{{ interface }}"
start_block: "^Ethernet.*$"
end_block: "^$"
items:
- "^(?P<name>Ethernet\\d\\/\\d*)"
- "admin state is (?P<state>.+),"
- "Port mode is (.+)"
Приведённый выше пример обработает вывод команды show interface в список хешей.
Фильтры сети также поддерживают обработку вывода команды CLI с помощью библиотеки TextFSM. Чтобы обработать вывод CLI с TextFSM, используйте следующий фильтр:
{{ output.stdout[0] | parse_cli_textfsm('path/to/fsm') }}
Использование фильтра TextFSM требует установки библиотеки TextFSM.
Фильтры XML сети
Новая версия с 2.5.
Чтобы преобразовать XML-вывод команды сетевого устройства в структурированный вывод JSON, используйте фильтр parse_xml:
{{ output | parse_xml('path/to/spec') }}
Фильтр parse_xml загрузит файл спецификаций и пропустит вывод команды, отформатировав его как JSON.
Файл спецификаций должен быть валидным YAML-файлом. Он определяет способ обработки XML-вывода и возвращает данные в формате JSON.
Ниже приведен пример валидного файла спецификаций, который будет обрабатывать вывод команды show vlan | display xml.
---
vars:
vlan:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
desc: "{{ item.desc }}"
enabled: "{{ item.state.get('inactive') != 'inactive' }}"
state: "{% if item.state.get('inactive') == 'inactive'%} inactive {% else %} active {% endif %}"
keys:
vlans:
value: "{{ vlan }}"
top: configuration/vlans/vlan
items:
vlan_id: vlan-id
name: name
desc: description
state: ".[@inactive='inactive']"
Файл спецификаций выше вернёт структуру данных JSON, представляющую собой список хешей с проанализированной информацией VLAN.
Ту же самую команду можно было бы обработать в виде хеша, используя директивы ключа и значений. Вот пример обработки вывода в хеш-значение с использованием той же команды show vlan | display xml.
---
vars:
vlan:
key: "{{ item.vlan_id }}"
values:
vlan_id: "{{ item.vlan_id }}"
name: "{{ item.name }}"
desc: "{{ item.desc }}"
enabled: "{{ item.state.get('inactive') != 'inactive' }}"
state: "{% if item.state.get('inactive') == 'inactive'%} inactive {% else %} active {% endif %}"
keys:
vlans:
value: "{{ vlan }}"
top: configuration/vlans/vlan
items:
vlan_id: vlan-id
name: name
desc: description
state: ".[@inactive='inactive']"
Значение top — это XPath относительно узла XML-корня. В приведённом ниже примере XML-вывода значение top — это configuration/vlans/vlan, что представляет собой выражение XPath относительно корневого узла (<rpc-reply>). configuration в значении top — это самый внешний контейнерный узел, а vlan — самый внутренний контейнерный узел.
items — это словарь пар ключ-значение, которые сопоставляют пользовательские имена с выражениями XPath, выбирающими элементы. Выражение XPath относительно значения XPath, содержащегося в top. Например, vlan_id в файле спецификаций — это пользовательское имя, а его значение vlan-id — это значение, относящееся к XPath в top
Атрибуты XML-тегов могут быть извлечены с помощью выражений XPath. Значение state в спецификации — это выражение XPath, используемое для получения атрибутов тега vlan в выходном XML:
<rpc-reply>
<configuration>
<vlans>
<vlan inactive="inactive">
<name>vlan-1</name>
<vlan-id>200</vlan-id>
<description>This is vlan-1</description>
</vlan>
</vlans>
</configuration>
</rpc-reply>
Примечание
Дополнительную информацию о поддерживаемых выражениях XPath см. на https://docs.python.org/2/library/xml.etree.elementtree.html#xpath-support.
Фильтры хеширования
Новая версия с 1.9.
Чтобы получить хеш sha1 строки:
{{ 'test1' | hash('sha1') }}
Чтобы получить хеш md5 строки:
{{ 'test1' | hash('md5') }}
Получить контрольную сумму строки:
{{ 'test2' | checksum }}
Другие хеши (зависит от платформы):
{{ 'test2' | hash('blowfish') }}
Чтобы получить хеш пароля sha512 (случайная соль):
{{ 'passwordsaresecret' | password_hash('sha512') }}
Чтобы получить хеш пароля sha256 со специфической солью:
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt') }}
Идемпотентный метод генерации уникальных хешей на систему — использование соли, которая сохраняется между запусками:
{{ 'secretpassword' | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}
Доступные типы хешей зависят от системы Ansible, 'hash' зависит от hashlib, password_hash зависит от passlib (https://passlib.readthedocs.io/en/stable/lib/passlib.hash.html).
Новая версия с 2.7.
Некоторые типы хешей позволяют указать параметр rounds:
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=10000) }}
Комбинирование хешей/словарей
Новая версия с 2.0.
Фильтр combine позволяет объединять хеши. Например, следующее перезапишет ключи в одном хеше:
{{ {'a':1, 'b':2} | combine({'b':3}) }}
Результат хеша будет:
{'a':1, 'b':3}
Фильтр также принимает необязательный параметр recursive=True для перезаписи ключей в первом хеше, а также рекурсивного входа в вложенные хеши и объединения их ключей.
{{ {'a':{'foo':1, 'bar':2}, 'b':2} | combine({'a':{'bar':3, 'baz':4}}, recursive=True) }}
Это приведет к:
{'a':{'foo':1, 'bar':3, 'baz':4}, 'b':2}
Фильтр также может принимать несколько аргументов для объединения:
{{ a | combine(b, c, d) }}
В этом случае ключи в d перезапишут ключи в c, которые перезапишут ключи в b, и так далее.
Это поведение не зависит от значения параметра hash_behaviour в ansible.cfg.
Извлечение значений из контейнеров
Новая версия с 2.1.
Фильтр extract используется для отображения списка индексов в список значений из контейнера (хеша или массива):
{{ [0,2] | map('extract', ['x','y','z']) | list }}
{{ ['x','y'] | map('extract', {'x': 42, 'y': 31}) | list }}
Результаты вышеприведённых выражений:
['x', 'z'] [42, 31]
Фильтр может принимать другой аргумент:
{{ groups['x'] | map('extract', hostvars, 'ec2_ip_address') | list }}
Это берёт список хостов в группе ‘x’, ищет их в hostvars, а затем ищет ec2_ip_address результата. Конечный результат — список IP-адресов для хостов в группе ‘x’.
Третий аргумент фильтра также может быть списком для рекурсивного поиска внутри контейнера:
{{ ['a'] | map('extract', b, ['x','y']) | list }}
Это вернёт список, содержащий значение b[‘a’][‘x’][‘y’].
Фильтр комментариев
Новая версия с 2.0.
Фильтр comment позволяет форматировать текст выбранным стилем комментариев. Например:
{{ "Plain style (default)" | comment }}
произведёт этот вывод:
# # Plain style (default) #
Аналогичный способ форматирования может быть применён к стилям C (//...), блоку C (/*...*/), Erlang (%...) и XML (<!--...-->):
{{ "C style" | comment('c') }}
{{ "C block style" | comment('cblock') }}
{{ "Erlang style" | comment('erlang') }}
{{ "XML style" | comment('xml') }}
Если вам нужен определённый символ комментария, который не включён ни одним из вышеперечисленных, вы можете настроить его с помощью:
{{ "My Special Case" | comment(decoration="! ") }}
производя:
! ! My Special Case !
Также возможно полностью настроить стиль комментариев:
{{ "Custom style" | comment('plain', prefix='#######\n#', postfix='#\n#######\n ###\n #') }}
Это создаст следующий вывод:
#######
#
# Custom style
#
#######
###
#
Фильтр также может применяться к любым переменным Ansible. Например, чтобы сделать вывод переменной ansible_managed более удобочитаемым, мы можем изменить определение в файле ansible.cfg на это:
[defaults]
ansible_managed = This file is managed by Ansible.%n
template: {file}
date: %Y-%m-%d %H:%M:%S
user: {uid}
host: {host}
а затем использовать переменную с фильтром comment:
{{ ansible_managed | comment }}
что произведёт этот вывод:
# # This file is managed by Ansible. # # template: /home/ansible/env/dev/ansible_managed/roles/role1/templates/test.j2 # date: 2015-09-10 11:02:58 # user: ansible # host: myhost #
Фильтр разделения URL
Новая версия с 2.4.
Фильтр urlsplit извлекает фрагмент, имя хоста, netloc, пароль, путь, порт, запрос, схему и имя пользователя из URL. Без аргументов возвращает словарь всех полей:
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('hostname') }}
# => 'www.acme.com'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('netloc') }}
# => 'user:password@www.acme.com:9000'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('username') }}
# => 'user'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('password') }}
# => 'password'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('path') }}
# => '/dir/index.html'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('port') }}
# => '9000'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('scheme') }}
# => 'http'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('query') }}
# => 'query=term'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('fragment') }}
# => 'fragment'
{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit }}
# =>
# {
# "fragment": "fragment",
# "hostname": "www.acme.com",
# "netloc": "user:password@www.acme.com:9000",
# "password": "password",
# "path": "/dir/index.html",
# "port": 9000,
# "query": "query=term",
# "scheme": "http",
# "username": "user"
# }
Фильтры регулярных выражений
Для поиска строки с помощью регулярного выражения используйте фильтр «regex_search»:
# search for "foo" in "foobar"
{{ 'foobar' | regex_search('(foo)') }}
# will return empty if it cannot find a match
{{ 'ansible' | regex_search('(foobar)') }}
# case insensitive search in multiline mode
{{ 'foo\nBAR' | regex_search("^bar", multiline=True, ignorecase=True) }}
Для поиска всех вхождений совпадений с регулярным выражением используйте фильтр «regex_findall»:
# Return a list of all IPv4 addresses in the string
{{ 'Some DNS servers are 8.8.8.8 and 8.8.4.4' | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }}
Для замены текста в строке с помощью регулярного выражения используйте фильтр «regex_replace»:
# convert "ansible" to "able"
{{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }}
# convert "foobar" to "bar"
{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}
# convert "localhost:80" to "localhost, 80" using named groups
{{ 'localhost:80' | regex_replace('^(?P<host>.+):(?P<port>\\d+)$', '\\g<host>, \\g<port>') }}
# convert "localhost:80" to "localhost"
{{ 'localhost:80' | regex_replace(':80') }}
# add "https://" prefix to each item in a list
{{ hosts | map('regex_replace', '^(.*)$', 'https://\\1') | list }}
Примечание
До версии ansible 2.0, если фильтр «regex_replace» использовался с переменными внутри YAML-аргументов (в отличие от более простых аргументов 'ключ=значение'), вам нужно было экранировать обратные ссылки (например, \\1) четырьмя обратными слешами (\\\\) вместо двух (\\).
Введено в версии 2.0.
Для экранирования специальных символов внутри регулярного выражения используйте фильтр «regex_escape»:
# convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$'
{{ '^f.*o(.*)$' | regex_escape() }}
Другие полезные фильтры
Для добавления кавычек для использования в оболочке:
- shell: echo {{ string_value | quote }}
Для использования одного значения при истинном и другого при ложном (введено в версии 1.9):
{{ (name == "John") | ternary('Mr','Ms') }}
Для конкатенации списка в строку:
{{ list | join(" ") }}
Для получения имени последней части пути файла, например, «foo.txt» из «/etc/asdf/foo.txt»:
{{ path | basename }}
Для получения имени последней части пути файла в стиле Windows (введено в версии 2.0):
{{ path | win_basename }}
Для разделения буквенного обозначения диска в пути файла в стиле Windows от остальной части пути (введено в версии 2.0):
{{ path | win_splitdrive }}
Для получения только буквенного обозначения диска:
{{ path | win_splitdrive | first }}
Для получения остальной части пути без буквенного обозначения диска:
{{ path | win_splitdrive | last }}
Для получения каталога из пути:
{{ path | dirname }}
Для получения каталога из пути в стиле Windows (введено в версии 2.0):
{{ path | win_dirname }}
Для расширения пути, содержащего символ тильды (~) (введено в версии 1.5):
{{ path | expanduser }}
Для расширения пути, содержащего переменные окружения:
{{ path | expandvars }}
Примечание
expandvars расширяет локальные переменные; его использование с удаленными путями может привести к ошибкам.
Введено в версии 2.6.
Для получения реального пути ссылки (введено в версии 1.8):
{{ path | realpath }}
Для получения относительного пути ссылки от начальной точки (введено в версии 1.7):
{{ path | relpath('/etc') }}
Для получения корня и расширения пути или имени файла (введено в версии 2.0):
# with path == 'nginx.conf' the return would be ('nginx', '.conf')
{{ path | splitext }}
Для работы со строками, закодированными в Base64:
{{ encoded | b64decode }}
{{ decoded | b64encode }}
Начиная с версии 2.6, вы можете определить тип кодирования, используемый по умолчанию utf-8:
{{ encoded | b64decode(encoding='utf-16-le') }}
{{ decoded | b64encode(encoding='utf-16-le') }}
Введено в версии 2.6.
Для создания UUID из строки (введено в версии 1.9):
{{ hostname | to_uuid }}
Для приведения значений к определенным типам, например, когда вы вводите строку как «True» из vars_prompt, а система не распознаёт её как булево значение:
- debug:
msg: test
when: some_string_value | bool
Введено в версии 1.6.
Для использования одного атрибута из каждого элемента в списке сложных переменных, используйте фильтр «map» (см. документацию Jinja2 map() для получения более подробной информации):
# get a comma-separated list of the mount points (e.g. "/,/mnt/stuff") on a host
{{ ansible_mounts | map(attribute='mount') | join(',') }}
Для получения объекта даты из строки используйте фильтр to_datetime (введено в версии 2.2):
# Get total amount of seconds between two dates. Default date format is %Y-%m-%d %H:%M:%S but you can pass your own format
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).total_seconds() }}
# Get remaining seconds after delta has been calculated. NOTE: This does NOT convert years, days, hours, etc to seconds. For that, use total_seconds()
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2016-08-14 18:00:00" | to_datetime)).seconds }}
# This expression evaluates to "12" and not "132". Delta is 2 hours, 12 seconds
# get amount of days between two dates. This returns only number of days and discards remaining hours, minutes, and seconds
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).days }}
Введено в версии 2.4.
Для форматирования даты с использованием строки (как с командой оболочки date), используйте фильтр «strftime»:
# Display year-month-day
{{ '%Y-%m-%d' | strftime }}
# Display hour:min:sec
{{ '%H:%M:%S' | strftime }}
# Use ansible_date_time.epoch fact
{{ '%Y-%m-%d %H:%M:%S' | strftime(ansible_date_time.epoch) }}
# Use arbitrary epoch value
{{ '%Y-%m-%d' | strftime(0) }} # => 1970-01-01
{{ '%Y-%m-%d' | strftime(1441357287) }} # => 2015-09-04
Примечание
Для получения всех возможных строк, проверьте https://docs.python.org/2/library/time.html#time.strftime
Фильтры комбинирования
Введено в версии 2.3.
Этот набор фильтров возвращает список комбинированных списков. Для получения перестановок списка:
- name: give me largest permutations (order matters)
debug:
msg: "{{ [1,2,3,4,5] | permutations | list }}"
- name: give me permutations of sets of three
debug:
msg: "{{ [1,2,3,4,5] | permutations(3) | list }}"
Для комбинаций всегда требуется размер набора:
- name: give me combinations for sets of two
debug:
msg: "{{ [1,2,3,4,5] | combinations(2) | list }}"
Также см. фильтры zip и zip_longest
Фильтры отладки
Введено в версии 2.3.
Используйте фильтр type_debug для отображения базового типа Python переменной. Это может быть полезно при отладке в ситуациях, когда вам необходимо знать точный тип переменной:
{{ myvar | type_debug }}
Некоторые полезные фильтры обычно добавляются с каждой новой версией Ansible. Раздел по разработке документов показывает, как расширить фильтры Ansible, написав свои собственные плагины, хотя в целом мы рекомендуем добавлять новые в ядро, чтобы все могли их использовать.
См. также
- Работа с Playbook
- Введение в Playbook
- Условные выражения
- Условные операторы в Playbook
- Использование переменных
- Всё о переменных
- Циклы
- Циклы в Playbook
- Роли
- Организация Playbook с помощью ролей
- Рекомендации по лучшим практикам
- Рекомендации по лучшим практикам в Playbook
- Список рассылки пользователей
- У вас есть вопросы? Обращайтесь на форум!
- irc.freenode.net
- Чат-канал IRC #ansible
© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.7/user_guide/playbooks_filters.html