Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Du 22 au 24 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. Ansible
  3. Écriture de modules
Extrait - Ansible Gérez la configuration de vos serveurs et le déploiement de vos applications (3e édition)
Extraits du livre
Ansible Gérez la configuration de vos serveurs et le déploiement de vos applications (3e édition)
2 avis
Revenir à la page d'achat du livre

Écriture de modules

Objectifs du chapitre et prérequis

Le chapitre précédent a été consacré à l’utilisation des playbooks et des rôles Ansible. Dans ce chapitre, vous allez voir qu’il est parfois nécessaire d’écrire des modules pour gérer certains types d’objets qu’il serait difficile de gérer avec un playbook.

1. Contexte et prérequis

L’écriture de modules Ansible réclame quelques compétences dans le langage Python. Néanmoins, les exemples proposés devraient être à la portée des personnes ayant des notions de programmation sur n’importe quel langage.

Au niveau du module en lui-même, vous verrez les bibliothèques à disposition de l’utilisateur ainsi que les différents appels à réaliser ou la gestion des paramètres. Vous aborderez également les mécanismes d’aide.

Vous verrez également quelques problèmes que le lecteur pourrait rencontrer comme la compatibilité entre Python 2 et 3 ou comment renvoyer à l’utilisateur de manière efficace des informations sur les modifications qui ont été réalisées sur le système.

2. Fichiers téléchargeables

Vous pouvez récupérer les exemples des répertoires inventaires et variables sur le repository GitHub suivant : https://github.com/EditionsENI/ansible

Vous pouvez également récupérer ces fichiers dans l’archive chapitre-12.tar.gz depuis la page Informations générales.

Mécanisme d’appel des modules Python

1. Principe de fonctionnement

On sait déjà que pour fonctionner Ansible a besoin d’un moyen de communication (SSH ou lancement local par exemple) et d’un interpréteur Python (sauf pour certains modules comme raw ou fetch).

Ansible se charge de gérer l’escalade de privilèges (sudo, su, etc.) pour enfin exécuter un programme.

Ce mini programme suivra les instructions se trouvant dans un module et les renverra à Ansible sous la forme d’un dictionnaire en plus de son code de retour (si exit 0, tout va bien, sinon, problème lors du lancement du programme).

Ainsi, chaque opération se traduit par la création d’un contexte d’exécution dans un répertoire temporaire sur la machine administrée. Ce chapitre va présenter les différentes étapes suivies par Ansible. Vous découvrirez notamment comment est construit ce mini programme autoporteur.

2. Activation des traces d’exécution

Une bonne façon de se rendre compte de toutes ces opérations préliminaires est de lancer Ansible avec l’option -vvv. Pour ce qui va suivre, vous prendrez un exemple simple de vérification de la présence de l’utilisateur root. En mode ad hoc, cette opération s’écrit de la manière suivante :

$ ansible -m user -a "user=root state=present" localhost -vvv 

Ces indications ne sont valables que dans le cas où Mitogen n’est pas actif. Si ce n’est pas le cas, désactivez-le.

L’option -vvv provoque sur Ansible la sortie suivante (extrait) :

Using /home/yannig/.ansible.cfg as config...

Pourquoi écrire un module ?

1. Contexte

Dans les chapitres précédents, vous avez fait appel à des playbooks et des rôles pour gérer vos installations. Dans certains cas, ce type de mécanisme n’est pas toujours suffisant et peut devenir problématique lorsque les objets à gérer sont complexes.

Imaginez que vous souhaitiez consulter le contenu d’une base de données. Avec un playbook/rôle, cette gestion se déroulerait de la manière suivante :

  • création d’un fichier d’ordre SQL ;

  • lancement de l’action avec un utilitaire SQL.

Cette approche pose plusieurs problèmes :

  • Le fichier de script reste sur la machine.

  • On peut le supprimer, mais dans ce cas, on ajoute une opération.

  • On perd de l’information puisqu’on ne récupère que la sortie de la requête. Vous perdez toutes les métadonnées (nom des champs, etc.).

Pour mieux comprendre, prenons le temps de prendre un exemple en comptant le nombre de tables dans le schéma mediawiki.

2. Consultation du schéma

La commande à lancer pour connaître le nombre de tables dans un schéma MySQL est la suivante :

SELECT 
  COUNT(*) 
FROM 
  information_schema.tables 
WHERE 
  table_schema = 'mediawiki'; 

 Avant de pouvoir l’exécuter, vous devez déposer ce script sous le nom de /tmp/test.sql.

 Pour vous connecter à une base de données MySQL/MariaDB, vous pouvez faire appel à la commande mysql. Pour éviter les problèmes de droits d’accès, vous lancerez cette...

Création d’un module

Vous avez vu comment récupérer cette information via un playbook et les appels par un shell. Vous allez maintenant réaliser la même chose avec un module. Vous verrez les avantages à en retirer.

1. Emplacement du programme

Le module que vous allez créer va s’appeler mysql_request. Son rôle sera de prendre en argument un nom de schéma de base de données MySQL et de lancer une requête SQL arbitraire.

 Vous sauvegarderez le programme sous le nom de mysql_request.py (le « .py » n’est pas obligatoire, mais reste recommandé pour des raisons de lisibilité).

 Vous devrez ensuite le mettre à disposition d’Ansible. Pour cela, vous avez plusieurs solutions :

  • Créer un répertoire library au même niveau que vos playbooks faisant appel à ce module.

  • Déposer le fichier dans un répertoire pris en compte par Ansible.

Les répertoires pris en compte par Ansible peuvent être définis par :

  • le champ library du fichier de configuration d’Ansible ;

  • la variable d’environnement ANSIBLE_LIBRARY.

Comme vous pouvez le constater, vous avez plusieurs solutions à votre disposition. Dans la plupart des cas, privilégiez l’utilisation du répertoire library qui vous évitera de devoir faire des modifications sur votre environnement de travail.

2. En-tête du programme

Au niveau du module en lui-même, vous commencerez par l’en-tête Python suivant :

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

3. Spécification des arguments du module

Avant de commencer à travailler...

Réentrance sur la création d’un schéma de base

1. Contexte

Vous avez vu un premier module Ansible qui vous a permis de vous familiariser avec cette notion. En revanche, vous avez un peu laissé de côté certains aspects et notamment la gestion de la réentrance.

Autre point : le module que vous avez créé est « dangereux » dans le sens où il va lancer les commandes sans les vérifier. Ne pas oublier non plus qu’il n’est compatible qu’avec un seul type de base de données : MySQL. Si vous deviez gérer une base Postgres, il vous faudrait en créer un nouveau.

Enfin, il n’est pas du tout en mesure de vous aider face à un problème typique que vous pourriez rencontrer avec une base de données : la gestion de la mise à jour du schéma.

La gestion d’un schéma de base de données est un vrai métier. Les exemples qui vont suivre sont là pour illustrer ce que peut être la réentrance appliquée à un petit schéma de base de données. Pour des schémas plus complexes, d’autres outils de migration existent comme par exemple Alembic, Liquibase ou encore Flyway.

Vous allez donc voir comment gérer cette réentrance. Afin de simplifier au maximum l’écriture de ce module, vous vous appuierez sur une petite bibliothèque pour tout ce qui va être gestion du contenu de la base : dataset.

C’est une petite bibliothèque Python qui se propose de gérer de manière totalement transparente la récupération d’informations contenues dans...

Gestion de l’option diff d’Ansible

1. Contexte

Pour vous assurer que les opérations ont été réalisées par Ansible, vous avez dû passer par une commande externe.

Vous allez maintenant voir comment gérer l’option --diff et faire en sorte qu’Ansible vous renvoie des indications sur les opérations réalisées. Cette option est à spécifier à Ansible en ligne de commande lors de son lancement.

Avec l’aide de cette option, et si vous retournez certains éléments à Ansible, ce dernier sera en mesure de vous renvoyer les modifications réalisées durant le lancement d’un module.

2. Principe de fonctionnement du diff

Vous vous en doutez, si vous ajoutez l’option --diff en l’état à Ansible, vous ne verrez aucun changement. Pour pouvoir gérer cette option, il faut ajouter de nouvelles variables dans l’appel module.exit_json.

Dans le cas de l’option --diff, il s’agit de renvoyer la variable diff avec les champs before et after. Le moteur Ansible s’occupera ensuite de faire la comparaison entre les deux champs avant de les renvoyer à l’utilisateur.

Voilà pour le mécanisme. Il vous reste maintenant à stocker dans ces deux variables l’état du système avant et après modification. Dans le cas présent, ces deux variables contiendront chacune deux tableaux :

  • Un tableau tables avec la liste des tables.

  • Un tableau columns avec la liste des colonnes.

Comme vous ne savez pas à quel tableau est rattachée une colonne avec son nom seul, vous les renverrez à Ansible sous la forme d’une...

Gestion de l’option test (check mode)

1. Activation du check mode

Afin de terminer la mise au point de ce module, vous allez ajouter la gestion d’un dernier mécanisme : la gestion de l’option test (ou check mode). Ce mode s’active à l’aide de l’option --check (ou -C pour la version courte).

Par défaut, si vous ne spécifiez rien du tout, Ansible n’exécutera pas le module. Ainsi, si vous reprenez l’appel du playbook de tout à l’heure et que vous souhaitez le lancer en mode test, vous devriez avoir la commande suivante :

$ ansible-playbook db_schema.yml --check 

Ci-dessous le résultat de la commande :

PLAY [Create schema] ******************************************* 
 
TASK [file] **************************************************** 
ok: [localhost]  
 
TASK [Create schema] ******************************************* 
skipping: [localhost] 
 
TASK [Update schema] ******************************************* 
skipping: [localhost] 
 
TASK [No modification] ***************************************** 
skipping: [localhost] 
 
PLAY RECAP ***************************************************** 
localhost       : ok=1    changed=0    unreachable=0    failed=0 

Comme vous pouvez le constater, toutes les opérations avec le module db_schema sont ignorées.

2. Prise en charge du mode check

L’activation du mode check passe tout d’abord par une modification des options à passer au constructeur de la classe AnsibleModule. Il faut ajouter l’option supports_check_mode avec la valeur...