Group variables inside families ================================= .. 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:: Prerequisites - We assume that Rougail's library is :ref:`installed ` on your computer. - It is possible to retrieve the current state of the various rougail files manipulated in this tutorial step by checking out the corresponding tag of the Rougail-tutorials git repository. Each tag corresponds to a stage of progress in the tutorial. Of course, you can also decide to copy/paste or download the tutorial files contents while following the tutorial steps. If you want to follow this tutorial with the help of the corresponding :tutorial:`Rougail-tutorials git repository `, this workshop page corresponds to the tags :tutorial:`v1.1_020 ` in the repository: :: git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git git checkout v1.1_020 .. type-along:: let's recap how far we've come We have this choice type variable in its structure definition file: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_010/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 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`. In short, let's describe our `proxy_mode` variable like this: .. confval:: proxy_mode :type: `choice` :default: No proxy Proxy mode's settings Now we will define new variables, and other structure definitions. For the sake of clarity, we will put the structure definitions in separate files. Please have a look at the :ref:`file naming and organizing convention `. 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`:: . └── firefox ├── 00-proxy.yml └── 10-manual.yml Creating a new family ----------------------- Let's create a family named `manual` which obviously corresponds to the proxy's manual configuration choice. .. 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). .. warning:: 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`. We have to force the family type inference. It's because we don't have set any :term:`variable` inside yet. When we will have a variable inside of this family, we will make a YAML block (that is, we just indent the lines) and the Rougail's type inference engine will implicitely infer the variable's container as a family type. .. type-along:: A family inside a family Creating a family hierarchy of family container types is very easy, here is an example: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_011/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 the `http_proxy` family. This time, the type of this new variable is a `domainname` type: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_012/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 Now that the :confval:`address` variable is declarde, the :term:`operator` can set :term:`a value ` to the :confval:`address` variable So we have now an :confval:`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. There are a bunch of types available in Rougail. 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/src/tag/v1.1_012/config/01/output_ro.html :class: error-box ..
🛑 ERRORS
    ┣━━ The following variables are mandatory but have no value:
    ┗━━   - manual.http_proxy.address (HTTP address)
    
Because the :term:`mandatory` variable attribute is infered by default for this variable. .. type-along:: user data files are where the user values lives And we need to set the values ​​in separate files too, called `user data files`. .. glossary:: user data file A user data file is a file where only :term:`user datas` are set. A user file is a file where there are only user datas in it, users can set values, called user values -- that is variable's values that have been set by an :term:`operator`\ . see also :term:`user datas` .. type-along:: let's set user values in a user data file Here is a user data file sample: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_012/config/03/config.yml :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_012/config/03/output_rw.html :class: output ..
╭────────────────────────── Caption ──────────────────────────╮
    │ Variable                           Default value            │
    │ Undocumented variable              Modified value           │
    │ Undocumented but modified variable (Original default value) │
    ╰─────────────────────────────────────────────────────────────╯
    Variables:
    ┣━━ 📓 proxy_mode: Manual proxy configuration (No proxy)
    ┗━━ 📂 manual
        ┗━━ 📂 http_proxy
            ┗━━ 📓 address: example.net
    
- 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 Variables can have parameters --------------------------------- .. questions:: Question **question**: Does our `address` domain name variable accepts IP addresses ? **answer**: Well it depends. We need to specify whether our variable accepts to be filled using an IP or a domain name only. This is where the ability to parameterize our variable comes in. .. type-along:: let's create a variable parameter named `allow_ip` .. --- manual: description: Manual proxy configuration http_proxy: description: HTTP Proxy address: description: HTTP address type: domainname params: allow_ip: true .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_024/firefox/10-manual.yml :language: yaml :caption: The `address` has a parameter set in the :file:`firefox/10-manual.yml` structure file :name: RougailAddressParameter :linenos: .. --- manual: description: Manual proxy configuration http_proxy: description: HTTP Proxy address: description: HTTP address type: domainname params: allow_ip: true We can see line 11 and 12 that the params allow the domain name `address` variable to be set with IPs. .. glossary:: parameter A parameter is a property of a variable that can refine its behavior .. type-along:: a second variable in the `http_proxy` family Let's create a `port` variable in the `http_proxy` family: .. confval:: port :type: `port` :default: 8080 The HTTP Port Here is the new :file:`firefox/10-manual.yml` structure file: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_012/firefox/10-manual.yml :language: yaml :caption: A rougail structure description file with a hierarchy. :name: RogailPortVariable :linenos: .. --- manual: description: Manual proxy configuration http_proxy: description: HTTP Proxy address: description: HTTP address type: domainname params: allow_ip: true port: description: HTTP Port type: port default: 8080 .. keypoints:: let's review the key points **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 data file`) - we have the big picture : the :term:`configuration`, which is (the structure files + the user data files) - we can add :term:`parameter`\ s to variables to refine their behavior **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`.