The `manual` family
====================

.. objectives:: Objectives

   We will learn how to:

   - create a :term:`family`
   - gather :term:`variable`\ s into a :term:`family`
   - make a variable within a variable, which turns this variable container into being a family

.. prerequisites:: Reminders

    - We have an idea of what a :term:`structure description file<structure file>` is
    - We have a folder named :file:`firefox` and we are putting all the structure description files into it


.. type-along:: So we have this choice type variable in the structure file

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_013/firefox/00-proxy.yml
   :linenos:
   :language: yaml
   :caption: The `proxy_mode` choice type variable in the :file:`firefox/00-proxy.yml` structure file

..
    ---
    proxy_mode:
      description: Configure Proxy Access to the Internet
      type: choice
      choices:
        - No proxy
        - Auto-detect proxy settings for this network
        - Use system proxy settings
        - Manual proxy configuration
        - Automatic proxy configuration URL
      default: No proxy

.. We're gonna put it in a :term:`family`.

.. note:: The variables, families, etc. will be created in several files for educational purposes.
          Here we made a :file:`firefox/00-proxy.yml` structure file and we're gonna make 
          a new structure file named :file:`firefox/10-manual.yml`
          We could of course have put everything in one file, we decided to separate the files for reasons of ordering and clarity

So we have now a `proxy_mode` variable.

.. confval:: proxy_mode
   :type: `choice`
   :default: No proxy

   This is a setting that controls the proxy's type

A family named `manual`
-------------------------

Let's create a family named `manual`

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_020/firefox/10-manual.yml
   :language: yaml
   :caption: A family structure file description named `manual` in a :file:`firefox/10-manual.yml` file
   :name: RougailManualFamily

..
    ---
    manual:
      description: Manual proxy configuration
      type: family

We can see that we have defined a :term:`family` here, and this family is *empty*
(that is the family which is a container variable contains no variable yet).

.. admonition:: If a family is empty

    We need to specify the :term:`family` type here because if we don't,
    the Rougail's type engine will infer it by default as a :term:`variable`.

    It's because we don't have set any :term:`variable` inside. If we have a variable inside of a family, 
    we make a YAML block (that is, we indent) and the Rougail's type inference engine will implicitely infer it as a family.

.. type-along::  A family inside a family

Creating a family hierarchy is very easy, here is an example:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_021/firefox/10-manual.yml
   :language: yaml
   :caption: A rougail structure description file with a hierarchy.
   :name: RougailFirstFamilyHierarchy

..
    ---
    manual:
      description: Manual proxy configuration
      type: family

      http_proxy:
        description: HTTP Proxy
        type: family

Here the `http_proxy` family lives inside the `manual` family.

Putting a variable inside of a family or a sub family
----------------------------------------------------------

Let's create a variable in its family.
The type of this variable is a `choice` type:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_024/firefox/10-manual.yml
   :language: yaml
   :caption: An `address` variable in the `http_proxy` family
   :name: RougailVariableInSubFamily

..
    ---
    manual:
      description: Manual proxy configuration
      type: family

      http_proxy:
        description: HTTP Proxy
        type: family

        address:
          description: HTTP address
          type: domainname

The :term:`operator` can now then set :term:`a value <value>` to the :confval:`address` variable

So we have now an `address` variable.

.. confval:: address
   :type: `domainname`
   :default: None

   This is the HTTP address of the proxy

.. note:: We encountered here a new type of variable there: the `domainname` type


Assigning a user value
------------------------------------

Now we need to set a value ​​for the :confval:`address` variable, 
otherwise we will get an error if we try to access this variable:

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_024/config/01/output_rw.html
   :class: error-box

.. 
    <pre>🛑 ERRORS
    <span style="color: #ff0000">┣━━ </span>The following variables are mandatory but have no value:
    <span style="color: #ff0000">┗━━ </span>  - manual.http_proxy.address (HTTP address)
    </pre>

Because this variable is mandatory. 

.. glossary::

   mandatory
   
       A variable is defined as mandatory if it **must** have a value.

.. type-along:: user files are where the user values lives

And we need to set the values ​​in separate files too, called `user files`.

.. glossary::

   user file
   
       A user file is a file where users can set values, called user values -- 
       that is variable's values that have been set by an :term:`operator`\ . 

Let's set user values in user files

Here is a user file sample: 

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_024/config/03/config.yaml
   :language: yaml
   :caption: A user file named :file:`config/config.yaml` with a value set for the `address` variable
   :name: RougailAddresseVariableUserValue
       
.. 
    ---
    proxy_mode: Manual proxy configuration
    manual:
      http_proxy:
        address: example.net

.. glossary::

   configuration 
   
       We call configuration the whole system structure and user values,
       and when we speak of consistency, it is in relation to this whole set. 

Let's validate the consitency of the configuration:

.. code-block:: text
   :class: terminal
   
    rougail -v 1.1 -m firefox/ -u file -ff config/config.yaml

Everything is OK:

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_024/config/03/output_rw.html
   :class: output

.. 
    <pre>╭────────────────────────── Caption ──────────────────────────╮
    │ Variable                           <span style="color: #ffd700">Default value</span>            │
    │ <span style="color: #5c5cff">Undocumented variable</span>              Modified value           │
    │ <span style="color: #ff0000">Undocumented but modified variable</span> (<span style="color: #00aa00">Original default value</span>) │
    ╰─────────────────────────────────────────────────────────────╯
    Variables:
    <span style="color: #5c5cff">┣━━ </span>📓 proxy_mode: Manual proxy configuration (<span style="color: #00aa00">No proxy</span>)
    <span style="color: #5c5cff">┗━━ </span>📂 manual
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┗━━ </span>📂 http_proxy
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">    </span><span style="color: #5c5cff">┗━━ </span>📓 address: example.net
    </pre>

- the `proxy_mode` value is in green because its value is set by default
- the `address` value is in black because its value has been set by a user


.. keypoints:: Key points progress

    **Keywords**
    - we know how to define :term:`variable`\ s inside of a family
    - we now know what a :term:`mandatory` variable is
    - we kwow how to set a variable's user value (in a :term:`user file`)
    - we have the big picture : the :term:`configuration`, which is (the structure files + the user files)
    
    **Progress**

    - we have a :term:`family` named `manual`  and a sub family named `http_proxy`
    - And we have now two variables: :confval:`proxy_mode` and :confval:`address`. 
