Ansible Template 模板

模板是一个文本文件,可以用于根据每个主机的不同环境而为生成不同的文件
模板文件中支持嵌套jinja2语言的指令,来实现变量,条件判断,循环等功能
需要使用template模块实现文件的复制到远程主机,但和copy模块不同,复制过去的文件每个主机可以会有所不同

1、jinja2语言

Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。

它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:

  • 沙箱中执行
  • 强大的 HTML 自动转义系统保护系统免受 XSS
  • 模板继承
  • 及时编译最优的 python 代码
  • 可选提前编译模板的时间
  • 易于调试。异常的行数直接指向模板中的对应行。
  • 可配置的语法

jinja2 语言支持多种数据类型和操作:

  • 字面量,如: 字符串:使用单引号或双引号,数字:整数,浮点数
  • 列表:[item1, item2, …]
  • 元组:(item1, item2, …)
  • 字典:{key1:value1, key2:value2, …}
  • 布尔型:true/false
  • 算术运算:+, -, *, /, //, %, **
  • 比较操作:==, !=, >, >=, <, <=
  • 逻辑运算:and,or,not
  • 流表达式:For,If,When

字面量:

表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。如"Hello World"双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在 Python 里, 42 和 42.0 是不一样的

算术运算:

Jinja 允许用计算值。支持下面的运算符
+:把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2
-:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1
/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 0.5
//:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
*:用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ '=' * 80 }}会打印 80 个等号的横条\
**:取左操作数的右操作数次幂。 {{ 23 }} 会返回 8

比较操作符

== 比较两个对象是否相等
!= 比较两个对象是否不等
>  如果左边大于右边,返回 true
>= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true

逻辑运算符

对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
and 如果左操作数和右操作数同为真,返回 true
or 如果左操作数和右操作数有一个为真,返回 true
not 对一个表达式取反
(expr)表达式组
true / false true 永远是 true ,而 false 始终是 false 

2、template

template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件存建议放于templates目录下,且命名为 .j2 结尾

yaml/yml 文件和templates目录平级,此时playbook中指定模版文件时可不用指定路径,目录结构如下示例:

 ./
 ├── temnginx.yml
 └── templates
         └── nginx.conf.j2
# 利用template 同步nginx配置文件
[root@ansible ~]#vim temnginx.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf

[root@ansible ~]#ansible-playbook temnginx.yml
# template变更替换
[root@ansible ~]#mkdir templates
[root@ansible ~]#vim templates/nginx.conf.j2
......
worker_processes {{ ansible_processor_vcpus }};
......


[root@ansible ~]#vim temnginx2.yml
---
- hosts: websrvs
  remote_user: root

  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
    - name: start service
      service: name=nginx state=started enabled=yes

[root@ansible ~]#ansible-playbook temnginx2.yml

template算术运算

vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**2 }};
worker_processes {{ ansible_processor_vcpus+2 }}; 
# 范例
[root@ansible ansible]#vim templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**3 }};

[root@ansible ansible]#cat templnginx.yml
---
- hosts: websrvs
  remote_user: root
  tasks:
    - name: install nginx
      yum: name=nginx
    - name: template config to remote hosts
      template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
      notify: restart nginx
    - name: start service
      service: name=nginx state=started enabled=yes
  handlers:
    - name: restart nginx
      service: name=nginx state=restarted

3、template中使用流程控制 for 和 if

template中也可以使用流程控制 for 循环和 if 条件判断,实现动态生成文件功能

3.1、for 循环

格式

{% for i in EXPR %}
 ...
{% endfor %}

# 示例:
{% for i in range(1,10) %}
 server_name web{{i}};
{% endfor %}
# 范例
# temlnginx2.yml
---
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - 81
      - 82
      - 83
  tasks:
    - name: template config
      template: src=nginx.conf2.j2 dest=/data/nginx.conf

# templates/nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
   listen {{ vhost }}
}
{% endfor %}

# 生成的结果:
server {
   listen 81
}
server {
   listen 82
}
server {
   listen 83
}
# 范例
# templnginx4.yml
- hosts: websrvs
 remote_user: root
 vars:
   nginx_vhosts:
     - listen: 8080
       server_name: "web1.test.org"
       root: "/var/www/nginx/web1/"
     - listen: 8081
       server_name: "web2.test.org"
       root: "/var/www/nginx/web2/"
     - {listen: 8082, server_name: "web3.test.org", root:
"/var/www/nginx/web3/"}
 tasks:
   - name: template config
     template: src=nginx.conf4.j2 dest=/data/nginx4.conf


# templates/nginx.conf4.j2
{% for vhost in nginx_vhosts %}
server {
   listen {{ vhost.listen }}
   server_name {{ vhost.server_name }}
   root {{ vhost.root }}
}
{% endfor %}

# 生成结果:
server {
   listen 8080
   server_name web1.test.org
   root /var/www/nginx/web1/
}
server {
   listen 8081
   server_name web2.test.org
   root /var/www/nginx/web2/
}
server {
   listen 8082
   server_name web3.test.org
   root /var/www/nginx/web3/
}
# 范例
# nginx.conf5.j2

upstream webservers {
{% for i in range(1,11) %}
 server 10.0.0.{{ i }}:{{ http_port }}
{% endfor %}

server {
    listen {{ http_port }};
    server_name {{ server_name }};
    location / {
        proxy_pass http://webservers;
    }
}

#templnginx5.yml
---
- hosts: websrvs
  vars:
    http_port: 80
    server_name: www.test.org
  tasks:
    - name: install nginx
      yum: name=nginx
    - name: config file
      template: src=nginx.conf5.j2 dest=/etc/nginx/conf.d/web_proxy.conf
    - name: start nginx
      service: name=nginx state=started
# 利用for循环遍历主机清单的指定主机组的主机
# cat templnginx6.yml
---
- hosts: proxy_servers
  vars:
    - fqdn: www.test.org
    - http_port: 80
    - upstream_name: webservers
    - node_port: 80
  tasks:
    - name: config file
      template:
        src: nginx.conf6.j2
        dest: /tmp/nginx.conf

# cat templates/nginx.conf6.j2
upstream {{ upstream_name }} {
{% for host in groups['webservers'] %}
    server {{ host }}:{{ node_port }}
{% endfor %}
}

server {
    listen {{ http_port }};
    server_name {{ fqdn }};
    location / {
        proxy_pass http://{{ upstream_name }};
    }
}

# vim /etc/ansible/hosts
[webservers]
192.168.1.12
192.168.1.13

3.2、if 条件判断

在模版文件中还可以使用 if条件判断,决定是否生成相关的配置信息

# templnginx6.yml
- hosts: websrvs
  remote_user: root
  vars:
    nginx_vhosts:
      - web1:
        listen: 8080
        root: "/var/www/nginx/web1/"
      - web2:
        listen: 8080
        server_name: "web2.test.org"
        root: "/var/www/nginx/web2/"
      - web3:
        listen: 8080
        server_name: "web3.test.org"
        root: "/var/www/nginx/web3/"
  tasks:
    - name: template config to
      template: src=nginx.conf5.j2 dest=/data/nginx5.conf

# templates/nginx.conf6.j2
{% for vhost in nginx_vhosts %}
server {
    listen {{ vhost.listen }}
{% if vhost.server_name is defined %}
    server_name {{ vhost.server_name }}   #注意缩进
{% endif %}
    root  {{ vhost.root }}                #注意缩进
}
{% endfor %}

# 生成的结果
server {
   listen 8080
   root /var/www/nginx/web1/
}
server {
   listen 8080
   server_name web2.test.org
   root /var/www/nginx/web2/
}
server {
   listen 8080
   server_name web3.test.org
   root /var/www/nginx/web3/
}
# 生成keepalived配置文件
# cat keepalived.conf.j2
global_defs {
    router_id {{ ansible_hostname }}
}
vrrp_instrance VI_1 {
{% if ansible_hostname == "ka1" %}
    state MASTER
    priority 100
{% elif ansible_hostname == "ka2" %}
    state SLAVE
    priority 80
{% endif% }
......
}

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享