fix: caracteristique.md
This commit is contained in:
parent
9d6778ce4f
commit
1adae63e18
1 changed files with 620 additions and 0 deletions
620
caracteristique.md
Normal file
620
caracteristique.md
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
---
|
||||
gitea: none
|
||||
include_toc: true
|
||||
---
|
||||
|
||||
# Rougail : caractéristiques
|
||||
|
||||
Rougail est un outil qui permet de gérer le cycle de vie des variables et de gestion des valeurs de ces variables.
|
||||
|
||||
Au moment de la conception de Rougail, il y a eu des choix structurant qui ont défini le fonctionnement de l'outil.
|
||||
|
||||
Voici la liste des principales caractéristiques :
|
||||
|
||||
## Logiciel libre
|
||||
|
||||
Rougail est un logiciel libre (et Open Source) de gestion externe de variables.
|
||||
Le développement est réalisé de manière ouverte.
|
||||
|
||||
Rougail repose sur le logiciel libre Tiramisu comme moteur de contrainte.
|
||||
|
||||
Rougail est composé :
|
||||
|
||||
- d'un format de description
|
||||
- d'un projet principal "Rougail" qui :
|
||||
|
||||
- charge les fichiers de structures,
|
||||
- applique les valeurs des données utilisateur,
|
||||
- représente les variables avec leurs valeurs.
|
||||
|
||||
- différents sous projet pour étendre les fonctionnalités de base
|
||||
- un outil en ligne de commande pour facilité l'utilisation de la bibliothèque.
|
||||
|
||||
## Les acteurs
|
||||
|
||||
Rougail est destiné a séparer le cycle de vie de la variable entre 3 acteurs :
|
||||
|
||||
- l'acteur qui défini les variables
|
||||
- l'acteur qui adapte les valeurs
|
||||
- l'acteur qui utilise les variables avec leurs valeurs
|
||||
|
||||
Exemples concret d'acteur :
|
||||
|
||||
Dans le cadre du déploiement d'une configuration :
|
||||
|
||||
- l'intégrateur défini les variables
|
||||
- l'exploitant adapte les valeurs
|
||||
- l'installeur utilise les variables avec leurs valeurs
|
||||
|
||||
Dans le cadre du développement d'une application :
|
||||
|
||||
- le dévelopeur défini les variables
|
||||
- l'utilisateur adapte les valeurs
|
||||
- l'application utilise les variables avec leurs valeurs
|
||||
|
||||
## Cycle de vie des variables
|
||||
|
||||
Rougail a pour but de définir les variables puis de gérer tout son cycle de vie.
|
||||
|
||||
Dans le cycle de vie d'une variable, on inclut les étapes générique d'une variable (par exemple pour le langage C) :
|
||||
|
||||
- déclaration (elles se voient attribuer un nom et un type) ;
|
||||
- définition (elles se voient affecter leur première valeur) ;
|
||||
- affectation (elles se voient modifier la valeur de la variable) ;
|
||||
- lecture (elles se voient utilisent la valeur de la variable) ;
|
||||
- fin de vie (elles se terminent à la destruction de l'objet).
|
||||
|
||||
Mais d'autres notions sont inclusent dans le cycle de vie :
|
||||
|
||||
- extension de la déclaration en ajoutant la "description" de la variable
|
||||
- présentation, l'acteur qui adapte les valeurs doit avoir toutes les informations nécessaires pour renseigner les valeurs, c'est ainsi qu'il est possible de généré automatiquement la documentation, le journal des modifications, ...
|
||||
- autorisations, des propriétés décrivent les contraintes d'accès
|
||||
- spécialisation, qui décrit l'usage possible d'une variable
|
||||
|
||||
Rôle des différents composants Rougail :
|
||||
|
||||
Le format permet de décrire :
|
||||
|
||||
- la déclaration (nom, type et description)
|
||||
- les autorisations
|
||||
- la spécialisation
|
||||
|
||||
Rougail et ces composants :
|
||||
|
||||
- la définition (via Tiramisu)
|
||||
- la présentation
|
||||
- l'affectation (via Tiramisu)
|
||||
- la lecture
|
||||
- la fin de vie
|
||||
|
||||
|
||||
## Architecture Structurals-UserDatas-Outputs
|
||||
|
||||
|
||||
### Structurals
|
||||
|
||||
Les fichiers de "Structures" sont des fichiers au format Rougail dans laquelle toutes les informations du cycle de vie sont définies.
|
||||
Il est important de tout mettre ces informations au même endroit. Ainsi on connaitre toutes les aspects de la variable en lisant ces fichiers.
|
||||
On y retrouve :
|
||||
|
||||
- un schéma
|
||||
- la définition des contraintes
|
||||
- des éléments de documentation
|
||||
- ...
|
||||
|
||||
Les variables sont ici mutables, elles peuvent être redéfinit à tout moment.
|
||||
Ces fichiers sont créées par l'acteur qui défini les variables.
|
||||
|
||||
|
||||
### UserDatas
|
||||
|
||||
Une fois la structure définie, il est possible de charger les "Données Utilisateur" (UserDatas). On retrouve plusieurs type de données utilisateurs :
|
||||
|
||||
- des fichiers de configuration
|
||||
- des variables d'environnement
|
||||
- des sources externes
|
||||
- des options de lignes de commande
|
||||
- un formulaire
|
||||
- ...
|
||||
|
||||
Les variables sont ici immuables, par contre les valeurs sont mutables.
|
||||
Ces sources sont peuplées par l'acteur qui adapte les valeurs.
|
||||
|
||||
|
||||
### Outputs
|
||||
|
||||
Ensuite on pourra définir sous quelle forme on veut recueillir l'information (Outputs) :
|
||||
|
||||
- un objet Tiramisu
|
||||
- une extraction JSON
|
||||
- un export pour l'inventaire Ansible
|
||||
- de la documetation
|
||||
- ...
|
||||
|
||||
Les variables et les valeurs sont ici immuables.
|
||||
|
||||
Voici un exemple concret :
|
||||
|
||||
Un intégrateur a besoin d'une variable et défini la défini ainsi (dans le fichier `structure_architecture.yml`) :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable:
|
||||
...
|
||||
```
|
||||
|
||||
L'exploitant défini la valeur de cette variable ainsi (dans le fichier `userdata.yml`) :
|
||||
|
||||
```yaml
|
||||
---
|
||||
my_variable: a value
|
||||
```
|
||||
|
||||
On désire afficher de manière lisible la configuration :
|
||||
|
||||
```bash
|
||||
rougail -m structure_architecture.yml -u yaml -yf userdata.yml
|
||||
╭──────── Caption ────────╮
|
||||
│ Variable Modified value │
|
||||
╰─────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: a value ◀ loaded from the YAML file "userdata.yml"
|
||||
```
|
||||
|
||||
|
||||
### Valeur par défaut
|
||||
|
||||
Les variables ont une valeur. Une valeur par défaut est définit à la variable (None ou []) mais il est possible d'en définir une autre.
|
||||
|
||||
Il ne faut pas confondre la valeur par défaut ou la/les valeur(s) défini par l'acteur adaptant la configuration.
|
||||
|
||||
Par exemple, si je veux définir la variable my_variable en y spécifiant une valeur par défaut (dans le fichier `structure_default.yml`) :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable:
|
||||
default: a default value
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_default.yml
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: a default value
|
||||
```
|
||||
|
||||
|
||||
## Le format : un langage
|
||||
|
||||
|
||||
### DSL (Domain Specific Language)
|
||||
|
||||
Contrairement à un langage générique, un langage dédié est conçu pour répondre à un domaine d'application précis.
|
||||
|
||||
La description des variables se faire dans des fichiers YAML version 1.2. Le langage de configuration de Rougail permet de décrire tout le cycle de vie de la variable.
|
||||
|
||||
|
||||
### Abstraction déclarative
|
||||
|
||||
Les variables sont décrite suivant un modèle déclaratif. Cela signigie que l'utilisateur définit simplement l'état final souhaité de celle-ci. Tiramisu determinera les actions nécessaires pour atteindre cet état.
|
||||
|
||||
Dit autrement l'utilisateur défini le schéma des variables qui sera ensuite appliqué de manière déterministe.
|
||||
|
||||
|
||||
|
||||
### Redéfinition explicite
|
||||
|
||||
Les variables peuvent être redéfinis à tout moment (utile notamment lorsqu'on définit des modèles de configuration). Mais la redéfinition d'une variable doit être explicitement déclaré comme tel.
|
||||
|
||||
Par exemple, si je veux redéfinir la variable my_variable en y spécifiant une valeur par défaut (dans le fichier `structure_redefine.yml`) :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable:
|
||||
redefine: true
|
||||
default: a new default value
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_default.yml structure_redefine.yml
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: a new default value
|
||||
```
|
||||
|
||||
|
||||
## Typage
|
||||
|
||||
|
||||
### Type standard
|
||||
|
||||
Rougail (et Tiramisu) accepte les types standards suivant :
|
||||
|
||||
- string (type par défaut d'une variable)
|
||||
- integer
|
||||
- float
|
||||
- boolean
|
||||
|
||||
|
||||
### Type métier
|
||||
|
||||
Mais on va retrouver également tout une série de type métier :
|
||||
|
||||
- IP
|
||||
- domainname
|
||||
- port
|
||||
- MAC
|
||||
- choice
|
||||
- secret
|
||||
- ...
|
||||
|
||||
Voici quelques exemples :
|
||||
|
||||
```structure_type.yml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_integer: 1
|
||||
|
||||
my_mail:
|
||||
type: mail
|
||||
default: foo@bar.net
|
||||
|
||||
my_date:
|
||||
type: date
|
||||
default: "2025-11-19"
|
||||
...
|
||||
```
|
||||
|
||||
```rougail -m structure_type.yml
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┣━━ 📓 my_integer: 1
|
||||
┣━━ 📓 my_mail: foo@bar.net
|
||||
┗━━ 📓 my_date: 2025-11-19
|
||||
```
|
||||
|
||||
|
||||
### Fortement typé
|
||||
|
||||
Rougail utilise en interne la bibliothèque Tiramisu. Les variables dans Tiramisu sont fortement typé.
|
||||
C'est à dire que le chargement des données utilisateur implique une attention sur le type des variables. Pour les données utilisateurs non typées (comme les variables d'environnement), en pré traitement, il y aura une adaptation du type de la valeur.
|
||||
|
||||
Par exemple si l'exploitant adapte la valeur de cette variable ainsi (dans le fichier userdata_fort_type.yml :
|
||||
|
||||
```yaml
|
||||
---
|
||||
my_variable: 1
|
||||
```
|
||||
|
||||
La valeur ne pourra pas être chargée (le type par défaut étant le type "string") :
|
||||
|
||||
```bash
|
||||
rougail -m structure_architecture.yml -u yaml -yf userdata_fort_type.yml
|
||||
🔔 WARNINGS
|
||||
┗━━ the value "1" is an invalid string for "my_variable", which is not a string, it will be ignored when loading from the YAML file "userdata.yml"
|
||||
🛑 ERRORS
|
||||
┗━━ The following variables are mandatory but have no value:
|
||||
┗━━ my_variable
|
||||
```
|
||||
|
||||
### Typage dynamique
|
||||
|
||||
Au moment de la définition de la structure, le type est dynamique. C'est à dire que l'acteur qui défini la variable peut changé à tout moment le type de la variable.
|
||||
|
||||
Par exemple (dans le fichier `structure_redefine_type.yml`) :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable:
|
||||
redefine: true
|
||||
type: integer
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_architecture.yml structure_redefine_type.yml -u yaml -yf userdata_fort_type.yml
|
||||
╭──────── Caption ────────╮
|
||||
│ Variable Modified value │
|
||||
╰─────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: 1 ◀ loaded from the YAML file "userdata.yml"
|
||||
```
|
||||
|
||||
Par contre, comme l'exemple du typage fort le suggère, l'acteur qui adapte la valeur n'a pas la possiblité de redéfinir le type de la variable.
|
||||
|
||||
### Inférence de type
|
||||
|
||||
Le type peut être défini explicitement (comme dans le fichier structure_type.yml) ou déduit du typage des variables YAML.
|
||||
|
||||
Par exemple la variable avec une valeur par défaut à 1 est une variable de type "integer" :
|
||||
|
||||
```structure3.yml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable: 1
|
||||
...
|
||||
```
|
||||
|
||||
```rougail -m structure3.yml
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: 1
|
||||
```
|
||||
|
||||
|
||||
### Valeur "nullable"
|
||||
|
||||
Le type "null" (ou "None" en python) n'existe pas dans Rougail. "null" est une valeur. Tous les types peuvent accepter cette valeur, mais par défaut, ce n'est pas le cas.
|
||||
|
||||
Voici la déclaration d'une variable avec la valeur par défaut à "null" (dans le fichier `structure_nullable.yml`) :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable:
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_nullable.yml
|
||||
🛑 ERRORS
|
||||
┗━━ The following variables are mandatory but have no value:
|
||||
┗━━ my_variable
|
||||
```
|
||||
|
||||
En réalité la variable n'est pas accessible lorsque Tiramisu est mode "lecture seule" (ce qui est le cas lors des étapes Outputs par défaut). Lorsqu'on force le mode "lecture écriture" on a bien accès :
|
||||
|
||||
```bash
|
||||
rougail -m structure_nullable.yml --cli.read_write
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: null
|
||||
```
|
||||
|
||||
Pour que notre variable accepte dans tous les cas "null" il faut modifier le fichier de structure comme cela :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_variable:
|
||||
mandatory: false
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_nullable.yml --cli.read_write
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_variable: null
|
||||
```
|
||||
|
||||
|
||||
## Intégrité des données
|
||||
|
||||
L'intégrité des données fait référence au fait que les données doivent être fiables et précises tout au long de leur cycle de vie.
|
||||
|
||||
Cela signifie que la valeur doit être :
|
||||
|
||||
- de qualité
|
||||
- adapté au context globale
|
||||
|
||||
|
||||
### Qualité de la donnée
|
||||
|
||||
Pour avoir des données de qualité, il faut que l'outil valide la saisie utilisateur.
|
||||
|
||||
La première façon de valider la donnée est bien évidement de définir le bon type.
|
||||
|
||||
Mais cela ne suffit pas.
|
||||
|
||||
#### Paramètres de type
|
||||
|
||||
Il existe, pour certains type, un certains nombres de paramètres qui vont pouvoir compléter le typage des variables :
|
||||
|
||||
```structure_param_type.yml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_percent:
|
||||
type: integer
|
||||
params:
|
||||
min_integer: 0
|
||||
max_integer: 100
|
||||
default:
|
||||
10
|
||||
...
|
||||
```
|
||||
|
||||
```rougail -m structure_param_type.yml
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_percent: 10
|
||||
```
|
||||
|
||||
Mais avec une donnée utilisateur invalide, la valeur ne sera pas chargé (dans le fichier `userdata1.yml`) :
|
||||
|
||||
```yaml
|
||||
---
|
||||
my_percent: 120
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure6.yml -u yaml -yf userdata1.yml
|
||||
🔔 WARNINGS
|
||||
┗━━ the value "120" is an invalid integer for "my_percent", value must be less than "100", it will be
|
||||
ignored when loading from the YAML file "userdata1.yml"
|
||||
╭─────── Caption ────────╮
|
||||
│ Variable Default value │
|
||||
╰────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_percent: 10
|
||||
```
|
||||
|
||||
Ou pourra même généré une erreur :
|
||||
|
||||
```bash
|
||||
rougail -m structure6.yml -u yaml -yf userdata1.yml --cli.invalid_user_datas_error
|
||||
🛑 ERRORS
|
||||
┗━━ the value "120" is an invalid integer for "my_percent", value must be less than "100", it will be
|
||||
ignored when loading from the YAML file "userdata1.yml
|
||||
```
|
||||
|
||||
|
||||
#### Validation
|
||||
|
||||
Mais il est possible d'ajouter des validations complémentaires, par exemple ici vérifier que la variable est impaire (dans le fichier `structure_validators.yml`) :
|
||||
|
||||
```structure_validators.yml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_odd_variable:
|
||||
type: integer
|
||||
validators:
|
||||
- jinja: "{% if not (_.my_odd_variable % 2) %}not an odd integer{% endif %}"
|
||||
default:
|
||||
10
|
||||
...
|
||||
```
|
||||
|
||||
```rougail -m structure7.yml
|
||||
🛑 ERRORS
|
||||
┗━━ "10" is an invalid integer for "my_odd_variable", not an odd integer
|
||||
```
|
||||
|
||||
Par contre cela passe avec une valeur impaire (dans le fichier `userdata_validators.yml`) :
|
||||
```yaml
|
||||
---
|
||||
my_odd_variable: 11
|
||||
```
|
||||
|
||||
|
||||
```bash
|
||||
rougail -m structure_validators.yml -u yaml -ff userdata_validators.yml
|
||||
╭────────────── Caption ───────────────╮
|
||||
│ Variable Modified value │
|
||||
│ (⏳ Original default value) │
|
||||
╰──────────────────────────────────────╯
|
||||
Variables:
|
||||
┗━━ 📓 my_odd_variable: 11 ◀ loaded from the YAML file "userdata_validators.yml" (⏳ 10)
|
||||
```
|
||||
|
||||
### Cohérence globale
|
||||
|
||||
Une variable isolée peut être considéré comme étant de qualité mais devenir incohérence suivant le contexte.
|
||||
|
||||
Par exemple, si on demande une valeur minimum puis une valeur maximum, la minimal doit être inférieur à la maximal. Dans le fichier `structure_consistency.yml` on a :
|
||||
|
||||
```yaml
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_min_value: 11
|
||||
|
||||
my_max_value:
|
||||
default:
|
||||
variable: _.my_min_value
|
||||
validators:
|
||||
- jinja: |-
|
||||
{% if _.my_min_value >= _.my_max_value %}
|
||||
must but upper than {{ _.my_min_value }} (the value of "my_min_value")
|
||||
{% endif %}
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_consistency.yml
|
||||
🛑 ERRORS
|
||||
┗━━ "11" is an invalid integer for "my_max_value", must but upper than 11 (the value of "my_min_value")
|
||||
```
|
||||
|
||||
Si on défini la bonne valeur :
|
||||
|
||||
```yaml
|
||||
---
|
||||
my_max_value: 13
|
||||
```
|
||||
|
||||
```bash
|
||||
%YAML 1.2
|
||||
---
|
||||
version: 1.1
|
||||
|
||||
my_min_value: 11
|
||||
|
||||
my_max_value:
|
||||
default:
|
||||
variable: _.my_min_value
|
||||
validators:
|
||||
- jinja: |-
|
||||
{% if _.my_min_value >= _.my_max_value %}
|
||||
must but upper than {{ _.my_min_value }} (the value of "my_min_value")
|
||||
{% endif %}
|
||||
...
|
||||
```
|
||||
|
||||
```bash
|
||||
rougail -m structure_consistency.yml -u yaml -ff userdata_consistency.yml
|
||||
╭────────────── Caption ───────────────╮
|
||||
│ Variable Default value │
|
||||
│ Modified value │
|
||||
│ (⏳ Original default value) │
|
||||
╰──────────────────────────────────────╯
|
||||
Variables:
|
||||
┣━━ 📓 my_min_value: 11
|
||||
┗━━ 📓 my_max_value: 13 ◀ loaded from the YAML file "userdata_consistency.yml" (⏳ 11)
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Arborescent
|
||||
Inspiré par ABAC
|
||||
Spécialisation des variables
|
||||
Modèle de configuration
|
||||
Réutilisable/partageable
|
||||
Simple/list/array/dynamique
|
||||
retutilisable
|
||||
jit
|
||||
traduit
|
||||
templating
|
||||
linter
|
||||
Loading…
Reference in a new issue