Aller au contenu principal

Les filtres Ansible - 3ème partie

· 7 minutes de lecture
Stéphane ROBERT
Consultant DevOps

La suite des filtres Jinja, après les billets 1 et 2. Au menu du jour les filtres de liste, de textes, quelques mathématiques et divers autres.

Travailler avec les listes

Obtenir un élément aléatoire d'une liste

Pour prendre un élément au hazard dans une liste on utilise le filtre random:

"{{ ['a','b','c'] | random }}"
# => 'c'

On peut utiliser le même filtre pour générer un nombre aléatoire parmi un range :

{{ 101 | random(step=10) }}
# => 70

Vous pouvez initialiser le générateur de nombres aléatoires à partir d'une chaîne pour créer des nombres aléatoires et idempotents:

"{{ 60 | random(seed=inventory_hostname) }} * * * * root /script/from/cron"

Obtenir les valeurs min et max d'une liste

Les filtres min et max d'une liste


{{ list1 | min }}

{{ list1 | max }}

Aplatir une liste

Pour sortir tous les éléments de listes imbriquées le filtre flatern est parfait. On peut définir un niveau max de traitements:

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

Mélanger une liste

Pour mélanger une liste, bien pratique quand on veut qu'un traitement ne se fasse jamais dans le même ordre. Comme pour random on peut utiliser une chaîne.

{{ ['a','b','c'] | shuffle }}
# => ['c','a','b']

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

Valeurs uniques d'une liste

# list1: [1, 2, 5, 1, 3, 4, 10]
{{ list1 | unique }}
# => [1, 2, 5, 3, 4, 10]

Union de listes

# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | union(list2) }}
# => [1, 2, 5, 1, 3, 4, 10, 11, 99]

Intersection de listes

# list1: [1, 2, 5, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | intersect(list2) }}
# => [1, 2, 5, 3, 4]

Différence de listes

# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | difference(list2) }}
# => [10]

Différence symétrique d'une liste

# list1: [1, 2, 5, 1, 3, 4, 10]
# list2: [1, 2, 3, 4, 5, 11, 99]
{{ list1 | symmetric_difference(list2) }}
# => [10, 11, 99]

Quelques filtres de calcul

Avec les filtres on peut également effectuer des calculs:

log

{{ myvar | log }}
{{ myvar | log(10) }}

puissance

{{ myvar | pow(2) }}

racine carrée

{{ myvar | root }}

Des filtres pour sécuriser les données ansible

Très utile pour sécuriser vos données le cryptage de chaîne et la génération de mots de passe.

Pour générer des mots de passes

{{ 'secretpassword' | password_hash('sha512', 65534 | random(seed=inventory_hostname) | string) }}
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt', rounds=10000) }}

Pour chiffrer des chaines

{{ 'test2' | hash('blowfish') }}
{{ 'test1' | hash('md5') }}
{{ 'test1' | hash('sha1') }}

Pour calculer un checksum

{{ 'test2' | checksum }}

Les filtres pour le texte

Ajouter des commentaires à des fichiers

Le filtre comment permet de créer des commentaires dans un fichier à partir du texte modèle. Par défaut, Ansible utilise #pour démarrer une ligne de commentaire et ajoute une ligne de commentaire vide au-dessus et en dessous du modèle.

{{ "Plain style (default)" | comment }}

donne:

#
# Plain style (default)
#

Il est possible de choisir d'autres style de commentaires:

{{ "C style" | comment('c') }}
{{ "C block style" | comment('cblock') }}
{{ "Erlang style" | comment('erlang') }}
{{ "XML style" | comment('xml') }}

On peut même créer son propre style de commentaire:

{{ "My Special Case" | comment(decoration="! ") }}
# ou encore
{{ "Custom style" | comment('plain', prefix='#######\n#', postfix='#\n#######\n   ###\n    #') }}

donne :

#######
#
# Custom style
#
#######
   ###
    #

Ajouter des guillemets à une commande shell:

- name: Run a shell command
  ansible.builtin.shell: echo {{ string_value | quote }}

Concaténer une liste en une chaîne:

{{ list | join(" ") }}

Encoder et décoder des chaînes en Base64

{{ encoded | b64decode }}
{{ decoded | string | b64encode }}

Depuis la version 2.6, vous pouvez définir le type d'encodage à utiliser, la valeur par défaut est utf-8:

Les filtres pour gérer des url

Il existe un seul filtre permettant de traiter les urls urlsplit.

Par défaut ce filtre retourne une liste contenant toutes les informations d'une url

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

Pour obtenir juste une des informations il suffit de le mettre en argument du filtre.

{{ "http://user:password@www.acme.com:9000/dir/index.html?query=term#fragment" | urlsplit('hostname') }}
# => 'www.acme.com'

Expressions régulières

Certainement celui que vous utiliserez le plus: les expressions régulières. Vous avez à votre disposition trois filtres. regex_search regex_findall et regex_replace

Rechercher une chaîne

Ce filtre peut prendre deux arguments :

{{ 'foo\nBAR' | regex_search("^bar", multiline=True, ignorecase=True) }}

Rechercher toutes les occurrences d'une chaîne

Par exemple pour retrouver toutes les adresses IP d'une chaine :

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

Gestion des nom de fichiers et de répertoire

Décomposer un chemin au format windows

{{ path | win_basename }}

Pour séparer la lettre de lecteur Windows du reste d'un chemin de fichier :

{{ path | win_splitdrive }}

Pour obtenir uniquement la lettre de lecteur Windows:

{{ path | win_splitdrive | first }}

Pour obtenir le reste du chemin sans la lettre de lecteur:

{{ path | win_splitdrive | last }}

Pour obtenir le répertoire à partir d'un chemin Windows:

{{ path | win_dirname }}

Décomposer un chemin au format linux

Pour obtenir le répertoire à partir d'un chemin:

{{ path | dirname }}

Pour remplacer le caractère tilde ( ~ ) :

{{ path | expanduser }}

Pour développer un chemin contenant des variables d'environnement:

{{ path | expandvars }}

Date et Heure

Pour finir ce billet le filtre pour générer des dates et heures. On a à notre disposition deux filtres:

Convertir un chaine en objet date

{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).total_seconds()  }}
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2016-08-14 18:00:00" | to_datetime)).seconds  }}
{{ (("2016-08-14 20:00:12" | to_datetime) - ("2015-12-25" | to_datetime('%Y-%m-%d'))).days  }}

Vous remarquez que ce filtre possède des fonctions qui permettent d'extraire des informations ou de convertir l'objet date.

Formater une date

{{ '%Y-%m-%d' | strftime }}
{{ '%Y-%m-%d %H:%M:%S' | strftime(ansible_date_time.epoch) }}

Ce filtre reprend le formatage de type python

Conclusion

Il existe d'autres filtres dédiés au traitement d'objet de type network. Cela fera l'objet d'un autre billet. Si vous voulez plus de tutorials Ansible je vous renvoie sur le billet de l'introduction à ansible