Ansible : Utiliser ses API avec Python
Ansible : Utiliser ses API avec Python
Depuis quelques temps j’ai enfin trouvé des idées de petits outils à développer avec Python pour pouvoir apprendre à manipuler ce langage.
Utilisant beaucoup Ansible de manière professionnelle (je vous invite à lire la serie de billets écrite à ce sujet si ce n’est déjà fait), et celui-ci étant développé en Python, je m’appuie dans notre contexte sur nos inventaires pour fournir diverses informations à d’autres systèmes ou encore à des utilisateurs.
Attention : Les API dont je vais parler sont utilisées par Ansible pour ses propres besoins et sont susceptibles de casser en cas de modification. Il faut donc rester parcimonieux sur leur utilisation et ne pas trop en dépendre !
L’un des premiers outils que j’ai bricolé avec Python est un générateur de fiche environnement pour une application, ceci dans le but de mettre fin aux 50 fichiers Excel éparpillés à droite et à gauche et jamais maintenus. Si j’ai pu facilement lire les fichiers group_vars
de l’inventaire Ansible avec le module pyyaml
de Python, le fichier hosts
au format ini
était un peu plus corsé et mal reconnu car il n’y avait pas forcément de clé / valeur pour un serveur.
Exemple :
[webservers]
host1
host2
[databases]
hostdb1
hostdb2
Le module ConfigParser
de Python avait du mal sur le coup.
Python 3.8.6 (default, Sep 25 2020, 00:00:00)
[GCC 10.2.1 20200723 (Red Hat 10.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.read('hosts')
['hosts']
>>> print(config['webservers'])
<Section: webservers>
>>>
… et à partir de là je ne voyais plus comment lui faire afficher les hosts du groupe webservers
.
Après quelques recherches j’ai donc vu cette possibilité d’importer directement les API d’Ansible.
Python 3.8.6 (default, Sep 25 2020, 00:00:00)
[GCC 10.2.1 20200723 (Red Hat 10.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from ansible.inventory.manager import InventoryManager
>>> from ansible.parsing.dataloader import DataLoader
>>> loader = DataLoader() # cette méthode se charge d'aller trouver et lire les fichiers .yaml, .ini, .json
>>> inventory = InventoryManager(loader=loader, sources='hosts') # on charge le fichier hosts de l'inventaire
>>> print(inventory.groups) # liste les groupes de l'inventaire
{'all': all, 'ungrouped': ungrouped, 'webservers': webservers, 'databases': databases}
>>> print(inventory.get_hosts('webservers')) # affiche les hosts d'un groupe
[host1, host2]
Et voilà, c’est aussi simple. A noter que les variables retournées font partie de la Classe d’Ansible, donc elles ne sont pas forcément exploitables directement dans du code externe. J’ai du passer par des intermédiaires pour retransformer les valeurs en str
afin de pouvoir les exploiter. Par exemple j’avais besoin de résoudre l’entrée DNS du nom du serveur pour obtenir l’IP afin de l’afficher dans le référentiel, la valeur retournée par la commande get_hosts
était nativement inexploitable pour socket.gethostbyname
.
D’autres méthodes sont aussi disponibles pour générer des inventaires dynamiques afin de lancer dans la foulée des Playbook Ansible via Python. Dans le ca de l’API Manager, le nécessaire est disponible dans les sources d’Ansible pour comprendre ce qu’elle permet de faire.