Ecrire des plugins de filtres Ansible
Parfois, manipuler des données directement dans les playbooks Ansible peut être fastidieux. C’est là que les filtres Ansible interviennent.
Les plugins de filtres vont vous permettre de gérer vos données directement avec du code Python. Une fois que vous saurez comment le faire, vous ne pourrez plus vous en passer.
Passons au code pour transformer une string SnakeCaze à une CamelCaze
Nous voulons transformer une string formatée en snake_case à une autre en CamelCase. Écrivons une simple boucle qui va itérer sur chaque élément d’un split avec le caractère ’_’, les passer en majuscule et concaténer le tout.
def snake_to_camel(text): words = text.split('_') return words[0].lower() + ''.join(word.title() for word in words[1:])
Écriture du plugin de filtre Ansible
Il suffit d’ajouter à la fin de votre programme python la définition de la classe FilterModule.
class FilterModule(object):
def filters(self): return { 'snaketocamel': snake_to_camel }
Ensuite enregistrer vos programmes dans le répertoire filter_plugins
. Si vous
voulez utiliser un autre répertoire, il faudra l’indiquer dans votre fichier
ansible.cfg
[default]filter_plugins = /path/to/filter/plugins
Utilisation de votre filtre dans un playbook
Rien de plus simple. Écrivez ceci dans un fichier que vous nommerez test.yml
---- hosts: localhost gather_facts: false vars: text1: "une_variable" text2: "une_autre_variable" tasks: - name: Snake To camel ansible.builtin.debug: msg: "{{ item | snaketocamel }}" with_items: - "{{text1}}" - "{{text2}}"
Vous pouvez le lancer avec la commande :
ansible-playbook -i localhost -c local test.yml
Ce qui vous donnera :
ok: [localhost] => (item=une_variable) => { "msg": "UneVariable"}ok: [localhost] => (item=une_autre_variable) => { "msg": "UneAutreVariable"}
Passer plusieurs variables à un filtre personnalisé
Nous allons ajouter un suffixe à notre filtre. La fonction devient :
def snake_to_camel(text,suffix=''): import re return suffix + ''.join(x.title() or '_' for x in text.split('_'))
Et le playbook :
---- hosts: localhost gather_facts: false vars: text1: "une_variable" text2: "une_autre_variable" tasks: - name: Snake to Camel ansible.builtin.debug: msg: "{{ item | snaketocamel('string') }}" with_items: - "{{text1}}" - "{{text2}}"
Ce qui donne comme résultat :
ok: [localhost] => (item=une_variable) => { "msg": "stringUneVariable"}ok: [localhost] => (item=une_autre_variable) => { "msg": "stringUneAutreVariable"}
Lever une exception Ansible dans votre filtre
En général, les erreurs rencontrées lors de l’exécution doivent être renvoyées en levant une AnsibleError() ou une classe similaire contenant un message décrivant l’erreur. Lorsque vous encapsulez d’autres exceptions dans des messages d’erreur, vous devez toujours utiliser la fonction Ansible to_text pour garantir la compatibilité des chaînes entre les différentes versions de Python.
Un exemple : Tester qu’une librairie est bien installé : ici la lib six.
# -*- coding: utf-8 -*-
from ansible.errors import AnsibleErrorimport re
try: import six HAS_LIB = Trueexcept ImportError: HAS_LIB = False
def snake_to_camel(text, suffix=''): if not HAS_LIB: raise AnsibleError('You need to install "six" prior to running ' 'snaketocamel filter') import re return suffix + ''.join(x.title() or '_' for x in text.split('_'))
class FilterModule(object):
def filters(self): return { 'snaketocamel': snake_to_camel }
On désinstalle six
et on lance le playbook :
pip3 uninstall six -yansible-playbook -i localhost test.yml
Ce qui donne :
TASK [Snake to Camel] ***fatal: [localhost]: FAILED! => {"msg": "You need to install \"six\" prior to running snaketocamel filter"}
Conclusion
Voila je vous laisse pour que vous puissiez développer vos propres filtres et l’intégrer dans vos playbooks.
Pour tester vos développements sur différentes versions d’Ansible et Python, je vous propose de lire ce billet.