Ansible - Utiliser MySQL comme inventaire dynamique

Parfois votre CMDB peut être stocké dans une base de données comme Mysql. C'est mon cas où un script python utilisant les résultats de la command nmap et des gather_facts d'Ansible stocke les machines dans la base mysql.

L'inventaire dynamique classique consiste à obtenir la liste des hôtes via un script externe et à la renvoyer à la commande ansible dans le format requis.

Ici on va utiliser deux astuces qui sont :

  • la commande add_host permettant d'ajouter une machine à un groupe dynamiquement ;
  • la possibilité de définir plusieurs sections avec différents groupes cible ;

Récupération des machines stockés dans votre base mysql

La première partie du playbook est un simple appel à la commande mysql via le module shell. Vous aurez juste à modifier les champs entre <> pour utiliser ce playbook. Cette requête vient récupérer les adresses IP qui sont ensuite stockées dans une variable nommée stuff

---
- hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: Retrieve stuff from mysql
      shell: mysql --user=<user> --password=<secret> <schema> --host=<ip> --port=<port> --batch --skip-column_names
 --execute="SELECT ipaddr FROM cmdb WHERE state like 'up'"
      register: stuff

Création du groupe

Toujours dans lé même section du playbook on va utiliser la commande add_host pour constituer le groupe qui sera ensuite utilisé dans la seconde section du playbook.

    - name: Add host
      add_host:
        hostname: "{{item}}"
        groups: running_hosts
      with_items: "{{ stuff.stdout_lines }}"

Utilisation du groupe dans la seconde section du playbook

Maintenant il suffit juste d'ajouter une nouvelle section à votre playbook utilisant cette fois le groupe running_hosts. Ici je vais créer un fichier de facts persos (via un template jinja) qui seront récupérés par la collecte des facts si elle est activée.

Le code complet :

---
- hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: Retrieve stuff from mysql
      shell: mysql --user=<user> --password=<secret> <schema> --host=<ip> --port=<port> --batch --skip-column_names
 --execute="SELECT ipaddr FROM cmdb WHERE state like 'up'"
      register: stuff
    - name: Add host
      add_host:
        hostname: "{{item}}"
        groups: running_hosts
      with_items: "{{ stuff.stdout_lines }}"
- hosts: running_hosts
  strategy: host_pinned
  gather_facts: no
  tasks:
    - name: create folder
      file:
        path: /etc/ansible/facts.d
        mode: '0644'
        state: directory
    - name: get install_date
      shell: stat /root/install.log | grep "Modif" | tail -1 | cut -d" " -f2,3| cut -d"." -f1
      register: install_date
    - name: Create file
      template:
        src: local_fact.j2
        dest: /etc/ansible/facts.d/defaults.fact

Le fichier jinja :

#jinja2: trim_blocks:False
[informations]
reboot_date={% if reboot_date.stdout_lines != [] %}{{reboot_date.stdout_lines[0]}}{% else %}{% endif %}
install_date={% if install_date.stdout_lines != [] %}{{install_date.stdout_lines[0]}}{% else %}{% endif %}

Voilà vous pouvez je suis sûr que vous trouverez des use-case utilisant cette technique.


Alimenter un blog comme celui-ci est aussi passionnant que chronophage. En passant votre prochaine commande (n'importe quel autre article) au travers du lien produit ci-contre, je touche une petite commission sans que cela ne vous coûte plus cher. Cela ne me permet pas de gagner ma vie, mais de couvrir les frais inhérents au fonctionnement du site. Merci donc à vous!