• 6 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 2/2/24

Créez votre propre module Ansible personnalisé avec Python

 

Dans la deuxième partie, vous avez créé et utilisé des playbooks et des rôles pour gérer le déploiement automatique de MediaWiki.

Dans ce chapitre, vous allez créer un module Ansible personnalisé. En effet, vous allez créer un module capable de compter le nombre de pages MediaWiki en interrogeant directement la base de données.

Pourquoi écrire un module ?

Il existe déjà beaucoup de modules et la collection s'enrichit régulièrement. Mais dans certain cas, il est nécessaire d’aller plus loin, comme dans votre cas : le module pour compter le nombre de pages dans un MediaWiki n’existe pas. Dans ce cas, il est préférable de faire un module spécifique pour répondre directement à ce besoin.

Dans votre cas, vous allez créer un module qui va exécuter une requête SQL. Cette requête comptera le nombre de pages dans la base MediaWiki

Pour créer le module, vous aurez besoin de :

  • écrire un script Python ;

  • créer un répertoire pour mettre le script ;

  • tester le module ;

  • documenter le module.

Comment faire un module ?

Ansible gère automatiquement toutes les étapes de fonctionnement d’un module.

En effet, quand un module est utilisé, Ansible a besoin de faire plusieurs actions, comme aller lire le fichier de configuration pour trouver l'emplacement des modules, ou établir une connexion avec les nodes, ou encore créer un fichier autoporteur et le déposer sur les nodes avant de l'exécuter.

Donc, pour créer un module, Il suffit simplement de mettre votre programme dans le répertoire library et d'écrire un programme Python en utilisant la classe AnsibleModule

Emplacement du module

Comme indiqué plus haut, vous allez créer un répertoire library au même niveau que les playbooks, c’est-à-dire dans votre environnement de travail.

Dans ce répertoire, vous allez créer votre programme Python, que vous allez appeler count_page.py.

Ansible ira regarder dans ce répertoire lorsque le module count_page sera appelé par le playbook.

Au préalable, connectez-vous sur le node manager avec l’utilisateur user-ansible et activez l’environnement virtuel :

$ source ansible/bin/activate

Puis créez le répertoire library :

$ mkdir library

Écrivez le programme Python

Vous allez écrire le programme qui sera exécuté par le module.

Vous allez structurer votre programme de la façon suivante :

  1. Créer un en-tête.

  2. Définir et gérer les arguments.

  3. Établir une connexion avec la base de données pour exécuter la requête SQL.

  4. Et transmettre les résultats à Ansible. 

Éditez le fichier count_page.py :

$  vi library/count_page.py

Créez l'en-tête

L’en-tête du programme indique l'interpréteur à utiliser pour exécuter le programme, et le type d’encodage du fichier. La majorité des programmes Python commencent de cette façon :

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

Définition des arguments du module

Vous allez utiliser deux arguments pour indiquer au module le nom de la base de données et la requête à utiliser :

  • db_name  : nom de la base de données ;

  • request  : requête SQL à lancer.

Pour intégrer ces arguments au programme, vous avez besoin de :

  • importer la classe  AnsibleModule  ;

  • définir la fonction  main()  ;

  • créer une instance de la classe  AnsibleModule  avec son constructeur ;

  • utiliser le paramètre  argument_spec  pour définir les arguments pris en charge par le module, ainsi que leurs types. 

from ansible.module_utils.basic import AnsibleModule  

def main(): 
    module = AnsibleModule( 
        argument_spec=dict( 
        db_name    = dict(required=True, type=’str’), 
        request    = dict(required=True, type=’str’), 
        ) 
    )

Récupération de la valeur des arguments

Vous allez maintenant récupérer la valeur des arguments à l’aide des fonctions params et gets de l’instance module, et les placer dans deux variables qui portent le même nom que les arguments.

db_name_local = module.params.get(’db_name’) 
request_local = module.params.get(’request’)

Connexion à la base

Pour la connexion à la base, vous avez besoin de :

  • importer la bibliothèque MySQLdb ;

  • définir un objet de connexion ;

  • définir un curseur sur l’objet ;

  • exécuter une requête sur le curseur ;

  • stocker le résultat de la requête dans une variable ;

  • fermer la connexion

import MySQLdb

db = MySQLdb.connect(db=db_name_local) 
cur = db.cursor() 
cur.execute(request_local) 
results = cur.fetchall() 
db.close()

Transmission du résultat à Ansible

La transmission du résultat se fait en utilisant la fonction module.exit_json avec les arguments changed et resultat qui indiquent respectivement l'état de l’action et le résultat de la requête.

Le programme se termine avec l’appel à la fonction main().

module.exit_json(changed=False, resultat=results)  

if __name__ == "__main__": 
    main()

Le code entier du module est donc :

L'image montre une capture d'écran pour le code entier du module pour la transmission du résultat à Ansible.

Test du module

Maintenant que tout est au point, vous allez pouvoir tester votre module.

Vous allez créer le playbook qui utilisera le module en question.

$ vi module.yml

À la différence des playbooks précédents qui utilisaient les rôles, celui-ci fait appel à une section tasks, qui contiendra un appel au module count_page 

L'image montre une capture d'écran du playbook qui testera le module créée précédemment.
Capture d'écran du test du module
  • - name: "Requete dans une base"   indique le nom du jeu d'instructions ;

  • hosts: bdd1  indique le nom du node sur lequel sera exécutée l’action ;

  • gather_facts: no indique de désactiver les facts ;

  • tasks:  indique que la section contient des tâches :

    • - name: "compte le nombre de pages dans le Wiki"  indique le nom de la tâche :

      • count_page:  indique le module à utiliser, 

        • db_name: "mediawiki"  indique le nom de la base de données,

        • request: "select count(*) from page;"  indique la requête à exécuter ,

      •  register: resultatindique de stocker le résultat de la requête dans la variable request ;

    • - debug: var=resultat  indique d’afficher le résultat de la requête contenue dans la variable result. 

Lancez maintenant le playbook module.yml avec la commande suivante : 

$ ansible-playbook -i inventaire.ini module.yml -K -b

Sont utilisées ici les options :

  • -i  pour l’inventaire à utiliser ;

  • -k  pour le password sudo ;

  • -b  pour passer en sudo.

(ansible) user-ansible@node-manager:~$ ansible-playbook -i inventaire.ini module.yml -K -b
BECOME password:

PLAY [Requete dans une base] *************************************************************************************

TASK [compte le nombre de pages dans le Wiki] ********************************************************************
ok: [bdd1]

TASK [debug] *****************************************************************************************************
ok: [bdd1] => {
  "resultat": {
  "ansible_facts": {
       "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "failed": false,
    "resultat": [
      [
        1
      ]
    ]
  }
}

PLAY RECAP *******************************************************************************************************
bdd1                   : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 

Voici le résultat de la requête : il y a 1 pages dans le wiki ! Il va falloir s’y mettre, car pour le moment c’est un peu light !

Gestion de l’aide

Pour agrémenter votre code, vous allez intégrer de la documentation. Ainsi, en utilisant la commande ansible-doc, vous pourrez donner des informations utiles pour l’utilisation de votre module.

Vous allez ajouter 3 déclarations dans votre programme :

  1. DOCUMENTATION qui contiendra le nom du module, la description et les options.

  2. EXAMPLES qui contiendra un exemple pour utiliser correctement votre module.

  3. RETURN qui contiendra la description du résultat retourné par votre module. 

L'image montre une capture d'écran pour l'intégration d'utilisation du module créée.
Capture d'écran pour l'intégration de la documentation

Pour vérifier ce que ça donne, vous allez utiliser la commande ansible-doc avec l’option -M pour indiquer le chemin du module, suivi du nom du module :

(ansible) user-ansible@node-manager:~$ ansible-doc -M library count_page

> COUNT_PAGE (/home/user-ansible/library/count_page.py)

 Module qui permet d'exécuter une requête SQL

OPTIONS (= is mandatory):

= db_name
 nom de la base de données


= request
 requête à exécuter

AUTHOR: Alexandre

EXAMPLES:

- name: "SQL"
 count_page:
 db_name: "BDD"
 request: "select * from user;"


RETURN VALUES:

resultat:
 retourne le résultat de la requête

Ainsi, vous pouvez retrouver de l’information sur le module sans aller voir dans le code.

Vous pouvez maintenant proposer votre module à la communauté et participer au développement d’Ansible. :D 

Et voici le fichier library/count_page.py dans son ensemble :

#!/usr/bin/python

from ansible.module_utils.basic import AnsibleModule  
import MySQLdb

def main():
  module = AnsibleModule(
	argument_spec=dict(
  	db_name	= dict(required=True, type='str'),
  	request	= dict(required=True, type='str'),
	)
  )
    
  db_name_local = module.params.get('db_name')
  request_local = module.params.get('request')
 
  db = MySQLdb.connect(db=db_name_local)
  cur = db.cursor()
  cur.execute(request_local)
  results = cur.fetchall()
  db.close()
 
  module.exit_json(changed=False, resultat=results)  
 
if __name__ == "__main__":
	main()


DOCUMENTATION='''
module: count_page
author: Alexandre
description: Module qui permet d'exécuter une requête SQL
 
options:
  db_name:
	description: nom de la base de données
	required: yes
  request:
	description: requête à exécuter
	required: yes
 
'''

EXAMPLES='''
- name: "SQL"
  count_page:
	db_name: "BDD"
	request: "select * from user;"
'''


RETURN = '''
resultat:
	description: retourne le résultat de la requête
'''

Résumé

Dans ce chapitre, vous avez créé votre propre module Ansible : 

  • vous avez écrit un programme Python en utilisant la classe  AnsibleModule ;

  • vous avez construit votre programme grâce à plusieurs sections qui vous ont permis de définir des arguments, de vous connecter à la base de données, de lancer une requête SQL et de transmettre le résultat à Ansible ;

  • vous avez ensuite placé votre programme dans le répertoire library,  afin qu’il soit pris en compte par Ansible ; 

  • vous avez ensuite testé votre module à l’aide d’un playbook ;

  • et pour finir, vous avez agrémenté votre programme avec de la documentation, ce qui permet de savoir comment utiliser votre module.

Un dernier mot

Vous êtes désormais prêt à automatiser toutes vos tâches d’administration. Grâce à Ansible, vous allez gagner du temps et vous pourrez vous concentrer sur des tâches à plus forte valeur ajoutée. Finies les actions chronophages et répétitives ; en écrivant ou en utilisant des playbooks ou des rôles, vous allez gagner en efficacité. Vous avez également créé votre propre module, vous pouvez maintenant voler de vos propres ailes et pourquoi pas, participer à la communauté Ansible.

J’ai été ravi de partager mon expérience avec vous,  et j'espère vous croiser prochainement parmi les utilisateurs ou les contributeurs actifs de Ansible. :)

Example of certificate of achievement
Example of certificate of achievement