Salt sls file format with jinja if sentense

144 Views Asked by At

I am trying to learn salt, and I want to use to to se advanced settings on ESXi hosts using the "salt-ext-modules-vmware" modules.

I have the following sls file:

{% for host in salt['vmware_esxi.list_hosts']() %}
        {% if salt['vmware_esxi.get_advanced_config']('host_name={{ host }}','config_name=Net.BlockGuestBPDU' == 0) %}
        set_advanced_option_{{host}}:
          module.run:
            - name: vmware_esxi.set_advanced_config
            - host_name: {{ host }}
            - config_name: Net.BlockGuestBPDU
            - config_value: 1
        {% endif %}
{% endfor %}

If I run the command to get a setting if work like it should.

Command: salt 'proxy-minion' vmware_esxi.get_advanced_config host_name=hostname.domain.com config_name=Net.BlockGuestBPDU

And if I skip the if part of the sls file it also works, but it will always set the values even when they are already set, so I decided to implement a if sentence to only set the value if it is not already correct.

But when I run the command to check the values I get an error, that I cannot figure out how to get rid of. Any help will be appreciated.

Command: salt 'proxy-minion' state.apply

Error:

proxy-minion:
    Data failed to compile:
----------
    Rendering SLS 'base:all_vmhosts_advanced_settings' failed: Problem running salt function in Jinja template: Datacenter 'host_name={{ host }}' was not found; line 2

---
{% for host in salt['vmware_esxi.list_hosts']() %}
        {% if salt['vmware_esxi.get_advanced_config']('host_name={{ host }}','config_name=Net.BlockGuestBPDU' == 0) %}    <======================
        set_advanced_option_{{host}}:
          module.run:
            - name: vmware_esxi.set_advanced_config
            - host_name: {{ host }}
            - config_name: Net.BlockGuestBPDU
[...]
---
2

There are 2 best solutions below

5
OrangeDog On

{{ }} expressions do not work when you're already in a Jinja context. Use the variable directly.

Argument keywords are not string values.

You want the test to operate on the function result, not one of its arguments.

{% if salt["vmware_esxi.get_advanced_config"](host_name=host, config_name="Net.BlockGuestBPDU") == 0 %}

Alternatively, instead of using Jinja, you can use an unless argument.

set_advanced_option_{{host}}:
  module.run:
    - vmware_esxi.set_advanced_config:
      - host_name: {{ host }}
      - config_name: Net.BlockGuestBPDU
    - unless:
      - fun: vmware_esxi.get_advanced_config
        host_name: {{ host }}
        config_name: Net.BlockGuestBPDU
1
Brian On

I figured out how this works.

Here is the solution to anyone with the same problem.

Turns out that there are functions and there are state modules.

State modules will only change values if they differ from the requested setting, where as functions will just run no matter what.

Here is the state file using a state module instead of a function:

{% for host in salt['vmware_esxi.list_hosts']() %}
set_advanced_config_{{host}}:
  vmware_esxi.advanced_config:
    - host_name: {{host}}
    - name: Net.BlockGuestBPDU
    - value: 1
{% endfor %}