Aller au contenu principal

Tester ses rôles Ansible avec Serverspec

· 6 minutes de lecture
Stéphane ROBERT
Consultant DevOps

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 :

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

Donnons les droits de lancer des commandes docker à votre utilisateur

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 :

sudo pip3 install ansible ansible-lint

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

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 :

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

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

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.
$ 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.

$ 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.

$ 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.