feat: user_datas/output

This commit is contained in:
egarette@silique.fr 2025-10-27 06:50:10 +01:00
parent 2eeedd70e2
commit 9d856f9de0
11 changed files with 205 additions and 39 deletions

View file

@ -67,6 +67,13 @@ Explained differently, Rougail allows you to easily implement an integration of
Value checks <check>
condition
.. toctree::
:titlesonly:
:caption: Load values from user datas
user_datas/index
configuration
.. toctree::
:titlesonly:
:caption: The library

View file

@ -31,7 +31,7 @@ Then, let's create the :term:`Tiramisu` objects via the following :file:`script.
from rougail import Rougail, RougailConfig
RougailConfig['main_structural_directories'] = ['dict']
RougailConfig['main_structural_directories'] = ['dict/']
RougailConfig['extra_namespaces']['example'] = ['extras/']
rougail = Rougail()
config = rougail.get_config()

View file

@ -36,14 +36,14 @@ We can display configuration directly in the console:
from rougail.output_console import RougailOutputConsole
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.output"] = "console"
rougail = Rougail(RougailConfig)
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputConsole(config).print()
FIXME display console!
.. FIXME display console!
console.key_is_description
''''''''''''''''''''''''''
@ -57,15 +57,15 @@ By default, the key is the variable description, if you prefer have only the pat
from rougail.output_json import RougailOutputJson
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["step.output"] = "json"
rougail = Rougail(RougailConfig)
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.output"] = "console"
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputJson(config).print()
FIXME display console!
.. FIXME display console!
console.show_secrets
''''''''''''''''''''
@ -79,14 +79,15 @@ Secrets are remplace by "*******", to display real secrets:
from rougail.output_console import RougailOutputConsole
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.output"] = "console"
RougailConfig["console.show_secrets"] = True
rougail = Rougail(RougailConfig)
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputConsole(config).print()
FIXME display console!
.. FIXME display console!
console.mandatory
'''''''''''''''''
@ -100,14 +101,15 @@ Before display configuration, mandatories variables are check. If you don't want
from rougail.output_console import RougailOutputConsole
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.output"] = "console"
RougailConfig["console.mandatory"] = False
rougail = Rougail(RougailConfig)
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputConsole(config).print()
FIXME display console!
.. FIXME display console!
JSON
----
@ -121,9 +123,9 @@ Your script can return a JSON object:
from rougail.output_console import RougailOutputConsole
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["console.mandatory"] = False
rougail = Rougail(RougailConfig)
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.output"] = "json"
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputConsole(config).print()
@ -132,7 +134,7 @@ Let's try this script:
.. code-block:: bash
$ LC_ALL=C python script.py
$ python script.py
{
"my_variable": "my value",
"my_boolean_variable": true,
@ -140,5 +142,128 @@ Let's try this script:
"my_secret_variable": "MyVeryStrongPassword"
}
ANSIBLE
-------
.. doc,ansible
It's possible to use Ansible has a output format.
The goal is here to use Ansible has a dynamic user's inventories structure manage by Rougail.
This output needs an extra namespace, named, by default, "hosts". This namespace define your hosts and groups.
Let's create a single group "my_group" with one host "group1.net":
.. code-block:: yaml
:caption: the :file:`hosts/00-hosts.yml` file content
%YAML 1.2
---
version: 1.1
hostnames:
my_group:
hosts:
type: domainname
default:
- group1.net
...
Now we can generate Ansible inventory:
.. code-block:: python
:caption: the :file:`script.py` file content
#!/bin/env python
from rougail import Rougail, RougailConfig
from rougail.output_ansible import RougailOutputAnsible
RougailConfig["main_namespace"] = "main"
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig['extra_namespaces']['hosts'] = ['hosts/']
RougailConfig["step.output"] = "ansible"
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputAnsible(config).print()
We will retrieved all ours variables associate to this group with all variables inside the namespace `main`:
.. code-block:: bash
$ python script.py
{
"_meta": {
"hostvars": {
"group1.net": {
"ansible_host": "group1.net",
"main": {
"my_variable": "my value",
"my_boolean_variable": true,
"my_integer_variable": 1,
"my_secret_variable": "MyVeryStrongPassword"
}
}
}
},
"my_group": {
"hosts": [
"group1.net"
]
}
}
We can now use our script as an inventory source in Ansible:
.. code-block:: bash
$ chmod +x script.py
$ ansible-inventory -i script.py --list
{
"_meta": {
"hostvars": {
"group1.net": {
"ansible_host": "group1.net",
"main": {
"my_boolean_variable": true,
"my_integer_variable": 1,
"my_secret_variable": "MyVeryStrongPassword",
"my_variable": "my value"
}
}
}
},
"all": {
"children": [
"ungrouped",
"my_group"
]
},
"my_group": {
"hosts": [
"group1.net"
]
}
}
DOC
---
We can generate the documentation of all the Rougail variable:
.. code-block:: python
:caption: the :file:`script.py` file content
from rougail import Rougail, RougailConfig
from rougail.output_doc import RougailOutputDoc
RougailConfig["main_namespace"] = "main"
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.output"] = "doc"
rougail = Rougail()
config = rougail.run()
config.property.read_only()
RougailOutputDoc(config).print()
.. FIXME : display

View file

@ -44,7 +44,7 @@ Create our first script to walk through our config:
from rougail import Rougail, RougailConfig
RougailConfig['main_structural_directories'] = ['dist']
RougailConfig['main_structural_directories'] = ["dist/"]
rougail = Rougail()
config = rougail.run()
@ -85,7 +85,7 @@ Let us distinguish the variables of the families
from rougail import Rougail, RougailConfig
RougailConfig['main_structural_directories'] = ['dist']
RougailConfig['main_structural_directories'] = ["dist/"]
rougail = Rougail()
config = rougail.run()
@ -128,7 +128,7 @@ Or if we want more precision:
from rougail import Rougail, RougailConfig
RougailConfig['main_structural_directories'] = ['dist']
RougailConfig['main_structural_directories'] = ["dist/"]
rougail = Rougail()
config = rougail.run()
@ -185,7 +185,7 @@ If we want to walk to get variables and their values:
from rougail import Rougail, RougailConfig
RougailConfig['main_structural_directories'] = ['dist']
RougailConfig['main_structural_directories'] = ["dist/"]
rougail = Rougail()
config = rougail.run()
@ -219,7 +219,7 @@ Some variables are mandatories but hasn't value. Here we set alls values:
:caption: the :file:`script.py` file content
from rougail import Rougail, RougailConfig
RougailConfig['main_structural_directories'] = ['dist']
RougailConfig['main_structural_directories'] = ["dist/"]
rougail = Rougail()
config = rougail.run()

View file

@ -1,7 +1,7 @@
Load user datas
===============
User datas are values setup but user for configuration variables.
User datas are values setup by user for configuration variables.
There is differents types of user datas for differents sources types.
@ -38,7 +38,7 @@ Here is the first script which is load this file:
from rougail import Rougail, RougailConfig
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
rougail = Rougail()
config = rougail.run()
print(config.value.get())
@ -75,7 +75,7 @@ Here is the script which is load user data from the YAML file:
from rougail.user_data_yaml import RougailUserDataYaml
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["yaml"]
RougailConfig["yaml.filename"] = ["dist.yml"]
rougail = Rougail()
@ -109,7 +109,7 @@ This is why the `yaml.file_with_secrets` parameter allows you to define whether
from rougail.user_data_yaml import RougailUserDataYaml
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["yaml"]
RougailConfig["yaml.filename"] = ["dist.yml"]
RougailConfig["yaml.file_with_secrets"] = "none"
@ -151,7 +151,7 @@ Here is the script:
from rougail.user_data_environment import RougailUserDataEnvironment
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["environment"]
rougail = Rougail()
config = rougail.run()
@ -178,7 +178,7 @@ We can redefine the prefix with `environment.default_environment_name` (prefix i
from rougail.user_data_environment import RougailUserDataEnvironment
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["environment"]
RougailConfig["environment.default_environment_name"] = "EX"
rougail = Rougail()
@ -197,7 +197,7 @@ Let's execute `script.py`:
env EX_MY_VARIABLE="a new value" EX_MY_BOOLEAN_VARIABLE="False" EX_MY_INTEGER_VARIABLE=10 EX_MY_SECRET_VARIABLE="MyVeryStrongPassword" python script.py
{<TiramisuOption path="my_variable">: 'a new value', <TiramisuOption path="my_boolean_variable">: False, <TiramisuOption path="my_integer_variable">: 10, <TiramisuOption path="my_secret_variable">: 'MyVeryStrongPassword'}
If you define a `main_namespace` or `extra_namespace`, the `environment.default_environment_name` is automaticly define with the name of the namespace in uppercase. And the separator is no more "_" but ".":
If you define a `main_namespace` or `extra_namespaces`, the `environment.default_environment_name` is automaticly define with the name of the namespace in uppercase. And the separator is no more "_" but ".":
.. code-block:: python
:caption: the :file:`script.py` file content
@ -206,7 +206,7 @@ If you define a `main_namespace` or `extra_namespace`, the `environment.default_
from rougail.user_data_environment import RougailUserDataEnvironment
RougailConfig["main_namespace"] = "main"
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["environment"]
rougail = Rougail()
config = rougail.run()
@ -234,7 +234,7 @@ This is why the `environment.with_secrets` parameter allows you to reject secret
from rougail.user_data_environment import RougailUserDataEnvironment
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["environment"]
RougailConfig["environment.with_secrets"] = False
rougail = Rougail()
@ -265,7 +265,7 @@ Value can be define directly with command line arguments:
from rougail.user_data_commandline import RougailUserDataCommandline
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["commandline"]
rougail = Rougail()
config = rougail.run()
@ -320,7 +320,7 @@ You can combine user datas, for example if you want to load datas from environme
from rougail.user_data_commandline import RougailUserDataCommandline
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["environment", "commandline"]
rougail = Rougail()
config = rougail.run()
@ -359,7 +359,7 @@ Recreate a script with environnement variable support which is display the retur
from rougail.user_data_environment import RougailUserDataEnvironment
RougailConfig["main_namespace"] = None
RougailConfig["main_structural_directories"] = ["dist"]
RougailConfig["main_structural_directories"] = ["dist/"]
RougailConfig["step.user_data"] = ["environment"]
RougailConfig["environment.with_secrets"] = False
rougail = Rougail()
@ -373,7 +373,7 @@ Recreate a script with environnement variable support which is display the retur
Try to load the value an unknown variable:
.. code-block:: bash
$ LC_ALL=C env ROUGAIL_UNKNOWN_VARIABLE="a value" python script.py
$ env ROUGAIL_UNKNOWN_VARIABLE="a value" python script.py
{'errors': [], 'warnings': ['variable or family "unknown_variable" does not exist, it will be ignored when loading from environment variable']}
As you can see, a warnings is return.
@ -381,13 +381,13 @@ As you can see, a warnings is return.
Try to load the value of an hidden variable:
.. code-block:: bash
$ LC_ALL=C env ROUGAIL_MY_HIDDEN_VARIABLE="a value" python script.py
$ env ROUGAIL_MY_HIDDEN_VARIABLE="a value" python script.py
{'errors': [], 'warnings': ['variable "my_hidden_variable" (My hidden variable) is hidden, it will be ignored when loading from environment variable']}
Finally if a try to change the value of a secret, which is not allowed:
.. code-block:: bash
$ LC_ALL=C env ROUGAIL_MY_SECRET_VARIABLE="MyVeryStrongPassword" python script.py
$ env ROUGAIL_MY_SECRET_VARIABLE="MyVeryStrongPassword" python script.py
{'errors': ['the variable "my_secret_variable" contains secrets and should not be defined in environment variable'], 'warnings': []}
An error is generate.

View file

@ -0,0 +1,3 @@
Load user datas from Bitwarden server
=====================================

View file

@ -0,0 +1,3 @@
Load user datas from commandline parser
=======================================

View file

@ -0,0 +1,3 @@
Load user datas from a environment variable
===========================================

19
docs/user_datas/index.rst Normal file
View file

@ -0,0 +1,19 @@
`Rougail`'s user datas description
==================================
Rougail is a collections of subproject to adjust functionalities to your needs.
User datas is one of category of subjects. The goal is to setup variable with value define by user.
There is differents user datas types:
.. toctree::
:titlesonly:
:caption: Use library
yaml
environment
commandline
ansible
bitwarden
questionary

View file

@ -0,0 +1,3 @@
Load user datas from a command line interface
=============================================

3
docs/user_datas/yaml.rst Normal file
View file

@ -0,0 +1,3 @@
Load user datas from a YAML file
================================