Ansible - Développer et installer des collections
Publié le : 4 mars 2021 | Mis à jour le : 22 janvier 2023Table des matières
Introduction
Introduit avec la version 2.8 d’Ansible les collections permettent de répondre à la problématique de distribution des contenus Ansible. En effet, les collections vont permettre d’installer en une seule opération modules, rôles, plugins, et même les playbooks Ansible.
Rappel : depuis la version 3.0 ansible est distribué différemment. En effet, il est composé de plusieurs packages python dont ansible-base. Ansible-base embarque les programmes de base d’Ansible que sont ansible-playbook, ansible-galaxy, ansible-doc, etc. et quelques modules et de la documentation.
Le reste des modules et plugins ont été déplacés dans diverses “collections”
dont la plus importante est la community.general
.
Pour s’y retrouver dans les collections, il faut se rendre sur cette page.
Installation de collections Ansible
Le premier moyen pour installer une collection est d’utiliser la commande
ansible-galaxy
. En effet, depuis la version 2.8 d’Ansible cette commande
possède une option permettant de gérer les collections.
ansible-galaxy collection install community.general
On peut également utiliser un fichier tar.gz. Mais ce sera surtout pour gérer vos propres collections.
ansible-galaxy collection install my_namespace-my_collection-1.0.0.tar.gz
Bon c’est bien avec une ou deux collections, mais pour un nombre important il faut plutôt utiliser un fichier requirement.yml
---
roles:
# Install a role from Ansible Galaxy.
- name: geerlingguy.java
version: 1.9.6
collections:
# Install a collection from Ansible Galaxy.
- name: geerlingguy.php_roles
version: 0.9.3
source: https://galaxy.ansible.com
Développement de collections Ansible
Comme dit plus haut une collection est un simple format de distribution de contenu utilisé par Ansible Galaxy. Ici, c’est une archive compressée qui contient cette arborescence :
collection/
├── docs/
├── galaxy.yml
├── plugins/
│ ├── modules/
│ │ └── module1.py
│ ├── inventory/
│ └── .../
├── README.md
├── roles/
│ ├── role1/
│ ├── role2/
│ └── .../
├── playbooks/
│ ├── files/
│ ├── vars/
│ ├── templates/
│ └── tasks/
└── tests/
On y retrouve :
- Un fichier galaxy.yml contenant les informations nécessaires pour créer cette collection.
- Un répertoire où est stockée la documentation des rôles et des plugins.
- Des répertoires rôles, playbooks, plugins et tests. Dans le répertoire plugins, il faut regrouper les plugins par type.
Cette structure est créée avec la commande suivante
ansible-galaxy collection init step.test
Il faut juste créer le répertoire playbooks. Dans le répertoire plugins, on
retrouve un fichier README.md
qui contient la liste de tous les types de
plugins ou il faudra créer un répertoire.
Pour créer des rôles, il suffit de se mettre dans le répertoire source et de lancer la commande classique de création de rôles ansible.
cd steph/test/roles
ansible-galaxy role init premierrole
Dans les taches du rôle ajoutons un simple debug :
---
- name: Debug test.
debug: msg="Mon premier role"
Build de notre collection
Cela se fait assez simplement. Depuis le répertoire de votre collection tapez la commande suivante :
ansible-galaxy collection build
Created collection for stephane.test_collection at /home/vagrant/Projets/perso/stephane/test_collection/stephane-test_collection-1.0.0.tar.gz
Utilisons notre collection
Créer un autre projet :
mkdir ~/Projets/test
ansible-galaxy collection install /home/vagrant/Projets/perso/stephane/test_collection/stephane-test_collection-1.0.0.tar.gz -p ./collections
[WARNING]: The specified collections path '/home/vagrant/Projets/perso/test/collections' is not part of the configured Ansible collections paths
'/home/vagrant/.ansible/collections:/usr/share/ansible/collections'. The installed collection won't be picked up in an Ansible run.
Comme vous pouvez le lire nous devons indiquer à Ansible ou se trouve notre collection. Pour ça il existe 2 moyens :
- dans le fichier ansible.cfg dans la section [defaults] en ajoutant le
paramètre
collections_paths
- avec la variable d’environnement
ANSIBLE_COLLECTIONS_PATHS
ANSIBLE_COLLECTIONS_PATHS=
Créer un simple playbook utilisant votre collection
- hosts: localhost
gather_facts: true
tasks:
- import_role:
name: stephane.test_collection.premierrole
Vous remarquez qu’il vous faut indiquer le chemin du rôle dans la collection. Lançons-le :
ansible-playbook -c local playbook.yaml
PLAY [localhost] ***
TASK [Gathering Facts] ***
ok: [localhost]
TASK [stephane.test_collection.premierrole : debug] ***
ok: [localhost] => {
"msg": "OracleLinux"
}
PLAY RECAP ******
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Ajouter des tests à votre collection
Depuis la version 2.9 d’Ansible, Ansible est livré avec un utilitaire se nommant
ansible-test
. Cet utilitaire permet d’ajouter des tests à vos collections qui
peuvent être :
- des tests unitaires sur vos propres développements de modules et de plugins (ils doivent intégrer des tests au format unittest ou pytest)
- des tests d’intégration
- des tests syntaxique
sanity test
Ansible-test utilise docker pour créer l’environnement de test. On peut utiliser les images suivantes qui contiennent python3 :
- centos8
- fedora32
- opensuse15
- ubuntu1804
Comment lancer les tests syntaxique dans une collection Ansible
Ces premiers tests ne nécessitent aucune action de notre part. Lançons les tests en prenant une centos8.
ansible-test sanity --docker centos8
...
ERROR: Found 3 yamllint issue(s) which need to be resolved:
ERROR: galaxy.yml:62:1: empty-lines: too many blank lines (1 > 0)
ERROR: roles/premierrole/tasks/main.yml:4:1: empty-lines: too many blank lines (1 > 0)
ERROR: tests/integration/targets/premierrole/tasks/main.yml:3:1: empty-lines: too many blank lines (1 > 0)
ERROR: The 3 sanity test(s) listed below (out of 45) failed. See error output above for details.
future-import-boilerplate
metaclass-boilerplate
pep8
Reste plus qu’à corriger et à relancer.
Pour retrouver la liste des tests actifs (33) :
ansible-test sanity --list-tests
action-plugin-docs
ansible-doc
...
yamllint
Surpris de ne pas retrouver ansible-lint
dans cette liste.
Comment ajouter des tests unitaires à notre collection ansible
Prenons l’exemple du développement d’un plugin de filtre Ansible. Il faut écrire
le plugin de filtre dans le répertoire plugins/filter_plugins/
de la
collection.
└── tests
└── unit
└── plugins
└── filter
├── __pycache__
│ └── test_snaketocamel.cpython-38.pyc
└── test_snaketocamel.py
Reprenons l’exemple du filtre du billet dédié à ce sujet.
from ansible.errors import AnsibleError
import re
try:
import six
HAS_LIB = True
except ImportError:
HAS_LIB = False
def snake_to_camel(text, suffix=''):
if not HAS_LIB:
raise AnsibleError('You need to install "six" prior to running '
'snaketocamel filter')
import re
return suffix + ''.join(x.title() or '_' for x in text.split('_'))
class FilterModule(object):
def filters(self):
return {
'snaketocamel': snake_to_camel
}
Dans le répertoire de la collection ajouter un répertoire tests/unit/plugins/filter
et
déposez-y ce fichier test_snaketocamel.py
:
import unittest
from ansible_collections.steph.test.plugins.filter_plugins.snaketocamel import snake_to_camel
class TestMyFilter(unittest.TestCase):
def test_snaketocamel(self):
self.assertEqual(snake_to_camel("une_variable"), 'UneVariable')
Maintenant, il suffit de lancer ansible-test depuis le répertoire de la collection :
ansible-test unit --docker ubuntu1804
...
Unit test with Python 3.6
============================= test session starts ==============================
platform linux -- Python 3.6.9, pytest-6.2.3, py-1.10.0, pluggy-0.13.1
rootdir: /root/ansible_collections/steph/test/tests/unit/plugins/filter, configfile: ../../../../../../../ansible/test/lib/ansible_test/_data/pytest.ini
plugins: forked-1.3.0, mock-3.6.0, xdist-2.2.1
gw0 I / gw1 I / gw2 I / gw3 I
gw0 [1] / gw1 [1] / gw2 [1] / gw3 [1]
. [100%]
- generated xml file: /root/ansible_collections/steph/test/tests/output/junit/python3.6-units.xml -
============================== 1 passed in 0.79s ===============================
Comment ajouter des tests d’intégration à notre collection ansible
Les tests d’intégration sont écrits sous la forme de rôles Ansible.
Dans le répertoire tests, il faut créer la structure suivante
integration/targets/premierrole/tasks
dans le répertoire tests de la
collection.
└── tests
├── integration
│ └── targets
│ └── premierrole
│ └── tasks
│ └── main.yml
Ajoutons simplement l’import du rôle premierrole
:
- import_role:
name: stephane.test_collection.premierrole
Lançons le test d’intégration :
ansible-test integration --docker ubuntu1804
PLAY [testhost] ****************************************************************
TASK [Gathering Facts] *********************************************************
ok: [testhost]
TASK [steph.test.premierrole : Debug test.] ************************************
ok: [testhost] => {
"msg": "Mon premier role"
}
PLAY RECAP *********************************************************************
testhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
On peut donc désormais valider notre collection sans installer quoique ce soit,
mis à part docker, avec ansible-test
. On peut aussi lancer des tests sur un
environnement cloud.
Je suis sûr que ce produit va encore beaucoup évoluer.
Plus loin avec les collections Ansible
Depuis l’écriture de ce billet beaucoup de lignes de codes sont passées et le développement de ces collections a bien évolué. Par exemple, nous pouvons utiliser molécule pour les tests unitaires sur des instances docker, vagrant ou ec2. /post/ansible-molecule-aws-ec2/
Si vous voulez plus de tutorials Ansible je vous renvoie sur le billet de l'introduction à ansible