jinja and calculations
This commit is contained in:
parent
1da10b7970
commit
91112a905a
6 changed files with 267 additions and 105 deletions
|
|
@ -8,9 +8,6 @@
|
||||||
Rougail
|
Rougail
|
||||||
===========
|
===========
|
||||||
|
|
||||||
.. todolist::
|
|
||||||
|
|
||||||
|
|
||||||
.. todo:: définir les termes suivants
|
.. todo:: définir les termes suivants
|
||||||
|
|
||||||
family.rst:25: WARNING: label non défini: 'convention on variable names'
|
family.rst:25: WARNING: label non défini: 'convention on variable names'
|
||||||
|
|
|
||||||
154
docs/tutorial/calculation.rst
Normal file
154
docs/tutorial/calculation.rst
Normal file
|
|
@ -0,0 +1,154 @@
|
||||||
|
Calculation with a jinja type
|
||||||
|
===============================
|
||||||
|
|
||||||
|
.. objectives:: Objectives
|
||||||
|
|
||||||
|
In this section we will learn how to create new ways of calculation.
|
||||||
|
|
||||||
|
|
||||||
|
Up to now, our only way of dynamically (that is, during the runtime) calculating
|
||||||
|
a value is to point on another variable's value. But this is not the only way.
|
||||||
|
|
||||||
|
A jinja calculated variable's hidden property
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
We can hide or disable some variables or families with other techniques than
|
||||||
|
pointing on a variable's value.
|
||||||
|
|
||||||
|
Let's reason on the previous HTTPS proxy configuration's manual mode:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
manual:
|
||||||
|
|
||||||
|
use_for_https:
|
||||||
|
description: Also use this proxy for HTTPS
|
||||||
|
default: true
|
||||||
|
|
||||||
|
https_proxy:
|
||||||
|
type: family
|
||||||
|
description: HTTPS Proxy
|
||||||
|
hidden:
|
||||||
|
variable: manual.use_for_https
|
||||||
|
|
||||||
|
|
||||||
|
This is extracted from the proxy's manual configuration we discussed before.
|
||||||
|
|
||||||
|
We see here that there is an `https_proxy` family that is going to be hidden
|
||||||
|
depending on the value of another variable:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
https_proxy:
|
||||||
|
type: family
|
||||||
|
hidden:
|
||||||
|
variable: manual.use_for_https
|
||||||
|
|
||||||
|
Now we could write it like that:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
manual:
|
||||||
|
|
||||||
|
use_for_https:
|
||||||
|
description: Also use this proxy for HTTPS
|
||||||
|
default: true
|
||||||
|
|
||||||
|
https_proxy:
|
||||||
|
description: HTTPS Proxy
|
||||||
|
type: family
|
||||||
|
hidden:
|
||||||
|
type: jinja
|
||||||
|
jinja: |
|
||||||
|
{% if rougail.manual.use_for_https %}
|
||||||
|
the HTTPS Proxy family is hidden
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
Yes, it's done in a more complicated (but more powerful) way.
|
||||||
|
Let's explain this a little:
|
||||||
|
|
||||||
|
We have replaced this simple hidden property declaration:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
hidden:
|
||||||
|
variable: manual.use_for_https
|
||||||
|
|
||||||
|
by this (more complicated) hidden property declaration:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
hidden:
|
||||||
|
type: jinja
|
||||||
|
jinja: |
|
||||||
|
{% if rougail.manual.use_for_https %}
|
||||||
|
the HTTPS Proxy family is hidden
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
The fact is that it has same result, but here we have more possibilities.
|
||||||
|
The hidden process is done by a calculation.
|
||||||
|
|
||||||
|
Another jinja calculation type sample
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
We can now hide or disable some variables or families with other techniques than
|
||||||
|
pointing on a variable's value.
|
||||||
|
|
||||||
|
Let's reason upon the proxy's manual configuration we discussed before.
|
||||||
|
We have the :file:`dict/02-proxy_manual.yml` structure file:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: the :file:`structfile/02-proxy_manual.yml` file
|
||||||
|
|
||||||
|
---
|
||||||
|
version: '1.1'
|
||||||
|
manual:
|
||||||
|
description: Manual proxy configuration
|
||||||
|
type: family
|
||||||
|
disabled:
|
||||||
|
type: jinja
|
||||||
|
jinja: |
|
||||||
|
{% if rougail.proxy.proxy_mode != 'Manual proxy configuration' %}
|
||||||
|
the proxy mode is not manual
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
.. questions:: Question
|
||||||
|
|
||||||
|
**question**: OK then. What happens when you select the "Manual proxy configuration"?
|
||||||
|
|
||||||
|
Here if the user selects the "Manual proxy configuration" proxy mode,
|
||||||
|
the the `manual` family will be disabled. This is what the jinja code says.
|
||||||
|
Let's explain it more precisely.
|
||||||
|
|
||||||
|
|
||||||
|
.. note:: The "the proxy mode is not manual" output is be used in the log outputs
|
||||||
|
for example while
|
||||||
|
|
||||||
|
Why Jinja?
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. questions:: What about this `Jinja` type?
|
||||||
|
|
||||||
|
If the :term:`Jinja` template returns some text, then the family will be `disabled`. Otherwise it is accessible.
|
||||||
|
Deactivating a family means that we will not be able to access it as well as the variables or families included in this family.
|
||||||
|
|
||||||
|
.. note:: If the Jinja template does not return any text, the variable will be **enabled**.
|
||||||
|
Here we are using the Jinja condition statement.
|
||||||
|
|
||||||
|
.. glossary::
|
||||||
|
|
||||||
|
Jinja
|
||||||
|
|
||||||
|
`Jinja <https://jinja.palletsprojects.com>`_ is a template engine.
|
||||||
|
we are using Jinja in a classical way, that is, Jinja allows us to handle different cases,
|
||||||
|
for example with the `if` statement.
|
||||||
|
|
||||||
|
|
||||||
|
.. todo:: montrer aussi ici des exemples de calculs de valeurs variables, ce qui est un des usages principaux de jinja
|
||||||
|
|
||||||
|
.. keypoints:: Key points
|
||||||
|
|
||||||
|
Here we have come to the possibility of making any kind of calculations based on the state of the :term:`configuration`.
|
||||||
|
This is an important feature to manage the stateful aspect of a configuration.
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,37 +5,40 @@ A dynamic family
|
||||||
|
|
||||||
.. objectives:: Objectives
|
.. objectives:: Objectives
|
||||||
|
|
||||||
In this section we will learn how to create a dynamically created family.
|
In this section we will learn how to create a dynamically built family.
|
||||||
|
|
||||||
.. prerequisites:: Reminder
|
.. prerequisites:: Reminder
|
||||||
|
|
||||||
We handled the HTTPS mode in the previous section. But there's more.
|
We handled the HTTPS mode in the previous section. But there's more modes to handle.
|
||||||
Let's have a look at the firefox's configuration page:
|
Let's turn back to the firefox's configuration page:
|
||||||
|
|
||||||
.. image:: images/soksv5.png
|
.. image:: images/soksv5.png
|
||||||
|
|
||||||
We see that we need to handle the SOCKS configuration in addition to the HTTPs configuration.
|
We see that we need to handle the SOCKS configuration in addition to the HTTPS configuration.
|
||||||
Moreover, we can see that these two group of variables are very similar:
|
Moreover, we can see that these two groups of variables are similar in the structure:
|
||||||
they both have a host and a port.
|
they both have a host and a port.
|
||||||
|
|
||||||
Creating a generic family
|
Creating a generic family
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
|
||||||
There are two proxies that are to be configured :
|
There are two proxies that are to be configured :
|
||||||
|
|
||||||
- the HTTP proxy
|
- the HTTPS proxy
|
||||||
- the SOCKS proxy
|
- the SOCKS proxy
|
||||||
|
|
||||||
It's not the place here to describe what the HTTP and SOCKS protocols are.
|
As they have the same structure, would it be possible to define the two of them
|
||||||
The interesting point here is that they are very similar in our firefox's configuration.
|
in one shot?
|
||||||
|
|
||||||
With Rougail, we can create some kind of a model of family.
|
.. note:: It's not the place here to describe what the HTTP and SOCKS protocols are.
|
||||||
we can use a generic family declaration mode in this use case.
|
The interesting point here is that they are very similar in our firefox's
|
||||||
We call this genericity family a "dynamic creation" because as we will see below,
|
configuration and that we can do batch processing.
|
||||||
these families exist at the very moment we define their identifiers.
|
|
||||||
|
|
||||||
what we could do with our current knowledge:
|
With Rougail, it is possible to create some kind of a model of family.
|
||||||
|
Kind of a generic family declaration.
|
||||||
|
We call this generic family creation process a "dynamic creation" because as we will see below,
|
||||||
|
these families exist at the very moment we define their **identifiers**.
|
||||||
|
|
||||||
|
First, here is what we need to make (without identifiers):
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
|
@ -63,14 +66,24 @@ what we could do with our current knowledge:
|
||||||
description: SOCKS Port
|
description: SOCKS Port
|
||||||
...
|
...
|
||||||
|
|
||||||
With Rougail we have the ability to declare our families this way:
|
Now with identifiers, we have the ability to declare our families this way:
|
||||||
|
|
||||||
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_037/firefox/20-manual.yml
|
.. code-block:: yaml
|
||||||
:language: yaml
|
|
||||||
:caption: firefox/20-proxy.yml
|
|
||||||
|
|
||||||
What is an identifier?
|
"{{ identifier }}_proxy":
|
||||||
-------------------------
|
description: "{{ identifier }} Proxy"
|
||||||
|
dynamic:
|
||||||
|
- HTTPS
|
||||||
|
- SOCKS
|
||||||
|
|
||||||
|
address:
|
||||||
|
description: "{{ identifier }} address"
|
||||||
|
|
||||||
|
port:
|
||||||
|
description: "{{ identifier }} port"
|
||||||
|
|
||||||
|
What is exactly an identifier?
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
If you know a YAML declaration tool named Ansible,
|
If you know a YAML declaration tool named Ansible,
|
||||||
the variable used to iterate over multiple values in a task is called an **`item`**.
|
the variable used to iterate over multiple values in a task is called an **`item`**.
|
||||||
|
|
@ -123,8 +136,6 @@ Here is the syntax we are using that allows the declaration of multiple families
|
||||||
|
|
||||||
This identifier is a parameter that enables us to create two families named `https_proxy` and `socks_proxy`:
|
This identifier is a parameter that enables us to create two families named `https_proxy` and `socks_proxy`:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
.. code-block:: yaml
|
||||||
|
|
||||||
https_proxy:
|
https_proxy:
|
||||||
|
|
@ -136,15 +147,15 @@ This identifier is a parameter that enables us to create two families named `htt
|
||||||
.. note:: The declaration syntax used is the :term:`Jinja <jinja>` templating syntax,
|
.. note:: The declaration syntax used is the :term:`Jinja <jinja>` templating syntax,
|
||||||
Jinja which is widely used in python.
|
Jinja which is widely used in python.
|
||||||
|
|
||||||
.. attention:: Be careful when choosing your identifiers items: the family
|
.. attention:: Be careful when choosing your identifiers items: pay attention that the family
|
||||||
that will be dynamically created shall not exist already.
|
that will be dynamically created has not been declared before in some other
|
||||||
|
YAML structure file.
|
||||||
|
|
||||||
If you define a dynamic family with the `https` item that will
|
If you define a dynamic family with the `https` item that will
|
||||||
build a `https_proxy` family and if this familiy already exist,
|
build a `https_proxy` family and if this familiy already exists,
|
||||||
then rougail will raise a warning.
|
then rougail will raise a family/variable override warning.
|
||||||
|
|
||||||
|
When we launch the rougail command line, we can have a look at the concrete families and variables that have appear:
|
||||||
Besides, when we launch the rougail command line, we can have a look at the concrete variables here:
|
|
||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
|
|
@ -172,15 +183,76 @@ We can see that the dynamic family has created:
|
||||||
- an `HTTPS Proxy` family
|
- an `HTTPS Proxy` family
|
||||||
- a `SOCKS Proxy` family
|
- a `SOCKS Proxy` family
|
||||||
|
|
||||||
as we wanted.
|
as we wanted, containing an address and a port.
|
||||||
|
|
||||||
|
|
||||||
A conditional hidden familiy
|
A conditional hidden familiy
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
Yes we have gained in genericity but we have lost in readability, you would say.
|
Here is the final YAML version of the HTTPS and SOCKS proxy families:
|
||||||
But we haven't just been generic. We now have the ability to create conditional hidden family
|
|
||||||
(and not only conditionnal hidden variables like we did earlier).
|
|
||||||
|
|
||||||
|
|
||||||
|
We have added:
|
||||||
|
|
||||||
|
- a conditional hidden family property
|
||||||
|
- a default value
|
||||||
|
|
||||||
|
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_037/firefox/20-manual.yml
|
||||||
|
:language: yaml
|
||||||
|
:caption: firefox/20-proxy.yml
|
||||||
|
|
||||||
|
..
|
||||||
|
---
|
||||||
|
manual:
|
||||||
|
|
||||||
|
use_for_https:
|
||||||
|
description: Also use this proxy for HTTPS
|
||||||
|
default: true
|
||||||
|
|
||||||
|
"{{ identifier }}_proxy":
|
||||||
|
description: "{{ identifier }} Proxy"
|
||||||
|
dynamic:
|
||||||
|
- HTTPS
|
||||||
|
- SOCKS
|
||||||
|
hidden:
|
||||||
|
variable: manual.use_for_https
|
||||||
|
|
||||||
|
address:
|
||||||
|
description: "{{ identifier }} address"
|
||||||
|
default:
|
||||||
|
variable: manual.http_proxy.address
|
||||||
|
|
||||||
|
port:
|
||||||
|
description: "{{ identifier }} port"
|
||||||
|
default:
|
||||||
|
variable: manual.http_proxy.port
|
||||||
|
|
||||||
|
|
||||||
|
The conditional property is this one:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
hidden:
|
||||||
|
variable: manual.use_for_https
|
||||||
|
|
||||||
|
it uses `use_for_https` variable:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
|
||||||
|
use_for_https:
|
||||||
|
description: Also use this proxy for HTTPS
|
||||||
|
default: true
|
||||||
|
|
||||||
|
|
||||||
|
.. keypoints:: Key points
|
||||||
|
|
||||||
|
- We now know what a generic family is, with its identifier.
|
||||||
|
- we now how to create default values for a variable that is calculated
|
||||||
|
because it retrieves the value of another variable.
|
||||||
|
- we know how to hide conditionaly a family with the same mechanism,
|
||||||
|
that is a calculated value. It is calculated because there is a dependancy
|
||||||
|
over another variable.
|
||||||
|
|
||||||
|
We will see other types of calculation in the next section.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,9 @@ The values entered by the user have to be
|
||||||
|
|
||||||
- validated
|
- validated
|
||||||
- consitent
|
- consitent
|
||||||
|
- conformity
|
||||||
|
|
||||||
|
.. todo:: explain the congruent term. or another term? compliance ? accordance ? conformity ?
|
||||||
|
|
||||||
At first glance we can see that we have a selection of five configuration options values that we need to fill in, they are highlighted here in this screenshot:
|
At first glance we can see that we have a selection of five configuration options values that we need to fill in, they are highlighted here in this screenshot:
|
||||||
|
|
||||||
|
|
@ -45,4 +48,5 @@ At first glance we can see that we have a selection of five configuration option
|
||||||
disabled
|
disabled
|
||||||
boolean
|
boolean
|
||||||
dynfam
|
dynfam
|
||||||
|
calculation
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,9 @@ In our firefox use case, the real type of the `proxy_mode` variable will be now
|
||||||
choice type
|
choice type
|
||||||
|
|
||||||
A choice type variable is a variable where the content is constrained by a list
|
A choice type variable is a variable where the content is constrained by a list
|
||||||
|
|
||||||
|
When a variable's setting is "choice" (`type: choice`), it means that
|
||||||
|
there is a list of available values that can be selected.
|
||||||
|
|
||||||
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_013/firefox/00-proxy.yml
|
.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_013/firefox/00-proxy.yml
|
||||||
:linenos:
|
:linenos:
|
||||||
|
|
@ -311,12 +314,6 @@ We have the list of the possible (authorized) values:
|
||||||
- `Manual proxy configuration`
|
- `Manual proxy configuration`
|
||||||
- `Automatic proxy configuration URL`
|
- `Automatic proxy configuration URL`
|
||||||
|
|
||||||
.. glossary::
|
|
||||||
|
|
||||||
choice type
|
|
||||||
|
|
||||||
The `proxy_mode` setting is "choice" (`type: choice`) means that
|
|
||||||
there is a list of available values that can be selected.
|
|
||||||
|
|
||||||
.. keypoints:: Key points progress
|
.. keypoints:: Key points progress
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,68 +1,6 @@
|
||||||
|
|
||||||
:orphan:
|
:orphan:
|
||||||
|
|
||||||
The Firefox proxy: the manual configuration
|
|
||||||
=============================================
|
|
||||||
|
|
||||||
.. objectives:: Objectives
|
|
||||||
|
|
||||||
We will learn how to: FIXME
|
|
||||||
|
|
||||||
|
|
||||||
.. prerequisites:: Reminders
|
|
||||||
|
|
||||||
FIXME
|
|
||||||
|
|
||||||
The manual mode
|
|
||||||
------------------
|
|
||||||
|
|
||||||
.. questions:: Question
|
|
||||||
|
|
||||||
**question**: OK then. What happens when you select the "Manual proxy configuration"?
|
|
||||||
|
|
||||||
A good configuration design is to place all the proxy's manual configuration in a :term:`family`.
|
|
||||||
Let's create the :file:`dict/02-proxy_manual.yml` dictionary:
|
|
||||||
|
|
||||||
.. code-block:: yaml
|
|
||||||
:caption: the the :file:`dict/02-proxy_manual.yml` file
|
|
||||||
|
|
||||||
---
|
|
||||||
version: '1.1'
|
|
||||||
proxy:
|
|
||||||
manual:
|
|
||||||
description: Manual proxy configuration
|
|
||||||
type: family
|
|
||||||
disabled:
|
|
||||||
type: jinja
|
|
||||||
jinja: |
|
|
||||||
{% if rougail.proxy.proxy_mode != 'Manual proxy configuration' %}
|
|
||||||
the proxy mode is not manual
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
Well, if the user selects the "Manual proxy configuration" proxy mode, we want to see a new subfamily (that is, a new set of configuration variables) called `manual` to appear (which is disabled).
|
|
||||||
|
|
||||||
.. glossary::
|
|
||||||
|
|
||||||
subfamily
|
|
||||||
|
|
||||||
A subfamily is just a family inside a family, a family that contains a family.
|
|
||||||
|
|
||||||
.. questions:: What about this `Jinja` type?
|
|
||||||
|
|
||||||
If the :term:`Jinja` template returns some text, then the family will be `disabled`. Otherwise it is accessible.
|
|
||||||
Deactivating a family means that we will not be able to access it as well as the variables or families included in this family.
|
|
||||||
|
|
||||||
.. note:: If the Jinja template does not return any text, the variable will be **enabled**.
|
|
||||||
Here we are using the Jinja condition statement.
|
|
||||||
|
|
||||||
.. glossary::
|
|
||||||
|
|
||||||
Jinja
|
|
||||||
|
|
||||||
`Jinja <https://jinja.palletsprojects.com>`_ is a template engine.
|
|
||||||
we are using Jinja in a classical way, that is, Jinja allows us to handle different cases,
|
|
||||||
for example with the `if` statement.
|
|
||||||
|
|
||||||
The HTTP proxy configuration
|
The HTTP proxy configuration
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue