理解 JINJA 模板
Posted 孤独的海浪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解 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
解析:
依据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 %}
在filter_by里面应用grains变量,相当于把逻辑放在另一个模板中了,可以被其他sls文件中的模板包引用
1 {% set auditd = salt[‘grains.filter_by‘]({ 2 ‘RedHat‘: { ‘package‘: ‘audit‘ }, 3 ‘Debian‘: { ‘package‘: ‘auditd‘ }, 4 }) %}
依据minion端变量auditd的值来指定包名
INCLUDE AND IMPORT
包含和导入可用于sls文件只共享通用的可配置的内容
示例:
1 {% from ‘lib.sls‘ import test %} 2 {% from ‘lib.sls‘ import test with context %}
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‘) }}
使用了一个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 %}
定义了一个宏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 }}
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 }}
文件中的内容可以关联到外部模板文件中预设好的逻辑中,实现灵活配置。
ESCAPING JINJA
jinja语法转义
比较简单的转义:
{{ ‘{{‘ }}
成块的转义:
1 {% raw %} 2 some text that contains jinja characters that need to be escaped 3 {% endraw %}
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
关于执行模块后续再深究。
思考:宏的定义和之前的变量定义逻辑有何不同?
宏定义能实现一组变量特定逻辑的处理,如果将多个变量定义放在普通的模板变量定义逻辑里面,一千个变量就需要定义一千次,而宏只需要定义一个规则,调用的时候自动
应用即可。
以上是关于理解 JINJA 模板的主要内容,如果未能解决你的问题,请参考以下文章