理解 JINJA 模板

UNDERSTANDING JINJA

jinja是sls文件是默认的模板语言


JINJA IN STATES

在state文件被运行之前需要将文件中jinja模板语言部分处理掉,处理完之后再转化成YAML格式,最后变成python数据结构。
jinja模板语法通常被用于在state文件中使用控制结构,如if条件,for循环等,可以达到消除冗余数据的效果。

在sls文件中使用jinja模板
示例:

 1 {% if grains['os'] != 'FreeBSD' %}
 2 tcsh:
 3     pkg:
 4         - installed
 5 {% endif %}
 6 
 7 motd:
 8   file.managed:
 9     {% if grains['os'] == 'FreeBSD' %}
10     - name: /etc/motd
11     {% elif grains['os'] == 'Debian' %}
12     - name: /etc/motd.tail
13     {% endif %}
14     - source: salt://motd
View Code

解析:

  依据minion端的os系统来部署不同的配置文件,但是上面的例子在jinja模板使用的代码可能过于冗余,代码内容的用途过于单一,它的作用仅能体现在一个文件的传输模块中。

  所以为了优化这种情况,name应该使用pillar变量,将这种判断逻辑包含到pillar环境里面,又或者将这种逻辑放在一个基础jinja模板中被继承,实现解耦,便于后续的变更。

jinja循环控制结构的示例:

 1 {% set motd = ['/etc/motd'] %}
 2 {% if grains['os'] == 'Debian' %}
 3   {% set motd = ['/etc/motd.tail', '/var/run/motd'] %}
 4 {% endif %}
 5 
 6 {% for motdfile in motd %}
 7 {{ motdfile }}:
 8   file.managed:
 9     - source: salt://motd
10 {% endfor %}
View Code

在filter_by里面应用grains变量,相当于把逻辑放在另一个模板中了,可以被其他sls文件中的模板包引用

1 {% set auditd = salt['grains.filter_by']({
2 'RedHat': { 'package': 'audit' },
3 'Debian': { 'package': 'auditd' },
4 }) %}
View Code

依据minion端变量auditd的值来指定包名


INCLUDE AND IMPORT

包含和导入可用于sls文件只共享通用的可配置的内容
示例:

1 {% from 'lib.sls' import test %}
2 {% from 'lib.sls' import test with context %}
View Code

INCLUDING CONTEXT DURING INCLUDE/IMPORT

{% import 'openssl/vars.sls' as ssl with context %}
#使用with context将变量的上下文也包含进来


MACROS

宏定义,宏的使用有利于消除代码的冗余

示例:

 1 # init.sls
 2 {% from 'lib.sls' import pythonpkg with context %}
 3 
 4 python-virtualenv:
 5   pkg.installed:
 6     - name: {{ pythonpkg('virtualenv') }}
 7 
 8 python-fabric:
 9   pkg.installed:
10     - name: {{ pythonpkg('fabric') }}
View Code

使用了一个include包含另一个sls文件

1 # lib.sls
2 {% macro pythonpkg(pkg) -%}
3   {%- if grains['os'] == 'FreeBSD' -%}
4     py27-{{ pkg }}
5   {%- elif grains['os'] == 'Debian' -%}
6     python-{{ pkg }}
7   {%- endif -%}
8 {%- endmacro %}
View Code

定义了一个宏pythonpkg,用于做变量替换,利用一个预设的规则对引用的变量做逻辑处理


TEMPLATE INHERITANCE

模板继承,参考jinja的模板语言中的继承逻辑和使用逻辑


FILTERS

过滤器

strftime
  将与时间有关的对象转化成基于时间的字符串,需要系统timelib库的支持
示例:

1 {% set curtime = None | strftime() %}
2 {{ "2002/12/25"|strftime("%y") }}
3 {{ "1040814000"|strftime("%Y-%m-%d") }}
4 {{ datetime|strftime("%u") }}
5 {{ "tomorrow"|strftime }}
View Code

yaml_encode
用于对一些需要特殊的字符做yaml转换

JINJA IN FILES
  jinja在文件中的使用
示例:

 1 # redis.sls
 2 /etc/redis/redis.conf:
 3     file.managed:
 4         - source: salt://redis.conf
 5         - template: jinja
 6         - context:
 7             bind: 127.0.0.1
 8 
 9 # lib.sls
10 {% set port = 6379 %}
11 
12 # redis.conf
13 {% from 'lib.sls' import port with context %}
14 port {{ port }}
15 bind {{ bind }}
View Code

文件中的内容可以关联到外部模板文件中预设好的逻辑中,实现灵活配置。


ESCAPING JINJA

jinja语法转义

比较简单的转义:
  {{ '{{' }}

成块的转义:

1 {% raw %}
2     some text that contains jinja characters that need to be escaped
3 {% endraw %}
View Code

CALLING SALT FUNCTIONS

jinja中可以使用salt函数,可以的函数列表可以参考以下链接:

两个等价函数的使用示例:
  {{ salt['cmd.run']('whoami') }}
  {{ salt.cmd.run('whoami') }}


DEBUGGING

show_full_context可用于输出当前上下文的变量值,便于debug分析排查问题
示例:
  Context is: {{ show_full_context() }}


CUSTOM EXECUTION MODULES

如何使用自定义的模块

  {{ salt['my_custom_module.my_custom_function']() }}

关于编写自有执行模块参考以下两个:

(1)一个执行模块在jinja语法中如何被执行
  https://docs.saltstack.com/en/2016.11/topics/tutorials/jinja_to_execution_module.html#tutorial-jinja-to-execution-module
(2)如何写一个执行模块
  https://docs.saltstack.com/en/2016.11/ref/modules/index.html#writing-execution-modules

  关于执行模块后续再深究。

思考:宏的定义和之前的变量定义逻辑有何不同?

     宏定义能实现一组变量特定逻辑的处理,如果将多个变量定义放在普通的模板变量定义逻辑里面,一千个变量就需要定义一千次,而宏只需要定义一个规则,调用的时候自动

     应用即可。

原文地址:https://www.cnblogs.com/solitarywares/p/7470497.html