Spec-Zone.ru › Ansible 2.5

Фильтры

  • Фильтры форматирования данных
  • Принудительное определение переменных
  • Установление значений по умолчанию для неопределённых переменных
  • Исключение параметров
  • Фильтры для списков
  • Фильтры теории множеств
  • Фильтр случайного числа
  • Фильтр перемешивания
  • Математические
  • Фильтр запроса 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 }}"

Принудительное определение переменных

По умолчанию Ansible и ansible.cfg требуют, чтобы переменные были определены, но это можно отключить.

Это позволяет явно проверить поведение без включённых проверок:

{{ variable | mandatory }}

Значение переменной будет использоваться как есть, но оценка шаблона вызовет ошибку, если она не определена.

Установление значений по умолчанию для неопределённых переменных

Jinja2 предоставляет полезный фильтр ‘default’, который часто является лучшим подходом к обработке случаев, когда переменная не определена:

{{ some_variable | default(5) }}

В приведенном выше примере, если переменная ‘some_variable’ не определена, используемое значение будет 5, а не будет выводиться ошибка.

Если переменная равна пустой строке, второй параметр фильтра должен быть установлен на true:

{{ lookup('env', 'MY_USER') | default('admin', true) }}

Исключение параметров

Начиная с Ansible 1.8, можно использовать фильтр по умолчанию для исключения параметров модуля, используя специальную переменную 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= не будет передан модулю файла, в то время как последний файл получит опцию mode=0444.

Примечание

Если вы используете дополнительные фильтры после фильтра default(omit), вы должны сделать что-то вроде этого: “{{ foo | default(None) | some_filter or omit }}”. В этом примере значение по умолчанию None (python null) вызовет ошибку последующих фильтров, что запустит часть логики or omit. Использование omit таким образом очень специфично для последующих фильтров, поэтому будьте готовы к некоторым попыткам и ошибкам, если вы это сделаете.

Фильтры для списков

Эти фильтры работают со списковыми переменными.

Новое в версии 1.8.

Чтобы получить минимальное значение из списка чисел:

{{ list1 | min }}

Чтобы получить максимальное значение из списка чисел:

{{ [3, 4, 2] | max }}

Новое в версии 2.5.

Разворачивать список (то же самое, что и flatten lookup):

{{ [3, [4, 2] ] | flatten }}

Разворачивать только первый уровень списка (аналогично items lookup):

{{ [3, [4, [2]] ] | flatten(level=1) }}

Чтобы получить минимальное значение из списка чисел:

.. _set_theory_filters:

Фильтры теории множеств

Все эти функции возвращают уникальное множество из множеств или списков.

Новое в версии 1.4.

Чтобы получить уникальное множество из списка:

{{ list1 | unique }}

Чтобы получить объединение двух списков:

{{ list1 | union(list2) }}

Чтобы получить пересечение 2 списков (уникальный список всех элементов в обоих):

{{ list1 | intersect(list2) }}

Чтобы получить разность 2 списков (элементы в 1, которых нет во 2):

{{ list1 | difference(list2) }}

Чтобы получить симметрическую разность 2 списков (элементы, уникальные для каждого списка):

{{ list1 | symmetric_difference(list2) }}

Фильтр случайного числа

Новое в версии 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, также можно перетасовать список идемпотентно. Всё, что вам нужно, это seed.:

{{ ['a','b','c'] | shuffle(seed=inventory_hostname) }}
# => ['b','a','c']

обратите внимание, что при использовании с элементом, не являющимся «список», он является noop, в противном случае он всегда возвращает список

Математические

Новое в версии 1.9.

Получить логарифм (по умолчанию по основанию e):

{{ myvar | log }}

Получить логарифм по основанию 10:

{{ 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') }}"

Этот пример показывает порты из кластера1:

- 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.

Для преобразования вывода команды сетевого устройства в структурированный JSON-вывод, используйте фильтр parse_cli:

{{ output | parse_cli('path/to/spec') }}

Фильтр parse_cli загрузит файл спецификации и пропустит вывод команды через него, вернув JSON-вывод. Файл спецификации YAML определяет способ разбора вывода командной строки.

Файл спецификаций должен быть валидным 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.

Ту же команду можно проанализировать в хеш, используя директивы key и values. Вот пример, как проанализировать вывод в значение хеша, используя ту же команду 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.

Ту же команду можно проанализировать в хеш, используя директивы key и values. Вот пример, как проанализировать вывод в значение хеша, используя ту же команду 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 (http://passlib.readthedocs.io/en/stable/lib/passlib.hash.html).

Объединение хешей/словарей

Новое в версии 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)') }}

Чтобы найти все совпадения регулярных выражений, используйте фильтр «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') }}

Примечание

До Ansible 2.0, если фильтр «regex_replace» использовался с переменными внутри YAML-аргументов (в отличие от более простых аргументов «ключ=значение»), вам нужно было экранировать обратные ссылки (например, \\1) 4 обратными слешами (\\\\) вместо 2 (\\).

Новое в версии 2.0.

Чтобы экранировать специальные символы в регулярном выражении, используйте фильтр «regex_escape»:

# convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$'
{{ '^f.*o(.*)$' | regex_escape() }}

Другие полезные фильтры

Чтобы добавить кавычки для использования в оболочке:

- shell: echo {{ string_value | quote }}

Чтобы использовать одно значение при true и другое при false (новое в версии 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 }}

Чтобы получить только букву диска Windows:

{{ path | win_splitdrive | first }}

Чтобы получить остальную часть пути без буквы диска:

{{ path | win_splitdrive | last }}

Чтобы получить каталог из пути:

{{ path | dirname }}

Чтобы получить каталог из пути в стиле Windows (новая версия 2.0):

{{ path | win_dirname }}

Чтобы расширить путь, содержащий символ тильды (~) (новое в версии 1.5):

{{ path | expanduser }}

Чтобы получить реальный путь ссылки (новое в версии 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 }}

Чтобы создать 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.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:

- 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 }}"

Новая версия с 2.4.

Для форматирования даты с использованием строки (как в команде shell 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.

Используйте фильтр type_debug для отображения базового типа Python переменной. Это может быть полезно при отладке в ситуациях, когда вам нужен точный тип переменной:

{{ myvar | type_debug }}

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

См. также

Работа с Playbook
Введение в Playbook
Условные операторы
Условные операторы в Playbook
Переменные
Всё о переменных
Циклы
Использование циклов в Playbook
Роли
Организация Playbook по ролям
Рекомендации
Рекомендации по Playbook
Список рассылки пользователей
У вас есть вопрос? Загляните в группу Google!
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.5/user_guide/playbooks_filters.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API