Aller au contenu

Tester ses rôles Ansible avec Serverspec

logo

Pour poursuivre notre formation Ansible, au menu du jour les tests des rôles.

Introduction

Ansible est un outil Devops largement utilisé et suivi par une très grande communauté. Pour valider mes rôles, j’utilisais jusqu’à peu molecule, mais dans une démarche de veille techno, j’ai découvert Kitchen-CI et ça été une belle découverte.

En effet molecule est un produit qui évolue sans cesse, imposant des ruptures importantes à chaque nouvelle version. Et là Kitchen-CI vient vraiment simplifier la partie test des rôles Ansible. J’aurais pu aussi utiliser ansible-test, mais ce sera pour une prochaine fois quand je créerai des collections ansible.

Kitchen-CI

Kitchen-CI est un outil Ruby développé par l’équipe en charge du produit de configuration Chef.

Kitchen-CI, permet de tester le résultat de l’exécution de divers outils de provisionning dont Terraform et Ansible. Vous voyez tout de suite l’intérêt : un outil commun pour réaliser une bonne partie de vos tests.

En effet Kitchen-CI est modulaire via ses drivers et modules qui lui permettent de fonctionner avec une grande partie des plateformes Onprem et Cloud : Docker, Vagrant, Terraform, AWS, Azure.

Automatiser les tests d’un rôle Ansible

Je vais, dans ce premier billet vous expliquer comment mettre en place des tests sur un rôle Ansible et ce, de manière simple avec Docker.

Installation des prérequis

Personnellement je l’installe dans ma VM de test provisionné avec Multipass.

Commençons par installer ruby, python3 docker :

Terminal window
sudo apt install ruby-full ruby-all-dev docker.io python3

Donnons les droits de lancer des commandes docker à votre utilisateur

Terminal window
sudo usermod -a -g docker $USER
sudo su - $USER

La seconde ligne permet de récupérer les droits du groupe sans à se déconnecter :)

Et ansible bien sur :

Terminal window
sudo pip3 install ansible ansible-lint

Maintenant on installe tous les produits Kitchen nécessaire à notre cas

Terminal window
gem install test-kitchen kitchen-vagrant kitchen-ansible kitchen-docker kitchen-verifier-serverspec serverspec

J’ai mis aussi vagrant.

On teste

Normalement on devrait partir d’une feuille blanche pour faire du TDD mais là on va prendre un rôle existant pour y ajouter la partie test. On récupère un rôle permettant d’installer apache fourni par Jeff Geerling :

Terminal window
git clone https://github.com/geerlingguy/ansible-role-apache.git

Il faut créer ces répertoires et ces fichiers :

Terminal window
cd ansible-role-apache
touch .kitchen.yml
# pour la partie test :
mkdir -p test/integration/default
mkdir test/integration/serverspec
touch test/integration/default/default.yml
touch test/integration/serverspec/install_apache_spec.rb
touch test/integration/spec_helper.rb

Dans le fichier .kitchen.yml on décrit notre infrastructure de test :

---
driver:
name: docker
use_sudo: false
require_chef_omnibus: false
require_ruby_for_busser: true
provisioner:
name: ansible_playbook
hosts: localhost
require_ansible_repo: true
ansible_verbose: true
ansible_verbosity: 2
ansible_diff: true # sympa ce truc
require_chef_for_busser: false
ssh_known_hosts:
- github.com
ignore_extensions_from_root: [".git"]
ignore_paths_from_root: [".git",".kitchen","bin"]
platforms:
- name: centos7
driver:
platform: rhel
image: centos:7
run_command: /usr/lib/systemd/systemd
provision_command:
- yum install -y iproute net-tools
verifier:
name: serverspec
sudo_path: true
suites:
- name: default
driver:
run_command: '/usr/sbin/init'
driver_config:
privileged: true
volume: /sys/fs/cgroup:/sys/fs/cgroup
verifier:
patterns:
- rôles/ansible-role-apache/test/integration/serverspec/*_spec.rb
transport:
max_ssh_sessions: 6
forward_agent: true

Quelques explications sur la structure de kitchen

Kitchen utilise des :

  • drivers ici j’ai choisi Docker, j’effectuerai des tests en local.
  • provisioners : j’ai bien sur choisi Ansible.
  • transports: paramétrages des sessions ssh
  • verifiers : j’ai choisi ServerSpec.
  • platforms: permet de définir comment est construit la machine de test.
  • suites: ce paramètre permet de configurer toute une stack si besoin, composé de plusieurs machines. Ici on se limite à une seule machine

Premières commandes kitchen

On peut déjà lancer les premières commandes kichen:

  • kitchen list qui permet de lister les instances.
  • kitchen create qui va créer les machines nécessaires au test.
Terminal window
$ kitchen list
Instance Driver Provisioner Verifier Transport Last Action Last Error
default-centos7 Docker AnsiblePlaybook Serverspec Ssh <Not Created> <None>
$ kithen create
.....
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
515cf7cb09ce 18a722885fb3 "/usr/sbin/init" About a minute ago Up About a minute 0.0.0.0:32809->22/tcp defaultcentos7-ubuntu-dev-ggl8fv2o

On voit que kitchen à instancier une machine docker :)

un playbook

Ajouter ceci au fichier test/integration/default/default.yml :

---
- hosts: all
- name: Installer le package httpd
hosts: all
gather_facts: False
rôles:
- { role: ansible-role-apache }

On lance l’installation

Cela se fait au moyen de la commande kitchen converge. Kitchen va installer tout ce qu’il faut pour exécuter le playbook et lancer le test. En cas d’erreur, vous pouvez vous connecter à votre instance avec la commande kitchen login. Si vous corrigez des choses relancer la commande kitchen converge.

Écriture d’un test

On va limiter le test à l’ajout du user apache. Ajouter ceci au fichier test/integration/serverspec/install_apache_spec.rb :

require_relative '../spec_helper'
describe user('apache') do
it { should exist }
it { should belong_to_group 'apache' }
it { should have_home_directory '/usr/share/httpd'}
it { should have_login_shell '/sbin/nologin'}
end

Il faut aussi ajouter ceci dans le fichier test/integration/spec_helper.rb. :

require 'serverspec'
set :backend, :exec

Lancement des tests

Cela se fait au moyen de la commande kitchen verify. Kitchen install à nouveau tout ce qu’il faut pour exécuter les tests.

Terminal window
$ kitchen verify
---> RSPEC_CMD variable is: /usr/local/bin/rspec
User "apache"
is expected to exist
is expected to belong to group "apache"
is expected to have home directory "/usr/share/httpd"
is expected to have login shell "/sbin/nologin"
Finished in 0.08071 seconds (files took 0.25256 seconds to load)
4 examples, 0 failures
Finished verifying <default-centos7> (0m3.43s).

Intégrer de nouvelles plateformes

Vous voulez ajouter une machine :) Ajouter juste ceci dans votre fichier .kitchen.yaml dans la partie platforms :

- name: oraclelinux8
driver:
platform: rhel
image: oraclelinux:8
run_command: /usr/lib/systemd/systemd
provision_command:
- dnf install -y iproute net-tools

On relance les commandes kitchen converge et kitchen verify.

Terminal window
$ kitchen converge
...
$ kitchen converge
...
$ kitchen verify
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["/usr/libexec/httpd-ssl-gencerts"], "delta": "0:00:00.002882", "end": "2020-12-31 13:58:09.185699", "msg": "non-zero return code", "rc": 127, "start": "2020-12-31 13:58:09.182817", "stderr": "/usr/libexec/httpd-ssl-gencerts: line 5: hostname: command not found", "stderr_lines": ["/usr/libexec/httpd-ssl-gencerts: line 5: hostname: command not found"], "stdout": "", "stdout_lines": []}

Il faut corriger ! Je vous en laisse le soin.

On peut aussi tout en une seule commande : kitchen test. Cela va provisionner, installer, tester et détruire. Tant qu’on parle de destruction, il existe la commande kitchen destroy à utiliser au besoin.

La suite de la formation ansible dans de prochains billets avec peut-être un test avec ansible-test et le développement des collections.