URL: https://linuxfr.org/news/presentation-de-monkeyble-framework-de-test-bout-en-bout-pour-ansible Title: Présentation de Monkeyble: Framework de test bout en bout pour Ansible Authors: sispheor palm123, devnewton et Xavier Teyssier Date: 2022-11-27T20:02:33+01:00 License: CC By-SA Tags: ansible et testing Score: 3 # Présentation de Monkeyble: framework de test bout en bout pour Ansible ![monkeyble_logo](https://github.com/HewlettPackard/monkeyble/raw/master/docs/images/monkeyble_logo.png) Monkeyble est un petit framework qui permet de tester de bout en bout vos playbooks [Ansible](https://fr.wikipedia.org/wiki/Ansible_(logiciel)). Il permet, au niveau des tâches des Playbooks, de: - 🐵 Vérifier qu'un module a été appelé avec les bons arguments ; - 🙊 Vérifier le résultat du retour d'un module ; - 🙈 Vérifier l'état d'exécution d'une tâche (changed, skipped, failed) ; - 🙉 Simuler (Mock) un module afin de retourner un résultat sans faire appel au vrai module. Monkeyble est tout particulièrement conçu pour être placé dans une CI/CD afin de détecter les éventuels régressions lors des modifications sur une base de code Ansible 🚀. ## Context La stratégie de test décrite dans la [documentation officielle de Ansible](https://docs.ansible.com/ansible/latest/reference_appendices/test_strategies.html#testing-lifecycle) consiste a exécuter un playbook sur un environnement (un inventaire) de développement qui simule la production et de valider le fonctionnement de celui-ci pour l'exécuter ensuite sur l'environement de production. Cette stratégie fonctionne dans le cadre d'un playbook utilisé pour un déploiement d'un service à un instant T. Les tests sont effectués manuellement en quelque sorte. Une fois le service déployé, en cas de modification sur le code, une exécution devra à nouveau être réalisée sur l'environement de développement avant celui de production et cetera... Cependant, si vos playbooks sont utilisés en tant que "services" en étant exposés par exemple dans un AWX/Tower ou derrière un catalogue de services comme [Squest](https://github.com/HewlettPackard/squest), en cas de modification sur le code il est préférable de vérifier que le service fonctionne toujours. Un test manuel n'est bien évidemment plus adapté. On préféra donner ce travail à une CI/CD. Ansible met à disposition de façon native quelques "garde-fous" sous forme de modules à placer dans vos tâches, rôles ou playbook afin d'effectuer des étapes de validation de données tel que "[fail](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/fail_module.html)", "[assert](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/assert_module.html)" ou encore le "[check mode](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_checkmode.html)". Cela n'est pas du test à proprement parler mais il permet d'apporter une forme de vérification avant l'exécution. Des projets annexes se sont également ajoutés pour compléter l'offre. Le plus connu étant Molecule, ce dernier se base sur la librairie Python "[testinfra](https://testinfra.readthedocs.io/en/latest/)" ou sur Ansible lui même afin de, non pas réellement de "tester" tâche par tâche, mais de "[vérifier](https://molecule.readthedocs.io/en/latest/configuration.html#verifier)" le résultat suite à l'exécution du rôle ou playbook. C'est l'une des choses qui peut déranger avec ce framework quand on a l'habitude de coder des tests avec des bibliothèques de tests natives (comme [unittest](https://docs.python.org/3/library/unittest.html) en Python par exemple) qui permettent de tester le code lui-même. Par ailleurs, comme précisé dans la [documentation](https://docs.ansible.com/ansible/latest/reference_appendices/test_strategies.html#the-right-level-of-testing), les ressources Ansible sont des "modèles d'états souhaités". Il n'est donc pas nécessaire de tester qu'un service a bien été démarré, qu'un paquet a bien été installé, etc. C'est Ansible qui le garantit pour vous. En effet les modules utilisés dans nos tâches ont leur propres tests unitaires qui assurent que ces choses sont déclarativement vraies. Plus encore, les modules derrière *testinfra* sont d'un nombre limité et ne peuvent couvrir à eux seuls toutes les possibilités d'exécutions d'un script Ansible. Et puis finalement un Playbook c'est quoi ? C'est bien souvent une suite de manipulations de données avant d'exécuter un module particulier. Nous récupérons de la donnée depuis une API d'un coté, puis de l'autre le résultat de l'exécution d'un module. Pour transformer cette donnée à l'aide de "[filtre](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html)" afin de merger des dictionnaires, de créer des listes, extraire des variables, nous concaténons le tout avec les informations fournies par l'opérateur au moment de l'exécution, etc... pour finalement faire un appel à un autre module dans une nouvelle tâche. Comme pour un test unitaire, suivant une liste de variables connues en entrée nous voulons être certains que cette derrière tâche : - est bien exécutée (le script peut avoir échoué en amont) ; - a bien été appelée avec la bonne instanciation d'arguments (notre donnée transformée) ; - a bien retourné le résultat attendu ; - s'est bien terminée dans l'état souhaité ("changed", skipped,"failed"). Monkeyble permet ce type de tests avec une approche que l'on retrouve communément dans les langages de programmation. ## Petit tour des fonctionnalités ### Tester les entrées Vous pouvez déclarer une vérification des valeurs instanciées passées en argument des modules ```yaml - task: "my_task_name" test_input: - assert_equal: arg_name: module_argument expected: "my_value" ``` Monkeyble supporte des méthodes de tests comme celle disponibles dans la librairie [unittest](https://docs.python.org/3/library/unittest.html) de Python: assert_equal, assert_not_equal, assert_in, assert_not_in, assert_true, assert_false, assert_is_none, assert_is_not_none, assert_list_equal, assert_dict_equal. ### Tester le résultat des exécutions de module Les modules Ansible, pour la majeure partie, retournent un dictionnaire qui peut être conservé à l'aide d'un "register" afin d'etre utilisé par les tâches suivantes. Monkeyble permet de tester les valeurs retournées avec les mêmes méthodes que pour le test des entrées. ```yaml - task: "my_task_name" test_output: - assert_dict_equal: dict_key: "result.key.name" expected: key1: "my_value" key2: "my_other_value" ``` ### Tester les états des tâches Une tâche Ansible a plusieurs états possibles suite à son exécution. Monkeyble peut vérifier qu'une tâche s'est bien terminée dans un état particulier. ```yaml - task: "my_task_name" should_be_skipped: false should_be_changed: true should_failed: false ``` ### Simuler un module (Monkey patching) Le "Monkey patching", est une technique permettant de modifier dynamiquement une méthode afin de renvoyer une ou des valeurs préalablement spécifiées dans le test. Monkeyble permet de "mocker" une tâche et retourner un résultat défini. Dans un scénario où vous travaillez avec des API de cloud, dans un contexte de tests, vous ne souhaitez pas forcément créer réellement une instance d'un objet à chaque exécution de votre CI/CD, cependant vous souhaitez que la tâche retourne ce que le vrai module aurait retourné afin d'exécuter le playbook dans son intégralité et que les tâches suivantes puissent se servir de cette sortie. ```yaml - task: "my_task_name" mock: config: monkeyble_module: consider_changed: true result_dict: my_key: "mock value" ``` ## Conclusion Monkeyble est très simple à utiliser, son fonctionnement est entièrement basé sur de la configuration Yaml et reste donc dans le même état d'esprit que le projet Ansible. Vous pouvez créer autant de scenarios que nécessaire afin de : - garantir que vos playbooks ou rôles fonctionnent correctement ; - protéger des régressions suite à une mise à jour de parties partagées ; - tester unitairement des tâches complexes qui manipulent de la donnée ; - passer dans chacune des conditions et blocs de code ; - valider que vos playbooks s'arrêtent bien (fail) ou ne s'exécutent pas (skip) quand il le faut ; - que les tâches critiques s'exécutent avec le bon jeu d'arguments. ``` monkeyble test Playbook | Scenario | Test passed -----------+-----------------+------------- play1.yml | validate_test_1 | ✅ play1.yml | validate_test_2 | ✅ play2.yml | validate_this | ✅ play2.yml | validate_that | ✅ 🐵 Monkeyble test result - Tests passed: 4 of 4 tests ``` Happy testing à vous ! ✅ ---- [Code](https://github.com/HewlettPackard/monkeyble) [Doc](https://hewlettpackard.github.io/monkeyble/) ----