Compare commits

...

8 Commits

42 changed files with 488 additions and 254 deletions

View File

@ -11,6 +11,7 @@ Rougail est un bibliothèque python3 qui permet de charger des dictionnaires (fi
- [Les dictionnaires](dictionary/rougail.md)
- [Les dictionnaires extra](dictionary/extra.md)
- [Convention d'écriture d'un dictionnaire](dictionary/convention.md)
### Les variables

View File

@ -8,12 +8,12 @@ Voici un exemple simple de validation des valeurs :
```
<variables>
<variable name="my_variable"/>
<variable name="my_variable"/>
</variables>
<constraints>
<check name="islower">
<target>my_variable</target>
</check>
<check name="islower">
<target>my_variable</target>
</check>
</constraints>
```
@ -46,7 +46,7 @@ Dans la contrainte, il est possible de spécifier le niveau d'erreur et le mettr
```
<check name="islower" level="warning">
<target>my_variable</target>
<target>my_variable</target>
</check>
```

View File

@ -6,12 +6,12 @@ Dans un premier dictionnaire déclarons notre variable et sa fonction de vérifi
```
<variables>
<variable name="my_variable"/>
<variable name="my_variable"/>
</variables>
<constraints>
<check name="islower">
<target>my_variable</target>
</check>
<check name="islower">
<target>my_variable</target>
</check>
</constraints>
```
@ -19,12 +19,12 @@ Dans un second dictionnaire il est possible de redéfinir le calcul :
```
<variables>
<variable name="my_variable" redefine="True"/>
<variable name="my_variable" redefine="True"/>
</variables>
<constraints>
<check name="isspace">
<target>my_variable</target>
</check>
<check name="isspace">
<target>my_variable</target>
</check>
</constraints>
```
@ -40,12 +40,12 @@ Dans un premier dictionnaire déclarons notre variable et notre fonction de vér
```
<variables>
<variable name="my_variable"/>
<variable name="my_variable"/>
</variables>
<constraints>
<check name="islower">
<target>my_variable</target>
</check>
<check name="islower">
<target>my_variable</target>
</check>
</constraints>
```
@ -53,9 +53,9 @@ Dans un second dictionnaire supprimer cette vérification :
```
<variables>
<family name="family">
<variable name="my_variable" redefine="True" remove_check="True"/>
</family>
<family name="family">
<variable name="my_variable" redefine="True" remove_check="True"/>
</family>
</variables>
```

View File

@ -10,15 +10,15 @@ La condition hidden_if_in permet de cacher une variable où une famille à l'uti
```
<variables>
<variable name="condition" type="boolean"/>
<variable name="my_variable"/>
<variable name="condition" type="boolean"/>
<variable name="my_variable"/>
</variables>
<constraints>
<condition name="hidden_if_in" source="condition">
<param>True</param>
<target>my_variable</target>
</condition>
<condition name="hidden_if_in" source="condition">
<param>True</param>
<target>my_variable</target>
</condition>
</constraints>
```
@ -34,16 +34,16 @@ Il est également possible de mettre plusieurs paramètre :
```
<variables>
<variable name="condition"/>
<variable name="my_variable"/>
<variable name="condition"/>
<variable name="my_variable"/>
</variables>
<constraints>
<condition name="hidden_if_in" source="condition">
<param>yes</param>
<param>maybe</param>
<target>my_variable</target>
</condition>
<condition name="hidden_if_in" source="condition">
<param>yes</param>
<param>maybe</param>
<target>my_variable</target>
</condition>
</constraints>
```
@ -69,8 +69,8 @@ Exemple :
```
<condition name="hidden_if_in" source="condition" optional="True", apply_on_fallback="False">
<param>yes</param>
<param>maybe</param>
<target>my_variable</target>
<param>yes</param>
<param>maybe</param>
<target>my_variable</target>
</condition>
```

View File

@ -8,15 +8,15 @@ Dans un premier dictionnaire déclarons notre variable et notre calcule :
```
<variables>
<variable name="condition" type="boolean"/>
<variable name="my_variable"/>
<variable name="condition" type="boolean"/>
<variable name="my_variable"/>
</variables>
<constraints>
<condition name="hidden_if_in" source="condition">
<param>True</param>
<target>my_variable</target>
</condition>
<condition name="hidden_if_in" source="condition">
<param>True</param>
<target>my_variable</target>
</condition>
</constraints>
```
@ -24,6 +24,6 @@ Dans un second dictionnaire supprimer ce calcul :
```
<variables>
<variable name="condition" redefine="True" remove_condition="True"/>
<variable name="condition" redefine="True" remove_condition="True"/>
</variables>
```

View File

@ -13,11 +13,11 @@ Voici un premier dictionnaire /srv/rougail/dictionaries/00-base.xml :
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<variable name="my_variable">
<value>my_value</value>
</variable>
</variables>
<variables>
<variable name="my_variable">
<value>my_value</value>
</variable>
</variables>
</rougail>
```
@ -39,11 +39,11 @@ En plus du dictionnaire précédent, créons un dictionnaire extra /srv/rougail/
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables>
<variable name="my_variable_extra">
<value>my_value_extra</value>
</variable>
</variables>
<variables>
<variable name="my_variable_extra">
<value>my_value_extra</value>
</variable>
</variables>
</rougail>
```
@ -65,11 +65,11 @@ Nous créons un dictionnaire complémentaire pour ajouter notre template /srv/ro
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<services>
<service name="example">
<file name="/etc/example.conf"/>
</service>
</services>
<services>
<service name="example">
<file name="/etc/example.conf"/>
</service>
</services>
</rougail>
```
@ -163,11 +163,11 @@ Nous créons un dictionnaire complémentaire pour ajouter un calcul à la variab
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<constraints>
<fill name="return_no">
<target>my_variable</target>
</fill>
</constraints>
<constraints>
<fill name="return_no">
<target>my_variable</target>
</fill>
</constraints>
</rougail>
```

View File

@ -14,6 +14,12 @@ Pour modifier il suffit de faire :
RougailConfig[key] = value
```
## Ajout d'une fonction de conversion
Les fonctions de conversion fait parti du moteur de rougail. Il converti les informations des dictionnaires pour créer des variables Tiramisu.
La clef "extra_annotators" permet d'ajouter des fonctions complémentaires.
## Configuration de chargement des dictionnaires
### Les répertoires des dictionnaires
@ -50,6 +56,9 @@ Pour pouvez changer le répertoire de destination de la DTD et le nom du fichier
Le fichier qui contient les fonctions personnalisés est géré dans la clef "functions_file" et a comme valeur par défaut "/srv/rougail/functions.py". Cette clef peut contenir une liste s'il y a plusieurs fichiers.
Les fonctions doivent retourner une valeur, même si la variable que l'on calcul est une variable multiple.
Si la fonction peut retourner une valeur multiple (une liste), il faut mettre le nom de la fonction dans la clef "multi_functions".
### La variable auto_freeze
La propriété auto_freeze n'est appliqué que une variable spécifique passe à True. Par défaut le nom de la variable est "instancied_module", mais il est possible de changer le nom de cette variable via la clef "auto_freeze_variable".
@ -113,8 +122,6 @@ Le groupe propriétaire des fichiers générés est géré dans la clef "default
La méthode d'inclusion des fichiers générés est géré dans la clef "default_files_included" et a comme valeur par défaut : "no". Les valeurs possible sont "no", "name" et "content".
'default_files_included': 'no',
## La configuration par défaut des overrides
### Le moteur de templates par défaut
## La configuration du moteur de templates
Le moteur de template est géré dans la clef "default_overrides_engine" et a comme valeur par défaut : "creole". Les valeurs possible sont "none", "creole" ou "jinja2".

View File

@ -0,0 +1,13 @@
# Convention de rédaction d'un dictionnaire
## Ordonnancement du dictionnaire
L'ordre des informations mise dans le dictionnaire est idéalement :
- services
- variables
- constraintes
## Le nom d'espace
Le nom d'espace dans un dictionnaire est de deux espaces.

View File

@ -7,11 +7,11 @@ Par exemple :
```
<variable name='varname' multi="True">
<value>val1</value>
<value>val2</value>
<value>val1</value>
<value>val2</value>
</variable>
<family name="my_dyn_family_" dynamic="varname" description="Describe ">
<variable name="my_dyn_var_"/>
<variable name="my_dyn_var_"/>
</family>
```

View File

@ -35,11 +35,11 @@ Voici un exemple de définition d'une variable meneuse et de deux variables mene
```
<variables>
<family name="family" leadership='True'>
<variable name="leader" multi='True'/>
<variable name="follower1"/>
<variable name="follower2" multi='True'/>
</family>
<family name="family" leadership='True'>
<variable name="leader" multi='True'/>
<variable name="follower1"/>
<variable name="follower2" multi='True'/>
</family>
</variables>
```
@ -49,8 +49,8 @@ Pour ajouter, dans un nouveau dictionnaire, une variable suiveuse à notre group
```
<variables>
<family name="family">
<variable name="follower3"/>
</family>
<family name="family">
<variable name="follower3"/>
</family>
</variables>
```

View File

@ -12,7 +12,7 @@ Cette famille doit être placé dans une balise [variables](../variables.md) :
```
<variables>
<family name="my_family"/>
<family name="my_family"/>
</variables>
```
@ -20,9 +20,9 @@ Ou dans une autre famille :
```
<variables>
<family name="my_family">
<family name="second_family"/>
</family>
<family name="my_family">
<family name="second_family"/>
</family>
</variables>
```

View File

@ -4,3 +4,4 @@ Une variable calculée est une variable donc sa valeur est le résultat d'une fo
- [Valeur calculée de la variable](value.md)
- [Réfinition](redefine.md)
- [Exemples de calcule](examples.md)

48
doc/fill/examples.md Normal file
View File

@ -0,0 +1,48 @@
# Exemples de calcule
## Calculer les noms de modèle à généré à partir d'une variable
Créeons deux variables multiples, une pour accueillir la liste des éléments du nom variable (ici `zones_list`), la seconde étant le nom du fichier calculé (ici `netwokd_configurations`) :
```
<variables>
<variable name="zones_list" type="string" multi="True">
<value>zone1</value>
<value>zone2</value>
<value>zone3</value>
</variable>
<variable name="netwokd_configurations" type="filename" multi="True" hidden="True"/>
</variables>
```
Calculons la valeur de la seconde variable à partir de la première :
```
<constraints>
<fill name="calc_value">
<param>/systemd/network/10-</param>
<param type="variable">zones_list</param>
<param>-risotto.network</param>
<param name="join"></param>
<param name="multi" type="boolean">True</param>
<target>netwokd_configurations</target>
</fill>
</constraints>
```
Le contenu de la variable `netwokd_configurations` sera alors :
- /systemd/netword/10-zone1/risotto.network
- /systemd/netword/10-zone2/risotto.network
- /systemd/netword/10-zone3/risotto.network
Enfin déclarer une balise file en utilisant ces deux variables :
```
<services>
<service name="systemd-networkd">
<file file_type="variable" source="network" variable="zones_list">netwokd_configurations</file>
</service>
</services>
```

View File

@ -6,12 +6,12 @@ Créons une variable dont la valeur est retournée par la fonction "return_no" :
```
<variables>
<variable name="my_calculated_variable"/>
<variable name="my_calculated_variable"/>
</variables>
<constraints>
<fill name="return_no">
<target>my_calculated_variable</target>
</fill>
<fill name="return_no">
<target>my_calculated_variable</target>
</fill>
</constraints>
```
@ -30,7 +30,7 @@ Attention, si une valeur par défaut est définit dans la variable "my_calculate
```
<variable name="my_calculated_variable">
<value>yes</value>
<value>yes</value>
</variable>
```
Cette valeur par défaut sera complètement ignorée. C'est le calcul qui en définira la valeur.
@ -59,24 +59,24 @@ Il est également possible de calculer [une variable d'une famille dynamique](..
```
<variables>
<variable name='suffixes' type='string' description="Suffixes of dynamic family" multi="True">
<value>val1</value>
<value>val2</value>
<variable name='suffixes' type='string' description="Suffixes of dynamic family" multi="True">
<value>val1</value>
<value>val2</value>
</variable>
<variable name="my_variable" type="string" description="My variable">
<value>val</value>
</variable>
<family name='dyn' dynamic="suffixes">
<variable name="my_calculated_variable_dyn\_" type="string" description="My calculated variable"/>
<value>val</value>
</variable>
<variable name="my_variable" type="string" description="My variable">
<value>val</value>
</variable>
<family name='dyn' dynamic="suffixes">
<variable name="my_calculated_variable_dyn\_" type="string" description="My calculated variable"/>
<value>val</value>
</variable>
</family>
</family>
</variables>
<constraints>
<fill name="return_value">
<param type="variable">my_variable</param>
<target>my_calculated_variable_dyn_</target>
</fill>
<fill name="return_value">
<param type="variable">my_variable</param>
<target>my_calculated_variable_dyn_</target>
</fill>
</constraints>
```
@ -90,11 +90,11 @@ Dans ce cas, il faut explicitement demander la valeur du suffix dans la fonction
```
<constraints>
<fill name="return_value_suffix">
<param type="variable">my_variable</param>
<param type="suffix"/>
<target>my_calculated_variable_dyn_</target>
</fill>
<fill name="return_value_suffix">
<param type="variable">my_variable</param>
<param type="suffix"/>
<target>my_calculated_variable_dyn_</target>
</fill>
</constraints>
```

View File

@ -11,9 +11,9 @@ Il faut, à la création du service, préciser son nom :
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<services>
<service name="squid"/>
</services>
<services>
<service name="squid"/>
</services>
</rougail>
```
@ -69,7 +69,7 @@ Il est possible de désactiver un service. Pour cela il faut rajouter l'attribut
```
<services>
<service name="test" disabled="True"/>
<service name="test" disabled="True"/>
</services>
```
@ -79,17 +79,17 @@ Il est possible de définir une [condition](../condition/README.md) de type "dis
```
<services>
<service name="test" servicelist="test">
</service>
<service name="test" servicelist="test">
</service>
</services>
<variables>
<variable name="condition" type="boolean"/>
<variable name="condition" type="boolean"/>
</variables>
<constraints>
<condition name="disabled_if_in" source="condition">
<param>False</param>
<target type="servicelist">test</target>
</condition>
<condition name="disabled_if_in" source="condition">
<param>False</param>
<target type="servicelist">test</target>
</condition>
</constraints>
```

View File

@ -10,9 +10,9 @@ Il est nécessaire, au minimum, de spécifier le chemin complet du fichier :
```
<services>
<service name="squid">
<file>/etc/squid/squid.conf</file>
</service>
<service name="squid">
<file>/etc/squid/squid.conf</file>
</service>
</services>
```
@ -30,14 +30,14 @@ Il est possible également de définir le nom du fichier dans une variable :
```
<services>
<service name="squid">
<file file_type="variable" source="squid.conf">my_variable</file>
</service>
<service name="squid">
<file file_type="variable" source="squid.conf">my_variable</file>
</service>
</services>
<variables>
<variable name="my_variable">
<value>/etc/squid/squid.conf</value>
</variable>
<variable name="my_variable">
<value>/etc/squid/squid.conf</value>
</variable>
</variables>
```
@ -49,15 +49,15 @@ Il est même possible de définir une variable de type multiple, ce qui génère
```
<services>
<service name="squid">
<file file_type="variable" source="squid.conf">my_variable</file>
</service>
<service name="squid">
<file file_type="variable" source="squid.conf">my_variable</file>
</service>
</services>
<variables>
<variable name="my_variable" multi="True">
<value>/etc/squid1/squid.conf</value>
<value>/etc/squid2/squid.conf</value>
</variable>
<variable name="my_variable" multi="True">
<value>/etc/squid1/squid.conf</value>
<value>/etc/squid2/squid.conf</value>
</variable>
</variables>
```
@ -73,23 +73,23 @@ En effet, il est possible de passer le contenu d'une variable au template :
```
<services>
<service name="squid">
<file file_type="variable" source="squid.conf" variable="my_variable2">my_variable1</file>
</service>
<service name="squid">
<file file_type="variable" source="squid.conf" variable="my_variable2">my_variable1</file>
</service>
</services>
<variables>
<variable name="my_variable1" multi="True">
<value>/etc/squid1/squid.conf</value>
<value>/etc/squid2/squid.conf</value>
</variable>
<variable name="my_variable2" multi="True">
<value>squid1</value>
<value>squid2</value>
</variable>
<variable name="my_variable1" multi="True">
<value>/etc/squid1/squid.conf</value>
<value>/etc/squid2/squid.conf</value>
</variable>
<variable name="my_variable2" multi="True">
<value>squid1</value>
<value>squid2</value>
</variable>
</variables>
```
Dans ce cas, lors de la génération du fichier /etc/squid1/squid.conf on retrouvera la variable "rougail_variable" avec la valeur "squid1" et le fichier /etc/squid2/squid.conf on retrouvera la variable "rougail_variable" avec la valeur "squid2".
Dans ce cas, lors de la génération du fichier /etc/squid1/squid.conf on retrouvera la variable "rougail_variable" avec la valeur "squid1" et la variable "rougail_index" avec la valeur "0". Lors de la génération du fichier /etc/squid2/squid.conf on retrouvera la variable "rougail_variable" avec la valeur "squid2" et la variable "rougail_index" avec la valeur "1".
Attention : les deux variables "my_variable1" et "my_variable2" doivent être multiple et de même longueur.
@ -117,18 +117,18 @@ Il est aussi possible de définir une [condition](../condition/README.md) de typ
```
<services>
<service name="test">
<file filelist="squid">/etc/squid/squid.conf</file>
</service>
<service name="test">
<file filelist="squid">/etc/squid/squid.conf</file>
</service>
</services>
<variables>
<variable name="condition" type="boolean"/>
<variable name="condition" type="boolean"/>
</variables>
<constraints>
<condition name="disabled_if_in" source="condition">
<param>False</param>
<target type="filelist">squid</target>
</condition>
<condition name="disabled_if_in" source="condition">
<param>False</param>
<target type="filelist">squid</target>
</condition>
</constraints>
```

View File

@ -28,19 +28,19 @@ Il est possible de définir une [condition](../condition/README.md) de type "dis
```
<services>
<service name="test">
<ip iplist="test_ip">variable_ip</ip>
</service>
<service name="test">
<ip iplist="test_ip">variable_ip</ip>
</service>
</services>
<variables>
<variable name="condition" type="boolean"/>
<variable name="variable_ip" type="ip"/>
<variable name="condition" type="boolean"/>
<variable name="variable_ip" type="ip"/>
</variables>
<constraints>
<condition name="disabled_if_in" source="condition">
<param>False</param>
<target type="iplist">test_ip</target>
</condition>
<condition name="disabled_if_in" source="condition">
<param>False</param>
<target type="iplist">test_ip</target>
</condition>
</constraints>
```

View File

@ -10,9 +10,9 @@ Il suffit d'avoir un template dont le nom est par défaut le nom du service avec
```
<services>
<service name="squid">
<override/>
</service>
<service name="squid">
<override/>
</service>
</services>
```

View File

@ -7,7 +7,7 @@ Il est placé à la racine du dictionnaire :
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<services/>
<services/>
</rougail>
```

View File

@ -8,10 +8,10 @@ Une variable est déjà un nom. C'est à dire qu'on pourra utiliser plus tard la
```
<variables>
<variable name="my_variable"/>
<family name="my_family">
<variable name="my_family_variable"/>
</variable>
<variable name="my_variable"/>
<family name="my_family">
<variable name="my_family_variable"/>
</variable>
</variables>
```
@ -39,7 +39,7 @@ Une variable a un type. Ce type permet de définir les valeurs acceptées par ce
- number : un nombre
- float : un chiffre flottant
- boolean : "True" ou "False", si aucune valeur n'est défini la valeur par défaut de cette variable sera "True", ces variables sont également obligatoire par défaut
- password : un mot de passe
- secret (ou password mais est obsolète) : un secret (comme un mot de passe, une clef privée, ...)
- mail : une adresse mail
- filename : nom de fichier au sens Unix (exemple : "/etc/passwd")
- date : une date au format "%Y-%m-%d" (exemple : "2021-01-30")
@ -123,7 +123,7 @@ Il est possible de fixer les valeurs par défaut d'une variable :
```
<variable name="my_variable">
<value>value</value>
<value>value</value>
</variable>
```
@ -131,8 +131,8 @@ Pour une variable multiple, il est possible de préciser plusieurs valeurs :
```
<variable name="my_variable" multi="True">
<value>value 1</value>
<value>value 2</value>
<value>value 1</value>
<value>value 2</value>
</variable>
```
@ -152,7 +152,9 @@ Attention trois attributs ne sont redéfinisable :
Créons notre variable :
<variable name="my_variable"/>
```
<variable name="my_variable"/>
```
Et redéfinisons là :
@ -186,7 +188,7 @@ Voici une variable a valeur automatiquement modifiée :
```
<variable name="my_variable" auto_save="True">
<value>my_value</value>
<value>my_value</value>
</variable>
```
@ -205,7 +207,7 @@ Voici un variable à valeur en lecture seule automatique :
```
<variable name="server_deployed" type="boolean">
<value>False</value>
<value>False</value>
</variable>
<variable name="my_variable" auto_freeze="True"/>
```
@ -252,3 +254,22 @@ Pour définir le [mode](../mode.md) :
```
<variable name="my_variable" mode="expert"/>
```
## Les variables qui fournissent des valeurs
Il peut être intéressant de retrouver facilement des variables sans connaitre le chemin complet mais en utilisant le contenu du paramètre "provider".
C'est particulièrement utile si un service peut être fournit par plusieurs services. Les variables n'auront donc pas le même nom. Utiliser ce paramètre, permet donc de retrouver facilement la variable.
Pour déclarer :
```
<variable name="my_variable" provider="my_function"/>
```
Dans le code de l'application, on pourra retrouver le chemin de la variable en faisant :
```
print(await config.information.get('provider:my_function'))
```
Pour les variables inclusent dans une famille dynamique, le chemin de la variable sera un template comme ceci "rougail.family_{suffix}.my_variable_{suffix}". Il vous suffit de remplacer "{suffix}" par le suffix voulu de la famille dynamique.

View File

@ -6,9 +6,9 @@ Il est possible d'imposer une liste de valeur pour une variable particulière :
```
<variable name="my_variable" type="choice">
<choice>val1</choice>
<choice>val2</choice>
<choice>val3</choice>
<choice>val1</choice>
<choice>val2</choice>
<choice>val3</choice>
</variable>
```
@ -19,10 +19,10 @@ Si la variable est obligatoire ou si une valeur est précisée (la variable pass
```
<variable name="my_variable" type="choice">
<choice>val1</choice>
<choice>val2</choice>
<choice>val3</choice>
<value>val1</value>
<choice>val1</choice>
<choice>val2</choice>
<choice>val3</choice>
<value>val1</value>
</variable>
```
@ -32,11 +32,11 @@ Par défaut les choix sont de type "string". Il est possible de préciser des no
```
<variable name="my_variable" type="choice">
<choice>val1</choice>
<choice type="string">val2</choice>
<choice type="number">3</choice>
<choice type="boolean">True</choice>
<choice type="nil"/>
<choice>val1</choice>
<choice type="string">val2</choice>
<choice type="number">3</choice>
<choice type="boolean">True</choice>
<choice type="nil"/>
</variable>
```
@ -48,7 +48,7 @@ Pour ajouter un choix à une variable à choix existante, rien de plus simple, j
```
<variable name="my_variable" redefine="True">
<choice>val4</choice>
<choice>val4</choice>
</variable>
```
@ -58,8 +58,8 @@ Si on veut supprimer un choix ou redéfinir complètement la liste, il faut red
```
<variable name="my_variable" redefine="True" remove_choice="True">
<choice>val1</choice>
<choice>val2</choice>
<choice>val1</choice>
<choice>val2</choice>
</variable>
```
@ -71,7 +71,7 @@ Une variable à valeur multiple peut servir de source des choix :
```
<variable name="my_variable" type="choice">
<choice type="variable">other_variable</choice>
<choice type="variable">other_variable</choice>
</variable>
```
@ -82,10 +82,10 @@ Seul un choice de type "variable" est possible par variable.
```
<variable name="my_variable" type="choice">
<choice type="function" name="trange">
<param type="number">0</param>
<param type="number">10</param>
</choice>
<value type="number">9</value>
<choice type="function" name="trange">
<param type="number">0</param>
<param type="number">10</param>
</choice>
<value type="number">9</value>
</variable>
```

View File

@ -33,17 +33,17 @@ Voici un exemple de définition d'une variable meneuse et de deux variables mene
```
<variables>
<family name="family">
<variable name="leader" multi='True'/>
<variable name="follower1"/>
<variable name="follower2" multi='True'/>
</family>
<family name="family">
<variable name="leader" multi='True'/>
<variable name="follower1"/>
<variable name="follower2" multi='True'/>
</family>
</variables>
<constraints>
<group leader="leader">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
<group leader="leader">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
</constraints>
```
@ -53,30 +53,41 @@ Il est possible d'en définit d'autres :
```
<constraints>
<group leader="leader" name="leadership" description="My leadership">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
<group leader="leader" name="leadership" description="My leadership">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
</constraints>
```
## Faire un calcul avec l'index de la variable meneuse
Dans un calcul sur un variable suiveuse il est possible de récupérer l'index de la variable meneuse :
```
<fill name="calc_val">
<param type="index"/>
<target>follower</target>
</fill>
```
## Définition des variables meneuse et suiveuse dans un dictionnaire extra
Voici un exemple de définition d'une variable meneuse et de deux variables meneuses dans un espace de nom "example" :
```
<variables>
<family name="family">
<variable name="leader" multi='True'/>
<variable name="follower1"/>
<variable name="follower2" multi='True'/>
</family>
<family name="family">
<variable name="leader" multi='True'/>
<variable name="follower1"/>
<variable name="follower2" multi='True'/>
</family>
</variables>
<constraints>
<group leader="example.family.leader">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
<group leader="example.family.leader">
<follower>follower1</follower>
<follower>follower2</follower>
</group>
</constraints>
```
@ -90,13 +101,13 @@ Pour ajouter, dans un nouveau dictionnaire, une variable suiveuse à notre group
```
<variables>
<family name="family">
<variable name="follower3"/>
</family>
<family name="family">
<variable name="follower3"/>
</family>
</variables>
<constraints>
<group leader="leader">
<follower>follower3</follower>
</group>
<group leader="leader">
<follower>follower3</follower>
</group>
</constraints>
```

View File

@ -7,6 +7,6 @@ Il est placé à la racine du dictionnaire :
```
<?xml version='1.0' encoding='UTF-8'?>
<rougail>
<variables/>
<variables/>
</rougail>
```

View File

@ -50,6 +50,8 @@ class Annotator(TargetAnnotator, ParamAnnotator):
self.objectspace = objectspace
self.functions = copy(functions)
self.functions.extend(self.objectspace.rougailconfig['internal_functions'])
self.calc_multi = list(CALC_MULTI)
self.calc_multi.extend(self.objectspace.rougailconfig['multi_functions'])
self.target_is_uniq = True
self.only_variable = True
self.allow_function = False
@ -79,7 +81,7 @@ class Annotator(TargetAnnotator, ParamAnnotator):
value = self.objectspace.value(fill.xmlfiles)
value.type = 'calculation'
value.name = fill.name
if fill.name not in CALC_MULTI:
if fill.name not in self.calc_multi:
is_calc_multi = self.calc_is_multi(target.name)
else:
is_calc_multi = False

View File

@ -56,11 +56,13 @@ class Annotator(Walk):
# hidden variable is also frozen
if isinstance(variable, self.objectspace.variable) and variable.hidden is True and \
variable.name != self.objectspace.rougailconfig['auto_freeze_variable']:
if not variable.auto_freeze:
if not variable.auto_freeze and \
not hasattr(variable, 'provider'):
variable.frozen = True
if not variable.auto_save and \
not variable.auto_freeze and \
'force_default_on_freeze' not in vars(variable):
'force_default_on_freeze' not in vars(variable) and \
not hasattr(variable, 'provider'):
variable.force_default_on_freeze = True
if not hasattr(variable, 'properties'):
variable.properties = []

View File

@ -35,6 +35,7 @@ CONVERT_OPTION = {'number': dict(opttype="IntOption", func=int),
'choice': dict(opttype="ChoiceOption"),
'string': dict(opttype="StrOption"),
'password': dict(opttype="PasswordOption"),
'secret': dict(opttype="PasswordOption"),
'mail': dict(opttype="EmailOption"),
'boolean': dict(opttype="BoolOption", func=convert_boolean),
'symlink': dict(opttype="SymLinkOption"),

View File

@ -43,6 +43,7 @@ RougailConfig = {'dictionaries_dir': [join(ROUGAILROOT, 'dictionaries')],
'variable_namespace': 'rougail',
'auto_freeze_variable': 'server_deployed',
'internal_functions': [],
'multi_functions': [],
'extra_annotators': [],
'modes_level': ['basic', 'normal', 'expert'],
'default_family_mode': 'basic',

View File

@ -93,7 +93,7 @@
<!ELEMENT variable ((choice*|value*)*)>
<!ATTLIST variable name CDATA #REQUIRED>
<!ATTLIST variable type (number|float|string|password|mail|boolean|filename|date|unix_user|ip|local_ip|netmask|network|broadcast|netbios|domainname|hostname|web_address|port|mac|cidr|network_cidr|choice) "string">
<!ATTLIST variable type (number|float|string|password|secret|mail|boolean|filename|date|unix_user|ip|local_ip|netmask|network|broadcast|netbios|domainname|hostname|web_address|port|mac|cidr|network_cidr|choice) "string">
<!ATTLIST variable description CDATA #IMPLIED>
<!ATTLIST variable help CDATA #IMPLIED>
<!ATTLIST variable hidden (True|False) "False">

View File

@ -29,7 +29,7 @@ from shutil import copy
import logging
from typing import Dict, Any
from subprocess import call
from os import listdir, makedirs, getcwd, chdir
from os import listdir, makedirs, getcwd, chdir, unlink, rmdir
from os.path import dirname, join, isfile, isdir, abspath
@ -271,7 +271,7 @@ class RougailBaseTemplate:
type_: str,
service_name: str,
service_type: str,
) -> None:
) -> str:
"""Run templatisation on one file
"""
self.log.info(_("Instantiating file '{filename}'"))
@ -286,6 +286,7 @@ class RougailBaseTemplate:
variable = [variable]
if not isdir(self.destinations_dir):
raise TemplateError(_(f'cannot find destinations_dir {self.destinations_dir}'))
destfilenames = []
for idx, filename, in enumerate(filenames):
if variable:
var = variable[idx]
@ -301,19 +302,28 @@ class RougailBaseTemplate:
)
if data is None:
continue
filename, source, destfile, var = data
destfilename = join(self.destinations_dir, destfile[1:])
filename, source, true_destfilename, var = data
destfilename = join(self.destinations_dir, true_destfilename[1:])
makedirs(dirname(destfilename), exist_ok=True)
self.log.info(_(f"{filevar['engine']} processing: '{destfilename}'"))
self.engines[filevar['engine']].process(filename=filename,
source=source,
true_destfilename=destfile,
true_destfilename=true_destfilename,
destfilename=destfilename,
destdir=self.destinations_dir,
variable=var,
index=idx,
rougail_variables_dict=self.rougail_variables_dict,
eosfunc=self.eosfunc,
)
self.process(true_destfilename,
destfilename,
filevar.get('mode'),
filevar.get('owner'),
filevar.get('group'),
)
destfilenames.append(destfilename)
return destfilenames
async def instance_files(self) -> None:
"""Run templatisation on all files
@ -339,6 +349,7 @@ class RougailBaseTemplate:
self.prepare_template(template,
templates_dir,
)
files_to_delete = []
for included in (True, False):
for service_obj in await self.config.option('services').list('all'):
service_name = await service_obj.option.description()
@ -374,14 +385,24 @@ class RougailBaseTemplate:
elif included is True:
continue
if fill['activate']:
self.instance_file(fill,
type_,
service_name,
service_type,
)
destfilenames = self.instance_file(fill,
type_,
service_name,
service_type,
)
if included and fill.get('included', 'no') == 'content':
files_to_delete.extend(destfilenames)
else:
self.log.debug(_("Instantiation of file '{filename}' disabled"))
self.log.debug(_(f"Instantiation of file '{fill['name']}' disabled"))
self.post_instance_service(service_name, service_type)
for filename in files_to_delete:
unlink(filename)
parent = filename
while True:
parent = dirname(parent)
if listdir(parent):
break
rmdir(parent)
self.post_instance()
if ori_dir is not None:
chdir(ori_dir)
@ -415,6 +436,11 @@ class RougailBaseTemplate:
): # pragma: no cover
pass
def process(self,
*args,
): # pragma: no cover
raise NotImplementedError(_('cannot processed'))
def post_instance(self): # pragma: no cover
pass

View File

@ -97,6 +97,7 @@ def process(filename: str,
destfilename: str,
destdir: str,
variable: Any,
index: int,
rougail_variables_dict: Dict,
eosfunc: Dict,
):
@ -110,6 +111,8 @@ def process(filename: str,
}
if variable is not None:
extra_context['rougail_variable'] = variable
if index is not None:
extra_context['rougail_index'] = index
cheetah_template = CheetahTemplate(filename,
source,
rougail_variables_dict,

View File

@ -119,6 +119,7 @@ def process(filename: str,
destfilename: str,
destdir: str,
variable: Any,
index: int,
rougail_variables_dict: Dict,
eosfunc: Dict,
):
@ -132,6 +133,8 @@ def process(filename: str,
}
if variable is not None:
extra_context['rougail_variable'] = variable
if index is not None:
extra_context['rougail_index'] = index
cheetah_template = CheetahTemplate(filename,
source,
rougail_variables_dict,

View File

@ -39,6 +39,7 @@ def process(filename: str,
destfilename: str,
destdir: str,
variable: Any,
index: int,
rougail_variables_dict: Dict,
eosfunc: Dict,
):
@ -48,11 +49,11 @@ def process(filename: str,
dir_name, template_name = filename.rsplit('/', 1)
if source is not None: # pragma: no cover
raise TemplateError(_('source is not supported for jinja2'))
rougail_variables_dict['rougail_variable'] = variable
var = {}
if variable is not None:
var = {'rougail_variable': variable}
else:
var = {}
var['rougail_variable'] = variable
if index is not None:
var['rougail_index'] = index
try:
# extra_context = {'normalize_family': normalize_family,
# eosfunc

View File

@ -21,13 +21,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""
from typing import Dict, Any
from os import makedirs, symlink
from os import makedirs, symlink, chmod
from os.path import dirname, isfile, join
from ipaddress import ip_network
from .base import RougailBaseTemplate
from ..i18n import _
from ..error import FileNotFound
from ..error import FileNotFound, TemplateError
ROUGAIL_IP_TEMPLATE = """[Service]
@ -41,10 +41,14 @@ IPAddressDeny=any
ROUGAIL_DEST = '/usr/local/lib'
ROUGAIL_GLOBAL_SYSTEMD_FILE = '/usr/lib/systemd/system'
ROUGAIL_DEST_FILE = '/tmpfiles.d/0rougail.conf'
LOCAL_DIR = ('/etc/', '/var/', '/srv/')
ROUGAIL_TMPL_TEMPLATE = f"""%def display(%%file, %%filename)
%if %%filename.startswith('/etc/') or %%filename.startswith('/var/') or %%filename.startswith('/srv/')
"""
TMP_LOCAL_DIR = (f"%%filename.startswith('{local_dir}')" for local_dir in LOCAL_DIR)
ROUGAIL_TMPL_TEMPLATE += '%if ' + ' or '.join(TMP_LOCAL_DIR)
ROUGAIL_TMPL_TEMPLATE += f"""
C %%filename %%file.mode %%file.owner %%file.group - {ROUGAIL_DEST}%%filename
%end if
%end def
@ -180,11 +184,29 @@ class RougailSystemdTemplate(RougailBaseTemplate):
destfilename=destfilename,
destdir=self.destinations_dir,
variable=self.ip_per_service,
index=None,
rougail_variables_dict=self.rougail_variables_dict,
eosfunc=self.eosfunc,
)
self.ip_per_service = None
def process(self,
filename: str,
destfilename: str,
mode: str,
owner: str,
group: str,
) -> None:
for local_dir in LOCAL_DIR:
if filename.startswith(local_dir):
return
if owner not in [None, self.rougailconfig['default_files_owner']]:
raise TemplateError(_(f'cannot change owner of file {destfilename}'))
if group not in [None, self.rougailconfig['default_files_group']]:
raise TemplateError(_(f'cannot change group of file {destfilename}'))
if mode not in [None, self.rougailconfig['default_files_mode']]:
chmod(destfilename, eval(f'0o{mode}'))
def post_instance(self):
destfilename = join(self.destinations_dir, ROUGAIL_DEST_FILE[1:])
makedirs(dirname(destfilename), exist_ok=True)
@ -195,6 +217,7 @@ class RougailSystemdTemplate(RougailBaseTemplate):
destfilename=destfilename,
destdir=self.destinations_dir,
variable=None,
index=None,
rougail_variables_dict=self.rougail_variables_dict,
eosfunc=self.eosfunc,
)

View File

@ -28,8 +28,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from json import dumps
from os.path import isfile
from .i18n import _
from .annotator import CONVERT_OPTION
from .objspace import RootRougailObject
from .error import DictConsistencyError
class BaseElt: # pylint: disable=R0903
@ -213,7 +215,11 @@ class Common:
self.populate_attrib()
self.populate_informations()
if hasattr(self.elt, 'provider'):
self.providers['provider:' + self.elt.provider] = self.dynamic_path
name = 'provider:' + self.elt.provider
if name in self.providers:
msg = f'provider {name} declare multiple time'
raise DictConsistencyError(msg, 79, self.elt.xmlfiles)
self.providers[name] = self.dynamic_path
return self.option_name
def populate_attrib(self):
@ -303,7 +309,7 @@ class Common:
return 'ParamSuffix()'
if param.type == 'index':
return 'ParamIndex()'
raise Exception(f'unknown type {param.type}') # pragma: no cover
raise Exception(_(f'unknown type {param.type}')) # pragma: no cover
@staticmethod
def build_option_param(param,

View File

@ -0,0 +1,13 @@
<?xml version='1.0' encoding='UTF-8'?>
<rougail version="0.10">
<variables>
<family name="general">
<variable name="float" type="float" description="Description" provider="float" hidden="True">
<value>0.527</value>
</variable>
<variable name="float_multi" type="float" description="Description" multi="True">
<value>0.527</value>
</variable>
</family>
</variables>
</rougail>

View File

@ -0,0 +1,12 @@
{
"rougail.general.float": {
"owner": "default",
"value": 0.527
},
"rougail.general.float_multi": {
"owner": "default",
"value": [
0.527
]
}
}

View File

@ -0,0 +1,6 @@
{
"rougail.general.float": 0.527,
"rougail.general.float_multi": [
0.527
]
}

View File

@ -0,0 +1,12 @@
{
"rougail.general.float": {
"owner": "default",
"value": 0.527
},
"rougail.general.float_multi": {
"owner": "default",
"value": [
0.527
]
}
}

View File

@ -0,0 +1,22 @@
from importlib.machinery import SourceFileLoader as _SourceFileLoader
from importlib.util import spec_from_loader as _spec_from_loader, module_from_spec as _module_from_spec
class func:
pass
_loader = _SourceFileLoader('func', 'tests/dictionaries/../eosfunc/test.py')
_spec = _spec_from_loader(_loader.name, _loader)
_func = _module_from_spec(_spec)
_loader.exec_module(_func)
for function in dir(_func):
if function.startswith('_'):
continue
setattr(func, function, getattr(_func, function))
try:
from tiramisu3 import *
except:
from tiramisu import *
option_3 = FloatOption(name="float", doc="Description", default=0.527, properties=frozenset({"hidden", "mandatory", "normal"}))
option_4 = FloatOption(name="float_multi", doc="Description", multi=True, default=[0.527], default_multi=0.527, properties=frozenset({"mandatory", "normal"}))
option_2 = OptionDescription(name="general", doc="general", children=[option_3, option_4], properties=frozenset({"normal"}))
option_1 = OptionDescription(name="rougail", doc="rougail", children=[option_2])
option_0 = OptionDescription(name="baseoption", doc="baseoption", children=[option_1])
option_0.impl_set_information('provider:float', "rougail.general.float")

View File

@ -15,7 +15,7 @@ test_ok = {f for f in listdir(template_dirs) if not f.startswith('_') and isdir(
test_ok -= excludes
test_ok = list(test_ok)
test_ok.sort()
#test_ok = ['20override']
#test_ok = ['01base_file_include_content']
@fixture(scope="module", params=test_ok)
@ -79,7 +79,7 @@ async def test_dictionary(test_dir):
[],
list_results,
)
assert list_templates == list_results
assert list_templates == list_results, f'error with {test_dir}:'
for result in list_results:
template_file = join(dest_dir, result)
assert islink(template_file) == islink(join(test_dir, 'result', result))