Variable with multiple values
================================

.. objectives:: Objectives

   We will introduce the concept of multiple type variable.
   It is more or less some kind of a container of variable's values.

.. prerequisites:: Prerequisites

    - We assume that Rougail's library is :ref:`installed <installation>` 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 <src/branch/v1.1>`,
    this workshop page corresponds to the tags :tutorial:`v1.1_110 <src/tag/v1.1_110/README.md>` to :tutorial:`v1.1_111 <src/tag/v1.1_111/README.md>`
    in the repository.

    ::

       git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git
       git switch --detach v1.1_110

A conditional disabled non mandatory variable with type domainname and parameters
-----------------------------------------------------------------------------------

In order to fit with our use case, we need a variable that takes as its value the domain names authorized to pass through the proxy, if it is enabled. We already used before in this tutorial the `domainname` type, which perfectly matches our needs here. 
We will just need to add certain parameters associated to this `domainname` type, as we will see.
We're gonna put it in another :term:`structure file` named :file:`firefox/40-no_proxy.yml`.

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_110/firefox/40-no_proxy.yml
   :language: yaml
   :caption: The :file:`firefox/40-no_proxy.yml` structure file with the domains that are allowed to pass through the proxy

..
    %YAML 1.2
    ---
    version: 1.1

    no_proxy:
      description: Address for which proxy will be desactivated
      type: domainname
      params:
        allow_ip: true
        allow_cidr_network: true
        allow_without_dot: true
        allow_startswith_dot: true
      mandatory: false
      disabled:
        variable: _.proxy_mode
        when: No proxy
    ...

This `no_proxy` variable is a `domainname` with some additional parameters, we authorize
values like:

- IP
- CIDR networks
- machine names (without `'.'`)
- sub-domaines like `.example`

To clarify things, let's launch the Rougail CLI

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_110/config/02/cmd_ro.txt
   :class: terminal

..
    rougail -m firefox/ --types types/proxy -u yaml -yf config/02/config.yml

On this :term:`user data`:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_110/config/02/config.yml
   :language: yaml
   :caption: Automatic proxy configuration :file:`config/02/config.yml` user data file  with a pass through domain name

.. 
    ---
    proxy_mode: Automatic proxy configuration URL
    auto: https://auto.proxy.net/wpad.dat
    no_proxy: 192.168.1.0/24

We then have this output:

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_110/config/02/output_ro.html   
   :class: output
   
..
    ╭────────────── Caption ───────────────╮
    │ Variable Modified value              │
    │          (⏳ Original default value) │
    ╰──────────────────────────────────────╯
    Variables:
    ┣━━ 📓 Configure Proxy Access to the Internet: Automatic proxy configuration URL ◀ loaded from the YAML file "config/02/config.yml" (⏳ No proxy)
    ┣━━ 📓 Automatic proxy configuration URL: https://auto.proxy.net/wpad.dat ◀ loaded from the YAML file "config/02/config.yml"
    ┗━━ 📓 Address for which proxy will be desactivated: 192.168.1.0/24 ◀ loaded from the YAML file "config/02/config.yml"

We can see the address for which proxy will be desactivated in the output.

A variable with multiple values
-----------------------------------

.. type-along:: For those who follow the tutorial with the help of the git repository

    Now you need to checkout the :tutorial:`v1.1_111 <src/tag/v1.1_111/README.md>` version::

          git switch --detach v1.1_111

It's easy to find out what the next step is:  we would now need some kind of a container type, 
which would allow us to set not only one domain name but a list of domain names for which the proxy will be disabled.

Making this change requires adding one line, just one, to our variable,
have a look at the `multi: true` parameter:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_111/firefox/40-no_proxy.yml
   :language: yaml
   :caption: The :file:`firefox/40-no_proxy.yml` structure file with the pass through domains set to `multi`

..
    %YAML 1.2
    ---
    version: 1.1

    no_proxy:
      description: Address for which proxy will be desactivated
      type: domainname
      params:
        allow_ip: true
        allow_cidr_network: true
        allow_without_dot: true
        allow_startswith_dot: true
      multi: true
      mandatory: false
      disabled:
        variable: _.proxy_mode
        when: No proxy
    ...


.. questions:: Question


   What difference does it make? 

   First, note that the `no_proxy` variable is still a `domainname` type. 
   The type hasn't changed.

There's a big difference: now it is important to note that the values ​​of the variable 
must be a list containing strings, and not a single string.
Therefore, the contents of the :term:`user data` file need to be changed.

Now let's launch the Rougail CLI with the `no_proxy` variable containing a list:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_111/config/02/config.yml
   :language: yaml
   :caption: Automatic proxy configuration :file:`config/02/config.yml` user data file  with a pass through domain name

.. 
    %YAML 1.2
    ---
    version: 1.1

    no_proxy:
      description: Address for which proxy will be desactivated
      type: domainname
      params:
        allow_ip: true
        allow_cidr_network: true
        allow_without_dot: true
        allow_startswith_dot: true
      multi: true
      mandatory: false
      disabled:
        variable: _.proxy_mode
        when: No proxy
    ...

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_111/config/02/cmd_ro.txt
   :class: terminal

..
    rougail -m firefox/ --types types/proxy -u yaml -yf config/02/config.yml

Now we have this output: 

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_111/config/02/output_ro.html   
   :class: output

..
    Variables:
    ┣━━ 📓 Configure Proxy Access to the Internet: Automatic proxy configuration URL ◀ loaded from the YAML file "config/02/config.yml" (⏳ No proxy)
    ┣━━ 📓 Automatic proxy configuration URL: https://auto.proxy.net/wpad.dat ◀ loaded from the YAML file "config/02/config.yml"
    ┗━━ 📓 Address for which proxy will be desactivated:
        ┣━━ example.net ◀ loaded from the YAML file "config/02/config.yml"
        ┗━━ 192.168.1.0/24 ◀ loaded from the YAML file "config/02/config.yml"

.. questions:: Answer to the question

   So, the difference it makes is: yes, we have a list now. 
   
   We call this a :term:`multiple <multi>` variable.

.. glossary::

   multi
   
       A multiple variable, in short, a multi, is a variable that has a list of values.
       
       Note that we have more than just a simple container here. 
       The real challenge is maintaining the consistency of the :term:`configuration`
       exactly the same way as if we only had one value to manage.
       
       A multi is a multiple variable, that is a variable that can have multiple values.

.. note:: Note that the value of a :term:`multi` variable which has no default value set and which is not :term:`mandatory`
   will be the empty list `[]`
   The :term:`mandatory` properties does not means that the `null` value is acceptable (that is the `empty` properties).

.. keypoints:: Key points

   We have now some kind of a container facility named `multi`, that can be applied 
   to a variable simply by setting the `multi: true` parameter.

