Ansible学习笔记——JINJA2模板的语法及使用(template模块)

JINJA2模板的语法

个人理解非常像shell脚本或者开发语言,例如一些逻辑运算等。
如果有开发基础,更易懂吧。比如我哈哈哈哈哈

1、变量

  • 可以在j2模板中引入facts变量,直接使用。
This is the system {{ ansible_facts['fqdn'] }}.
This is a {{ ansible_facts['distribution'] }} version {{ ansible_facts['distribution_version'] }} system.
Only use this system with permission.
  • 也可以直接引用playbook中的变量
  • 也可以在j2模板中定义变量——此时的优先级高于playbook中的优先级。

例如,在j2模板中定义了username变量:

{% set username = 'zhang' %}
The username id {{ username }}

在yml文件中也定义了变量

  vars:
    - username: wangxc

执行后,文件中的结果为:

The username id zhang

此时可以证明,j2模板中的变量优先级是更高的。
当移除掉j2模板中的变量定义时,将会引用yml文件中的变量。

The username id wangxc

2、逻辑控制——ifelse

{% if 条件表达式 %}
……
{% endif %}

{% if 条件表达式 %}
……
{% elif 条件表达式 %}
……
{% else %}
……
{% endif %}

jinja2的支持使用for循环、ifelse判断控制。逻辑控制语句,需要写在{% ………………%} 中

{# {% if filter01 is defined %} #}
{% if myhosts is defined %}
variable is defined
{% else %}
variable is undefined
{% endif %}

在yml文件中定义变量矩阵

  vars:
    myhosts:
      - servera
      - serverb

输出的结果:

variable is defined

3、逻辑控制——for循环

jinja2的支持使用for循环、ifelse判断控制

{% for myhost in groups['myhosts'] %}
my host is {{ myhost }}
{% endfor %}

在yml文件中定义变量矩阵

  vars:
    myhosts:
      - servera
      - serverb

运行结果:

my host is servera
my host is serverb

4、算术运算符

用的很少

+:把两个对象加到一起。如:{{ 1 + 1 }} 等于 2。但是如果两者是字符串或列表,你可以用这种方式来衔接它们【连接字符串推荐使用 ~ 运算符】。

-:用第一个数减去第二个数。如:{{ 3 - 2 }} 等于 1 。

/:对两个数做除法。返回值会是一个浮点数。如:{{ 1 / 2 }} 等于 {{ 0.5 }} 。

//:对两个数做除法,返回整数商。如:{{ 20 // 7 }} 等于 2 。

%:计算整数除法的余数。如:{{ 11 % 7 }} 等于 4 。

*:用右边的数乘左边的操作数。如:{{ 2 * 2 }} 会返回 4。也可以用于重复一个字符串多次。如:{{ '=' * 80 }} 会打印 80 个等号的横条。

**:取左操作数的右操作数次幂。如:{{ 2 ** 3 }} 会返回 8。

5、逻辑运算

==:比较两个对象是否相等。

!=:比较两个对象是否不等。

>:如果左边大于右边,返回 true。

>=:如果左边大于等于右边,返回 true。

<:如果左边小于右边,返回 true。

<=:如果左边小于等于右边,返回 true。
对于逻辑判断,在 for 过滤或 if 表达式中,它可以用于联合多个表达式:

and:如果左操作数和右操作数同为真,返回 true。

or:如果左操作数或右操作数有一个为真,返回 true。

not:对一个表达式取反(见下)。

(expr):表达式组。

提示:is 和 in 运算符同样支持使用中缀记法:foo is not bar 和 foo not in bar。所有的其它表达式需要前缀记法:not (foo and bar) 。
in:运行序列/映射包含检查。如果左操作数 包含于 右操作数,返回 true 。比如 {{ 1 in [1,2,3] }} 会返回 true。

is:运行一个 测验。参见上述

|:应用一个 过滤器。参见上述

~:把所有的操作数转换为字符串,并且连接它们。 {{ "Hello " ~ name ~ "!" }} 会返回(假设 name 值为 'John' ) Hello John!。

6、过滤器

官方的解释是这样的:
在这里插入图片描述
我觉得这一部分有点抽象,但看起来似乎又像是提供了一些比较方便的工具类(它叫做过滤器),可以帮助我们快速实现一些功能。就比如Java中的String类的自带方法,trim、toUpperCase、length等
以下是从网络上找到的一个例子,可以参考看看:

{# 变量定义 #}
{% set filter01 = -24.5 %}
{% set filter02 = 'abcDEGg' %}
{% set filter03 = "  abCDef G hkIL   " %}
{% set filter04 = ['physics', 'chemistry', 1997, 2000] %}

# 过滤器 使用
## 取绝对值
{{ filter01|abs() }} 或者 {{ filter01|abs }}
## 首字符大写,其他小写
{{ filter02|capitalize() }} 或者 {{ filter02|capitalize }}
## 去掉两端空格
|{{ filter03|trim() }}| 或者 |{{ filter03|trim }}|
## 返回序列的第一个
{{ filter04|first() }} 或者 {{ filter04|first }}
## 将序列变为字符串,可以指定每个元素间加入什么字符,默认空
默认情况: {{ filter04|join() }} 或者 {{ filter04|join }}
加入字符: {{ filter04|join('|') }}

# Tests 测验 使用
## 变量是否定义
未定义: {{ filter00 is defined }}
已定义: {{ filter01 is defined }}
## 变量是否是数字
{{ filter01 is number }} === {{ filter02 is number }}
## 变量是否是小写
{{ filter02 is lower }}
## 变量是否是字符串
{{ filter02 is string }}

## 变量在 if 中的判断是否已定义
{# ***** 变量已经被定义,直接判断表达式是 True或False ***** #}
{# {% if filter01 %} #}{# 如果变量没有定义,那么执行会报错 #}
{# 由于 filter00 之前未定义,因此这里定义为 false,不然执行会报错【生产中会在 playbook中定义】
{% set filter00 = false %}
{% if filter00 %}
#}
{# ***** 通过判断变量是否被定义,得到到True或False ***** #}
{# {% if filter01 is defined %} #}
{% if filter00 is defined %}
variable is defined
{% else %}
variable is undefined
{% endif %}

# range 使用
{% for i in range(1,20) %}
  server 172.16.1.{{ i }}:80
{% endfor %}

运行的结果

# 过滤器 使用
## 取绝对值
24.5 或者 24.5
## 首字符大写,其他小写
Abcdegg 或者 Abcdegg
## 去掉两端空格
|abCDef G hkIL| 或者 |abCDef G hkIL|
## 返回序列的第一个
physics 或者 physics
## 将序列变为字符串,可以指定每个元素间加入什么字符,默认空
默认情况: physicschemistry19972000 或者 physicschemistry19972000
加入字符: physics|chemistry|1997|2000

# Tests 测验 使用
## 变量是否定义
未定义: False
已定义: True
## 变量是否是数字
True === False
## 变量是否是小写
False
## 变量是否是字符串
True

## 变量在 if 中的判断是否已定义
variable is undefined

# range 使用
  server 172.16.1.1:80
  server 172.16.1.2:80
  server 172.16.1.3:80
  server 172.16.1.4:80
  server 172.16.1.5:80
  server 172.16.1.6:80
  server 172.16.1.7:80
  server 172.16.1.8:80
  server 172.16.1.9:80
  server 172.16.1.10:80
  server 172.16.1.11:80
  server 172.16.1.12:80
  server 172.16.1.13:80
  server 172.16.1.14:80
  server 172.16.1.15:80
  server 172.16.1.16:80
  server 172.16.1.17:80
  server 172.16.1.18:80
  server 172.16.1.19:80

JINJA2模板的引入

需要通过template模块,引入对应的j2模板。
j2模板没有要求必须以 .j2结尾,但为了提升可读性,建议这样做。

---
- name:
  hosts: servera
  tasks:
    - name: jinja2 test
      template:
        src: jinja2.j2
        dest: /home/student/j2_res

本文部分示例引用自:https://blog.csdn.net/woshizhangliang999/article/details/105849051

JINJA2模板综合实验

实验环境

[student@workstation file-review]$ pwd
/home/student/file-review
[student@workstation file-review]$ cat ansible.cfg 
[defaults]
inventory = inventory
ansible_managed = Ansible managed: modified on %Y-%m-%d %H:%M:%S
[student@workstation file-review]$ cat inventory 
[servers]
serverb.lab.example.com
[student@workstation file-review]$ cat files/issue 
*------------------------------- PRIVATE SYSTEM -----------------------------*
 -   Access to this computer system is restricted to authorised users only.   *
 -                                                                            *
 -      Customer information is confidential and must not be disclosed.       *
*----------------------------------------------------------------------------*

实验要求

  • 识别serverb上的facts变量,显示系统内存总量及处理器数目
  • 创建一个j2模板,当devops用户登录时,显示出内存总量和处理器数目
  • 创建playbook,使用devops用户并提权
  • 使用template配置J2模板,并映射到目标主机的/etc/motd。设置所属组、所有者为root,权限为0644
  • 使用stat和debug验证并显示/etc/motd的文件信息
  • 使用copy将files/issue的文件放到被管理主机的/etc/目录下,并配置与源文件相同的权限
  • 使用file模块保证/etc/issue.net是/etc/issue的链接

示例文件

[student@workstation file-review]$ cat motd.j2 
system total memory: {{ ansible_facts['memtotal_mb'] }} MiB
system processor count: {{ ansible_facts['processor_count'] }}

[student@workstation file-review]$ cat motd.yml 
---
- name:
  hosts: all
  remote_user: devops
  become: true
  tasks:
    - name: 
      template:
        src: motd.j2
        dest: /etc/motd
        owner: root
        group: root
        mode: 0644
    - name:
      stat:
        path: /etc/motd
      register: stat_res
    - name:
      debug:
        msg: "{{ stat_res }}"
    - name:
      copy:
        src: files/issue
        dest: /etc/
        owner: root
        group: root
        mode: 0644
    - name:
      file:
        src: /etc/issue
        dest: /etc/issue.net
        state: link
        owner: root
        group: root
        force: yes


运行结果

[student@workstation file-review]$ ansible-playbook motd.yml 

PLAY [all] ***************************************************************************************************************************

TASK [Gathering Facts] ***************************************************************************************************************
ok: [serverb.lab.example.com]

TASK [template] **********************************************************************************************************************
changed: [serverb.lab.example.com]

TASK [stat] **************************************************************************************************************************
ok: [serverb.lab.example.com]

TASK [debug] *************************************************************************************************************************
ok: [serverb.lab.example.com] => {
    "msg": {
        "changed": false,
        "failed": false,
        "stat": {
            "atime": 1616666801.3760493,
            "attr_flags": "",
            "attributes": [],
            "block_size": 4096,
            "blocks": 8,
            "charset": "us-ascii",
            "checksum": "860519cbc178f27e2a63bcdd38510709cf65710c",
            "ctime": 1616666801.3780494,
            "dev": 64513,
            "device_type": 0,
            "executable": false,
            "exists": true,
            "gid": 0,
            "gr_name": "root",
            "inode": 8758505,
            "isblk": false,
            "ischr": false,
            "isdir": false,
            "isfifo": false,
            "isgid": false,
            "islnk": false,
            "isreg": true,
            "issock": false,
            "isuid": false,
            "mimetype": "text/plain",
            "mode": "0644",
            "mtime": 1616666800.7440493,
            "nlink": 1,
            "path": "/etc/motd",
            "pw_name": "root",
            "readable": true,
            "rgrp": true,
            "roth": true,
            "rusr": true,
            "size": 55,
            "uid": 0,
            "version": "2324674415",
            "wgrp": false,
            "woth": false,
            "writeable": true,
            "wusr": true,
            "xgrp": false,
            "xoth": false,
            "xusr": false
        }
    }
}

TASK [copy] **************************************************************************************************************************
changed: [serverb.lab.example.com]

TASK [file] **************************************************************************************************************************
changed: [serverb.lab.example.com]

PLAY RECAP ***************************************************************************************************************************
serverb.lab.example.com    : ok=6    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

验证

注意:默认sshd是无法展示issue中的内容。以下结果是ansible的lab命令在初始化实验环境时,已经配置过sshd服务的。
如果想要展示,需要手动修改serverb中的 /etc/ssh/sshd_config文件,添加下面这一行:

Banner /etc/issue.net

这一行指定了banner的文件路径。默认情况下是:

# no default banner path
#Banner none

以下是ansible的执行结果:

[student@workstation file-review]$ ssh devops@serverb
*------------------------------- PRIVATE SYSTEM -----------------------------*
*   Access to this computer system is restricted to authorised users only.   *
*                                                                            *
*      Customer information is confidential and must not be disclosed.       *
*----------------------------------------------------------------------------*
system total memory: 821 MiB
system processor count: 1
Activate the web console with: systemctl enable --now cockpit.socket

Last login: Thu Mar 25 18:53:58 2021 from 172.25.250.9

大功告成!

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值