AbdelbassetKABOU / CI_SentiDock

Automatiser un pipeline CI/CD pour tester une API utilisant Docker-composite et Redis

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CI_SentiDock

Objectif

L'objectif est de crier un pipeline CI/CD pour tester une API. Nous allons nous placer dans la peau d'une équipe censé créer une batterie de test à appliquer automatiquement avant déploiement.

Usage

Lancez la commande : ./docker-compose up. Suivant les variables d'environement PRINT et LOG _(dans le fichier docker-compose.yml), le résultat des tests sera affiché sur la console et/ou sur le fichier api_test.log à l'intérieur du répertoire cicd_vol.

API

Dans ce scénario, une équipe a créé une application qui permet d'utiliser un algorithme de sentiment analysis: il permet de prédire si une phrase (en anglais) a plutôt un caractère positif ou négatif. Cette API va être déployée dans un container dont l'image est pour l'instant :

datascientest/fastapi:1.0.0

Les endpoints de cette API sont les suivants :

  • status: renvoie 1 si l'API fonctionne
  • permissions: renvoie les permissions d'un utilisateur
  • /v1/sentiment: renvoie l'analyse de sentiment en utilisant un vieux modèle
  • /v2/sentiment: renvoie l'analyse de sentiment en utilisant un nouveau modèle

Le point d'entrée /status permet simplement de vérifier que l'API fonctionne bien. Le point d'entrée /permissions permet à quelqu'un, identifié par un username/password de voir à quelle version du modèle il a accès. Enfin les deux derniers prennent une phrase en entrée, vérifie que l'utilisateur est bien identifiée, vérifie que l'utilisateur a bien le droit d'utiliser ce modèle et si c'est le cas, renvoie le score de sentiment: -1 est négatif; +1 est positif.

L'API est disponible sur le port 8000 de la machine hôte. Une description détaillée des points d'entrée est disponible sur le point d'entrée /docs.

Tests

Nous allons définir certains scénarios de tests qui se feront via des containers distincts.

Authentication

Dans ce premier test, nous allons vérifier que la logique d'identification fonctionne bien. Pour cela, il va falloir effectuer requêtes de type GET sur le point d'entrée /permissions. Nous savons que deux utilisateurs existent alice et bob et leurs mots de passes sont wonderland et builder. Nous allons essayer un 3e test avec un mot de passe qui ne fonctionne pas: clementine et mandarine.

Authorization

Dans ce deuxième test, nous allons vérifier que la logique de gestion des droits de nos utilisateurs fonctionne correctement. Nous savons que bob a accès uniquement à la v1 alors que alice a accès aux deux versions. Pour chacun des utilisateurs, nous allons faire une requête sur les points d'entrée /v1/sentiment et /v2/sentiment: on doit alors fournir les arguments username, password et sentence qui contient la phrase à analyser.

Content

Dans ce dernier test, nous vérifions que l'API fonctionne comme elle doit fonctionner. Nous allons tester les phrases suivantes avec le compte d'alice:

  • life is beautiful
  • that sucks

Pour chacune des versions du modèle, on devrait récupérer un score positif pour la première phrase et un score négatif pour la deuxième phrase. Le test consistera à vérifier la positivité ou négativité du score.

Construction des tests

Pour chacun des tests, nous créons un container séparé qui effectuera ces tests. L'idée d'avoir un container par test permet de ne pas changer tout le pipeline de test si jamais une des composantes seulement a changé.

Le testeur se dispose de deux variables d’environnements. Si le variable LOG vaut 1, on imprime une trace dans un fichier api_test.log. Si PRINT vaut 1, on l'imprime sur la console.

Trois type de tests sont disponibles : Authentication, Authorization et Content. Les trois types partagent la même structure, à savoir :

  • Un fichier de la partie métier (authentication.py, authorization.py et content.py)
  • Un fichier de configuration (config. py) rassemblant l’essentiel des variables utilisés pour chaque type de test, e.g. adresse de l'API, port, log file, etc.
  • Un fichier database. py contenant l'ensembles des utilisateurs (users_database) et des phrases (sentences_database) requises pour les tests.

Redis

Pour une meilleure performance, les variables de configurations (ainsi que les données des utilisateurs/phrases de test) sont sollicités depuis une base de donnée de type redis, avec les couples key/value suivants :

  • api_address : adresse du serveur d'API

  • api_port : port de l'API

  • logfile : nom du fichier de trace

  • volume : nom du volume contenant le fichier de trace (dans notre cas api_test.py)

  • authentication_output : un template de trace pour la partie authentification.

    Exemple :

    ============================
         Authentication test_
    ============================
    request done at "/permissions"
         | username="alice"
         | password="wonderland"
    expected result = 200
    actual restult = {status_code}
    ==> {test_status}
    
  • authorization_output, content_output, i.e. des templates relatives aux tests d'autorisation et de contenu

  • users : l'ensemble des utilisateurs de test (nécessaires pour les requêtes de test)

  • sentences : l'ensemble des phrases de test (requise notamment lors des test de type "content")

A noter que Redis, par défault, ne supporte pas des structures de type nested_dictionnaries. Pour remédier à ce problème, on a diviser chaque base de donnée en deux parties, une englobant uniquement les logins (e.g. "alice", "bob", etc) et l'autre listant les détails de chaque utilisateurs (e.g. 'alice': {'password': "xxxx", 'v1': 1, 'v2': 1}).

Le lancement du serveur se fait via un script shell (start-redis.sh). Le fichier permet également d'insérer les données (keys) vues précédemment via le client redis-cli avec un fichier nommé redis-dump.csv dont voici un extrait :

SET api_address 'sentiment'
SET api_port '8000'
...

Docker Compose

On construira par la suite les images Docker via des DockerFile (fichiers présent à l'intérieur de chaque répertoire de test)

Pour une meilleure automatisation, on utilise Docker Compose qui est un outil très utilisé pour les pipelines de CI/CD. Il nous permet de lancer nos différents tests d'un coup tout en facilitant le partage de données entre les différents tests. docker-compose.yml est notre fichier qui organise ce pipeline.

Le fichier au final décrit cinq conteneurs (services), à savoir : authentication, authorization, content ainsi que les deux derniers : sentiment (serveur d'API) et redis (base de donnée).

A noter les routines depends_on et networks. La première assure le lancement des deux service (sentiment et redis) avant l'exécution des tests. La deuxième déclare et précise que l'ensemble de l'infrastructure est interconnectée via un réseau virtuel baptisé cicd_networkd

Comming soon

Dans le cadre d'un déploiement en production, il se peut nécessaire d'ajouter l'authentification au serveur Redis. Le stockage en clair des password est également à éviter. L'utilisation de la bibliothèque bcrypt me semble un choix judicieux dans ce cas.

About

Automatiser un pipeline CI/CD pour tester une API utilisant Docker-composite et Redis


Languages

Language:Python 94.1%Language:Dockerfile 3.0%Language:Shell 2.8%