https://lafor.ge/feed.xml

Partager des faits entre les séquences d'un scénario molécule

2023-11-09

Bonjour 😀

Je continue à faire n'importe quoi avec ansible et surtout son framework de tests d'intégrations molécule.

Aujourd'hui j'ai un besoin que je vais vous exposer, pas en détail, un vrai article sur le sujet arrivera.

Non juste une recette de cuisine pour mon besoin spécifique.

Je suis possible pas dans le vrai ou pas élégant, mais ce que j'ai trouvé me dépanne bien. ^^

Donc vite fait, molécule qu'est ce que c'est ?

Molécule est un ordonnanceur de playbook ansible qui permet en regroupant sous la forme de séquence de venir gérer le cycle de vie et de test d'un rôle.

Ce cycle de vie se découpe en un certain nombre de séquences:

  • create : Créer la ou les bécanes
  • prepare : Prépare la ou les bécanes avant test
  • converge : Applique le rôle
  • verify : Vérifie que le rôle marche ou pas
  • cleanup : Nettoie la preparation
  • destroy : Détruit la ou les bécanes

Il y a d'autres séquences mais elles ne m'intéressent pas pour cet article.

Alors qu'est ce que je veux faire ?

Vous vous souvenez du rôle/tâche pour commander des PG et des redis depuis l'API Clever, ben j'ai réussi à le faire et à récupérer tout ce dont j'ai besoin.

Seulement celui-ci n'est pas fait pour-être utiliser dans un autre rôle, mais pour provisionner des DB dans le cadre de tests d'intégrations. il a un défaut, il n'est pas vraiment d'idempotent, il demande une ressource et reçoit un UUID de db, on pourrait l'améliorer, mais pour mon besoin c'est pour le moment inutile. Donc relancer plusieurs fois la tâche commandera plusieurs DB, ce qui fait perdre du temps et mange de la ressource pour rien.

Heureusement Molécule est malin : si on fait molecule converge, son état interne lui permet de déterminer que l'étape create et prepare ont déjà été réalisée, et s'arrêtera à l'étape converge ou verify ce qui est parfait dans notre cas !

On peut ainsi commander la DB dans la phase prepare et la buter au destroy.

La problématique est d'être capable de partager les faits entre phases. (c'est dingue c'est le titre de l'article ^^')

Et dernière subtilité, le rôle de commande et de destruction de la DB sera réalisé en localhost.

Si vous définissez un scénario ainsi:

#molecule.yml
provisionner:
    playbooks:
        prepare: prepare.yml
        converge: converge.yml
        cleanup: cleanup.yml
# prepare.yml
- name: Prepare - Clever calls
  hosts: localhost
  gather_facts: false
  tasks:
    - name : Order a Postgres Database
      noa.clevercloud.addon_register:
        provider: postgres
        organisation: orga_xxxx
        details: 
            plan: xxs_sml
            version: 15
      register: result_pg
# cleanup.yml
- name: Cleanup - Clever calls
  hosts: localhost
  gather_facts: false
  taks:
    - name: Delete addon
    noa.clevercloud.addon_remove:
        addon: "{ result_pg.addon_id }"

Le result_pg déclaré dans prepare.yml n'existera pas pour cleanup.yml, en effet chaque séquence est un ansible-playbook différent avec son propre contexte.

Le moyen que j'ai trouvé est de réaliser une persistance sur disque des faits que je veux transmettre dans mon pipeline.

#molecule.yml
provisionner:
    config_options:
        defaults:
            gathering: smart
            fact_caching: jsonfile
            fact_caching_connection: /tmp/facts_cache
            fact_caching_timeout: 7200
    playbooks:
        prepare: prepare.yml
        converge: converge.yml
        cleanup: cleanup.yml

Et modifier la manière dont je fais le register

# prepare.yml
- name: Prepare - Clever calls
  hosts: localhost
  gather_facts: false
  tasks:
    - name : Order a Postgres Database
      noa.clevercloud.addon_register:
        provider: postgres
        organisation: orga_xxxx
        details: 
            plan: xxs_sml
            version: 15
      register: result_pg

    - name: Persist fact
      ansible.buitin.set_fact:
        cacheable: yes
        addon_pg: result_pg

Je peux alors utiliser ce fait dans mon cleanup.yml

# cleanup.yml
- name: Cleanup - Clever calls
  hosts: localhost
  gather_facts: false
  taks:
    - name: Delete addon
      noa.clevercloud.addon_remove:
        addon: "{ addon_pg.addon_id }"

Bon ça c'était de localhost à localhost, c'est entre guillements "facile", maintenant si je veux utiliser un fait défini dans prépare dans mon converge.yml qui lui s'applique à tout host.

Il faut bien avoir en tête que ansible applique le playbook par hosts et donc que les faits de localhost n'existe pas pour les autres hosts.

Ce qui signifie que:;

# converge.yml
- name: Converge 
  hosts: all
  gather_facts: false
  taks:
    - name: Delete addon
      ansible.builtin.debug:
        var: addon_pg

Ne marche pas.

Heureusement, il existe, une dernière arnaque.

# converge.yml
- name: Converge 
  hosts: all
  gather_facts: false
  taks:
    - name: Delete addon
      ansible.builtin.debug:
        var: hostvars['localhost']['addon_pg']

Et ça par contre, ça marche très bien ^^

Bref, un article court de hack répréhensible par Loi. 😁

avatar

Auteur: Akanoa

Je découvre, j'apprends, je comprends et j'explique ce que j'ai compris dans ce blog.

Ce travail est sous licence CC BY-NC-SA 4.0.