> For the complete documentation index, see [llms.txt](https://thorstenkramm.gitbook.io/saltstack/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://thorstenkramm.gitbook.io/saltstack/jinja.md).

# Jinja

![Die Python-Template-Engine](/files/-LbJ6uhFh6zNE3eQb-AN)

### Jinja in SLS-Dateien verwenden

Alls SLS-Dateien werden immer durch die 📖 [Jinja-Template-Engine](https://docs.saltproject.io/en/latest/topics/jinja/index.html) "gejagt". Jinja wird aktiv, sobald es die Zeichenketten `{{ }}` oder `{% %}` findet.&#x20;

Innerhalb von `{% %}` definieren Sie Logik oder weisen Variablen Werte zu, z.B. `{% set name='Salt' %}`

`{{ var }}` veranlasst ein Suchen und Ersetzen. Die Variable innerhalb der Klammern wird durch ihren Wert ersetzt.

{% hint style="danger" %}
Jinja kennt weder Yaml noch sonst eine Programmiersprache oder Konvention innerhalb einer verarbeiteten Datei. Das hat zur Folge, dass Jinja das übliche Kommentarzeichen `#` ignoriert. Sie können mit `# {{ var }}` nicht verhindern, dass die Variable ersetzt wird.&#x20;

Verwenden Sie stattdessen Kommentare innerhalb der Jinja-Klammern. `{# {{ var }} #}`
{% endhint %}

### Variablen

{% code title="/srv/salt/exmaples/hosts.sls" %}

```yaml
{% set domain = 'example.com' %}
gw:
  host.present:
    - ip: 192.168.1.1
    - names:
      - gw
      - gw.{{ domain }}
mail:
  host.present:
    - ip: 192.168.1.2
    - names:
      - mail
      - mail.{{ domain }}
```

{% endcode %}

#### 🧩 **Aufgabe**

Schauen Sie sich das Beispiel zu [Installation von Netdata](/saltstack/salt-states/shell-kommandos.md#beispiel-netdata) noch einmal an. Dort wird die Versionsnummer mehrfach wiederholt. Optimieren Sie diesen State, sodass die Netdata Version nur einmal über eine Jinja-Variable definiert wird.

### Fallunterscheidungen (if/else)

{% code title="/srv/salt/examples/apache.sls" %}

```yaml
apache:
  pkg.installed:
{% if grains['os'] == 'RedHat' %}
    - name: httpd
{% elif grains['os'] == 'Ubuntu' %}
    - name: apache2
{% endif %}
```

{% endcode %}

#### 🧩 **Aufgabe**

1. Erstellen Sie einen State in `init/ssh.sls`, welcher den SSH-Server und Client für die unterschiedlichen Distributionen installiert.&#x20;
2. Legen Sie anschließend einen State `init/init.sls` an, der alle im Ordner `init` gespeicherten States inkludiert. Ziel ist es, dass man mit `salt '*' state.apply init` alle Minions »initialisieren« kann, d. h. alle Basis-Konfigurationen werden angewendet.

<details>

<summary>Lösung</summary>

```yaml
#
# Install SSH Server and Client for different distributions
#
{% set ssh_pkg = salt['grains.filter_by']({
    'Debian': ['ssh'],
    'RedHat': ['openssh-server','openssh-clients'],
    'Suse': ['openssh-common'],
    'Arch': ['openssh']
  })
%}

install-ssh:
  pkg.installed:
    - pkgs: {{ ssh_pkg }}
```

</details>

{% hint style="success" %}
Alle Grains sind bereits all Standard-Variablen (Python Dictionary) in Jinja verfügbar.
{% endhint %}

{% hint style="info" %}
Die Einrückung der Jina-Anweisungen spielen keine Rolle. Die SLS-Datei wird erst von Jinja verarbeitet, wobei alle Jinja-Anweisungen inklusive der Steuerzeichen entfernt werden. Danach wird die Datei an den Yaml-Interpreter des Minions übergeben, der nichts davon weiß, dass die Datei vorher von Jinja "manipuliert" wurde.
{% endhint %}

### Schleifen

{% code title="/srv/salt/examples/users.sls" %}

```yaml
{% for user in ['moe','larry','curly'] %}
{{ user }}:
  group:
    - present
  user:
    - present
    - gid_from_name: True
    - require:
      - group: {{ user }}
{% endfor %}
```

{% endcode %}

### Mapping-Tabellen

In Kombination mit dem Modul kann man mit Jinja kann man Mappings ohne lange if-else-elseif-Konstruktionen erstellen. Wenn nichts anderes angegeben wird, wird das Grain `os_family` zum Filtern verwendet.

{% code title="/srv/salt/examples/apache-map.sls" %}

```yaml
{% set apache = salt['grains.filter_by']({
    'Debian': {'pkg': 'apache2', 'srv': 'apache2'},
    'RedHat': {'pkg': 'httpd', 'srv': 'httpd'},
}, default='Debian') %}
{{ apache.pkg }}:
  pkg.installed: []
```

{% endcode %}

<figure><img src="/files/g0TiHjNBQeThtf5f6iAw" alt=""><figcaption><p>Mapping-Tabelle in Aktion</p></figcaption></figure>

{% code title="/srv/salt/caddy/php.sls" %}

```yaml
include:
  - .init

php-fpm:
  pkg.installed: []

{% set fpm = salt['grains.filter_by']({
    'Debian': {
        'backend': 'unix //var/run/php/php7.3-fpm.sock'
    },
    'Ubuntu': {
        'backend': 'unix //var/run/php/php7.2-fpm.sock'
    },
    'Rocky': {
        'backend': '127.0.0.1:9000'
    }  
},grain='os') %}

extend:
  /etc/caddy/Caddyfile:
    file.managed:
        - contents: |
            :80 {
                root * /var/www
                php_fastcgi {{ fpm['backend'] }}
            }

/var/www/info.php:
  file.managed:
    - contents: <?php phpinfo(); ?>
```

{% endcode %}

### Salt-Module in Jinja aufrufen

```yaml
{% if 1 == salt['cmd.retcode']('test -f /tmp/woo.test') %}
ack:
  file.touch:
    - name: /tmp/woo.test
{% endif %}
```

### Bedingungen testen und abbrechen <a href="#bedingungen-testen-und-abbrechen" id="bedingungen-testen-und-abbrechen"></a>

```
{% if not grains.id in salt['pillar.get']('master:nodegroups:webserver', []) %}
always-fails:
  test.fail_without_changes:
    - name: Requirement not met
    - failhard: True
{% endif %}
```

#### Beispiel Java installieren <a href="#beispiel-java-installieren" id="beispiel-java-installieren"></a>

```
{% if grains['os'] == 'CentOS' %}
{% set name='java-1.8.0-openjdk-headless' %}
{% else %}
{% set name='default-jre-headless' %}
{% endif %}

{% if 0 != salt['cmd.retcode']('which java') %}
{{ name }}:
  pkg.installed: []
{% endif %}
```

### Jina Line -Statements

Wer viel Jina in SLS-Dateien verwendet, kann auf die öffnenden und schließenden Klammern `{% %}` verzichten, und die sogenannten [Line-Statements](https://jinja.palletsprojects.com/en/2.10.x/templates/#line-statements) aktivieren. Damit kann eine komplette Zeile als Jinja-Zeile gekennzeichnet werden.

{% code title="/etc/salt/master.d/jinja.conf" %}

```yaml
jinja_sls_env:
  line_statement_prefix: ';'
  line_comment_prefix: ';;'
```

{% endcode %}

{% code title="/srv/salt/examples/multiline.sls" %}

```yaml
;; This is a comment
; set var1 = ['ietm1','item2','item4']
; if grains['os_family'] == 'Debian'
;     do var1.append('Debian')
; endif
; set list = var1|join(',')
/tmp/dummy.txt:
  file.managed:
    - contents: {{list}}
```

{% endcode %}

### Variablen in Variablenzuweisung einfügen

Variablen können andere Variablen enthalten.&#x20;

```
{% set my_var = grains['oscodename'] %}
{% set some_var = "some string" + grains['os_family']
```

```yaml
{% if grains['os'] == 'Debian' %}
{% set url = "https://repo.zabbix.com/zabbix/5.0/debian/pool/main/z/zabbix-release/zabbix-release_5.0-2+debian" + grains['osrelease'] + "_all.deb" %}
{% elif grains['os'] == 'Ubuntu' %}
{% set url = "https://repo.zabbix.com/zabbix/5.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_5.0-1+" + grains['oscodename'] + "_all.deb"%}
{% endif %}
zabbix-repo:
  cmd.run:
    - cwd: /tmp
    - name: |
        set -e
        wget {{ url }}
        dpkg -i zabbix-release*.deb
        apt-get -y update
    - creates: /etc/apt/sources.list.d/zabbix.list
```
