Some suitable types ===================== .. objectives:: Objectives There isn't just the basic `string` available type, here we will discover new variable types, for example the `boolean` type, and even types that are much more suited to our use case, such as `domainname` or `port`. .. 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_030 ` to :tutorial:`v1.1_033 ` in the repository. :: git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git git switch --detach v1.1_030 .. type-along:: let's recap how far we've come We have an `http_proxy` family with an `address` variable in it. .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_022/firefox/10-manual.yml :language: yaml :caption: An `address` variable in the `http_proxy` family .. manual: # Manual proxy configuration http_proxy: # HTTP Proxy address: description: HTTP address :tutorial:`Download this file from the rougail-tutorials git repository ` A variable with type `domainname` ----------------------------------- We will add a custom type to our `address` variable: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/firefox/10-manual.yml :language: yaml :caption: An `address` variable in the `http_proxy` family .. manual: # Manual proxy configuration http_proxy: # HTTP Proxy address: description: HTTP address type: domainname :tutorial:`Download this file from the rougail-tutorials git repository ` Notice that we have assigned the `domainname` type to this variable: .. code-block:: yaml :linenos: :caption: The `address` variable with the `domainname` type assigned address: type: domainname Assigning a type is convenient for reading, but what else does it bring? Well, with a correct user data like this one, .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/01/config.yml :language: yaml :caption: A domain name user data setting .. --- manual: http_proxy: address: net.example :tutorial:`Download this file from the rougail-tutorials git repository ` if we launch the Rougail CLI on it: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/01/cmd_ro.txt :class: terminal .. rougail -m firefox/ -u yaml -yf config/01/config.yml We have this output: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/01/output_ro.html :class: output ..
╭──────── Caption ────────╮
    │ Variable Default value  │
    │          Modified value │
    ╰─────────────────────────╯
    Variables:
    ┣━━ 📓 Configure Proxy Access to the Internet: No proxy
    ┗━━ 📂 Manual proxy configuration
        ┗━━ 📂 HTTP Proxy
            ┗━━ 📓 HTTP address: example.net ◀ loaded from the YAML file 
                "config/01/config.yml"
    
And we don't really see any change associated with the fact that we have assigned a type to this variable. But if we assign this (wrong) user data: .. type-along:: A domain name has no space in it Let's have a look at an example of user setting that does not fit the `domainname` type: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/03/config.yml :language: yaml :caption: An invalid domain name for the :file:`config/03/config.yml` user data setting .. --- manual: http_proxy: address: bla bla :tutorial:`Download this file from the rougail-tutorials git repository ` The value is obviously not a domain name, then when we will launch the Rougail CLI: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/03/cmd_invalid.txt :class: terminal .. rougail -m firefox/ -u yaml -yf config/03/config.yml --cli.invalid_user_datas_error we then have this output: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/03/output_invalid.html :class: error ..
🛑 ERRORS
    ┗━━ the value "bla bla" is an invalid domain name for 
        "manual.http_proxy.address" (HTTP address), must not be an IP, it will be 
        ignored when loading from the YAML file "config/02/config.yml"
    
.. type-along:: what if we set an IP address instead of a domain name? .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/02/config.yml :language: yaml :caption: A domain name in the :file:`config/02/config.yml` user data setting with an IP address .. --- manual: http_proxy: address: 19.168.230.51 :tutorial:`Download this file from the rougail-tutorials git repository ` With a value that *is not a domain name* but an IP address, then when we will launch the Rougail CLI we will see a little problem: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/02/cmd_invalid.txt :class: terminal .. rougail -m firefox/ -u yaml -yf config/02/config.yml --cli.invalid_user_datas_error we then have this output: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_030/config/02/output_invalid.html :class: error ..
🛑 ERRORS
    ┗━━ the value "192.168.0.1" is an invalid domain name for 
        "manual.http_proxy.address" (HTTP address), must not be an IP, it will be 
        ignored when loading from the YAML file "config/02/config.yml"
    
We observe that an error has been raised because an IP address is not a domain name. Therefore, a type validation is taking place because we declared the type `domainname`. .. questions:: Question OK I agree with the `domainname` necessary type validation, but what if I want to specify an IP address as a user value for this `address` variable? Because it is therefore simply impossible to do so now. Is there a way for my `address` variable to accept an IP address? Well, it is possible to configure the type so that it accepts IP addresses. 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. A variable with type's parameters ------------------------------------- .. type-along:: For those who follow the tutorial with the help of the git repository Now you need to checkout the `v1.1_031` version:: git switch --detach v1.1_031 Let's add a type parameter named `allow_ip`: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_031/firefox/10-manual.yml :language: yaml :caption: The `allow_ip` type parameter set in the :file:`firefox/10-manual.yml` structure file :linenos: .. --- manual: description: Manual proxy configuration http_proxy: description: HTTP Proxy address: description: HTTP address type: domainname params: allow_ip: true The params allow the domain name `address` variable to be set with IPs. .. glossary:: type parameter A type parameter is a parameter of a variable that can refine its behavior. It is declared by adding the `params` attribute in the variable's definition. Now we will test with an IP address as the value for our `address` variable. .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_031/config/02/config.yml :language: yaml :caption: An IP address as a value in the :file:`config/02/config.yml` user value .. --- manual: http_proxy: address: 192.168.0.1 :tutorial:`Download this file from the rougail-tutorials git repository ` if we launch the Rougail CLI on it: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_031/config/02/cmd_ro.txt :class: terminal .. rougail -m firefox/ -u yaml -yf config/02/config.yml We have this output: .. raw:: html :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_031/config/02/output_ro.html :class: output We can see that the IP address value has been accepted. A variable with type `port` ------------------------------ .. type-along:: For those who follow the tutorial with the help of the git repository Now you need to checkout the `v1.1_032` version:: git switch --detach v1.1_032 After the `address` variable let's add, according to our use case, a new variable of type `port`: .. image:: images/firefox_port.png Our structure file looks like this: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_032/firefox/10-manual.yml :language: yaml :caption: The `port` type variable in the :file:`firefox/10-manual.yml` structure file :linenos: .. port: description: HTTP Port type: port default: 8080 :tutorial:`Download this file from the rougail-tutorials git repository ` Let's assign a value to this port: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_032/config/02/config.yml :language: yaml :caption: A user data :file:`config/02/config.yml` setting a value to the port variable .. proxy_mode: Manual proxy configuration manual: http_proxy: address: example.net port: 3128 :tutorial:`Download this file from the rougail-tutorials git repository ` If we launch the Rougail CLI: .. raw:: html :class: terminal :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_032/config/02/cmd_ro.txt We have this output: .. raw:: html :class: output :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_032/config/02/output_ro.html ..
╭─────────────────────────── Caption ────────────────────────────╮
    │ Variable                           Modified value              │
    │ Undocumented but modified variable (⏳ Original default value) │
    ╰────────────────────────────────────────────────────────────────╯
    Variables:
    ┣━━ 📓 Configure Proxy Access to the Internet: Manual proxy configurationloaded from the YAML file "config/02/config.yml" (⏳ No proxy)
    ┗━━ 📂 Manual proxy configuration
        ┗━━ 📂 HTTP Proxy
            ┣━━ 📓 HTTP address: example.net ◀ loaded from the YAML file 
            "config/02/config.yml"
            ┗━━ 📓 HTTP Port: 3128 ◀ loaded from the YAML file 
                "config/02/config.yml" (⏳ 8080)
    
How can we know what validations the port type performs on the value assigned to the variable? There are a number of validations that are carried out with this `port` type. Now let's assign a value that is outside the allowed ports: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_032/config/03/config.yml :language: yaml :caption: A user value in :file:`config/03/config.yml` that is not allowed :tutorial:`Download this file from the rougail-tutorials git repository ` Again, we launch the Rougail CLI: .. raw:: html :class: terminal :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_032/config/03/cmd_invalid.txt .. rougail -m firefox/ -u yaml -yf config/03/config.yml --cli.invalid_user_datas_error And we have this output: .. raw:: html :class: error :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_032/config/03/output_invalid.html ..
🛑 ERRORS
    ┗━━ the value "100000" is an invalid port for "manual.http_proxy.port" (HTTP 
        Port), must be between 1 and 65535, it will be ignored when loading from the
        YAML file "config/03/config.yml"
    
We observe that, as with the `domainname` type, a number of validations are performed to ensure that the value assigned to this variable conforms to the `port` type. A variable with type `boolean` ----------------------------------- .. type-along:: For those who follow the tutorial with the help of the git repository Now you need to checkout the `v1.1_033` version:: git switch --detach v1.1_033 Let's add one more variable in the `manual` family, with a much more basic type: `boolean`. .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_033/firefox/20-manual.yml :language: yaml :caption: A new structure file :file:`firefox/20-manual.yml` with one variable .. %YAML 1.2 --- version: 1.1 manual: use_for_https: true # Also use this proxy for HTTPS ... :tutorial:`Download this file from the rougail-tutorials git repository ` .. note:: - it is not necessary to declare the variable as a boolean type this type is *inferred* by the `true` default value - we have decided to create a new structure file :file:`firefox/20-manual.yml`. This is not necessary but usefull, please have a look at the :ref:`structure file organization and naming conventions ` - here we reuse the `manual` existing family name that has already been declared in the :file:`firefox/10-manual.yml` structure file. The content in the :file:`firefox/20-manual.yml` will be added to the existing `manual` family. Note that if two different structure files are loaded by Rougail and if they declare the same family name, then **the declarations are concatenated in the family name**. Let's switch this boolean variable to a `false` value: .. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_033/config/02/config.yml :language: yaml :caption: A :file:`config/02/config.yml` user data file with false as a value for `use_for_https` .. --- manual: http_proxy: address: example.net use_for_https: false :tutorial:`Download this file from the rougail-tutorials git repository ` Let's run the Rougail CLI: .. raw:: html :class: terminal :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_033/config/02/cmd_ro.txt .. rougail -m firefox/ -u yaml -yf config/02/config.yml the result is: .. raw:: html :class: output :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_033/config/02/output_ro.html We could of course perform several tests on type validators, but here the validation is simple: only two values ​​are allowed (`true` or `false`). .. keypoints:: let's review the key points - we can assign a `domainname` type to a variable - we can set a :term:`type parameter` to a `domainname` variable to refine their typing behavior - we can assign a `port` type to a variable - we know how to set a `boolean` type variable to `true` or `false`