Calculation with a jinja type

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.

Todo

on peut aussi faire un exercice de ce genre pour la propriété mandatory

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:

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:

https_proxy:
  type: family
  hidden:
    variable: manual.use_for_https

Now we could write it like that:

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:

hidden:
  variable: manual.use_for_https

by this (more complicated) hidden property declaration:

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 dict/02-proxy_manual.yml structure file:

the 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 %}

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?

What about this Jinja type?

If the 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.

Jinja

Jinja 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.

What can be calculated?

We have seen that the disabled or hidden properties could be calculated. The default values can be calculated too.

Todo

montrer un exemple de valeur par défaut calculées (type jinja)

Todo

montrer aussi ici des exemples de calculs de valeurs variables, ce qui est un des usages principaux de jinja

Using jinja in a dynamic family declaration

Let’s come back to the previous section’s dynamic family example.

In a dynamic family, as seen before, you have the possibility to name your identifier. In the classic declaration, the identifier’s variable is named “identifier” by default. Sounds logical:

"{{ identifier }}_proxy":
  description: "{{ identifier }} Proxy"
  dynamic:
    - HTTPS
    - SOCKS

Here the identifer’s variable takes the value of the dynamic family parameter.

Using a jinja calculation with a parameter

We have the possibility to use a given variable variable inside a jinja calculation:

firefox/20-proxy.yml
%YAML 1.2
---
version: 1.1

manual:

  use_for_https: true  # Also use this proxy for HTTPS

  https_proxy:
    description: HTTPS Proxy
    hidden:
      variable: _.use_for_https

    address:
      description: HTTPS address
      default:
        variable: __.http_proxy.address

    port:
      description: HTTPS Port
      default:
        variable: __.http_proxy.port
...

This can be done by defining a my_identifier variable.

This jinja variable comes from the params parameter of the hidden property.

params:
  my_identifier:
    type: identifier

Here the hidden property’s value is defined by a jinja calculation. In this jinja calculation we have a my_identifier jinja variable.

hidden:
  jinja: |
    {% if my_identifier == 'HTTPS' and manual.use_for_https %}
    HTTPS is same has HTTP
    {% endif %}
  params:
    my_identifier:
      type: identifier
  description: |
    in HTTPS case if "manual.use_for_https" is set to True

The when and when_not parameter notation

Todo

ça devrait être sur une autre page. déplacer cela ailleurs

Handling the SOCKS version

Now we need to handle the SOCKS version as show in the firefox configuration screenshot:

../_images/firefox_soks_version.png

We’ll just add a choice variable with a default value and a disabled property:

version:
  description: SOCKS host version used by proxy
  choices:
    - v4
    - v5
  default: v5
  disabled:
    type: identifier
    when: 'HTTPS'

There is still something new about this YAML, though. It is the when parameter of the disabled property. You have two possible notations: when or when_not. These two notations are just a short hand of what we could express in jinja as this code:

{% if identifier == 'HTTPS' %}
when the identifer equals 'HTTPS' then the SOCKS version is disabled
{% endif %}

And the when_not parameter is just the logical opposite.

Here is the final version of our YAML dynamic family:

firefox/20-proxy.yml
%YAML 1.2
---
version: 1.1

manual:

  use_for_https: true  # Also use this proxy for HTTPS

  https_proxy:
    description: HTTPS Proxy
    hidden:
      variable: _.use_for_https

    address:
      description: HTTPS address
      default:
        variable: __.http_proxy.address

    port:
      description: HTTPS Port
      default:
        variable: __.http_proxy.port
...

Key points

keywords

  • calculation with a jinja type calculation

  • calculation with a when or when_not parameter

  • defining a jinja internal variable in a jinja calculation

progress

Here we have come to the possibility of making any kind of calculations based on the state of the configuration. This is an important feature to manage the stateful aspect of a configuration.