zoukankan      html  css  js  c++  java
  • Ansible之templates模板

      一、jinja2简介解

      Jinja2是Python下一个被广泛应用的模版引擎,他的设计思想来源于Djanjo的模板引擎,并扩展了其语法和一系列强大的功能。ansible的模板配置文件就是用jinja2这种模板编程语言写的,其中jinja2使用字面量有如下形式

      1)字符串:使用单引号或双引号引起来的部分

      2)数字:支持整数,浮点数(小数)

      3)列表:和python里的列表一样,用中括号括起来,每个元素之间用逗号隔开,如[item1,item2,....]

      4)元组:和python里的元组一样,小括号括起来,每个元素之间用逗号隔开,如(item1,item2,....)

      5)字典:同python里的字典一样,大括号括起来,每个k/v(键值对)用逗号隔开,键和值用":"冒号隔开,如{key1:value1,key2:value2,....}

      6)布尔型:同其他语言布尔型一样,ture/false

      7)支持算数运算:+,-,*,/,//(整除,地板除),%(取模,取余数),**(幂运算)

      8)支持比较操作:==(比较两个值是否相等),!=(不等),>,>=(大于等于),<,<=(小于等于)

      9)支持逻辑运算:and(与),or(或),not(非)

      10)支持for(循环) ,if(判断),when(当某一条件满足才开始执行when所在的代码块,作用类似if)

      除此以外,jinja2还支持“test”测试语句,比如我们要判断某个变量是否定义,可以使用defined来判断,如 vars is defined ,如果vars定义则表达式返回true,相反返回false。类似的还有undefined(与defined相反),equalto(与“==”作用等效),even(判断对象是否是偶数),iterable(判断对象是否可迭代)

      二、jinja2语法

    jinja2有如下语法:

      1)控制结构,它和我们写别的语言的控制结构类似,唯一不同的是它的for循环要用”{%%}“给括起来,且必须写在两个百分号之间,后面结束有一个{%endfor$}来表示for循环的结束,同样if语句也是,必须写在"{%%}" 两个百分号之间,后面结束也有个{%endif%}来表示if语句的结束,当然if语句支持elif ,else  这个同python里的if用法一样。

      2)变量引用,jinja2的变量引用同ansible的变量应用类似,都是用"{{}}" 双大括号来表示中间括起来的内容表示变量

      3)注释用"{#"开始,中间部分表示注释,以"#}"结束表示注释结束,支持多行注释和当行注释

    示例:

      1)for循环使用

    {% for vhost in nginx_vhosts %}
    server {
    listen {{ vhost.listen }}
    }
    {% endfor %}
    

      说明:以上模板表示,从nginx_vhosts列表里去循环,nginx_vhosts里有几个元素,它将循环几次,每次循环取的值用vhost变量代替,它的用法类型shell里的for循环和python里的for循环

      2)if单分支选择使用

    {% if vhost.server_name is defined %}
        server_name {{ vhost.server_name }}
    {% endif %}

      3)if多分支选择使用

    {%if vhost.port is undefined %}
        http_port=80
    {%elif vhost.port == 81%}
        http_port=81
    {%else%}
        http_port = 83
    {%endif%}
    

      4)单行注释

    {#% for i in list %#}
    

      5)多行注释

    {#
        {% for i in list %}
             i+=i
          {% endfor %}
    #}
    

      三、playbook中使用模板

    templates是ansible的一个模块,其功能是根据模板文件动态生成配置文件,templates文件必须存放于templates目录下,且命名为".j2"结尾,yaml/yml文件需要和templates目录平级,这样我们在yml文件中调用模板的时候,就不需要写模板文件的路径,否则需要描述模板文件的路径,因为template模块会自动去找templates目录下的模板文件。目录结构如下

    .
    ├── temnginx.yml
    └── templates
       └── nginx.conf.j2
    

    示例:playbook中template变量替换

      利用tamplates同步nginx配置文件,其中修改nginx.conf.j2(worker_processes {{ ansible_processor_vcpus }};)指定其worker进程的个数由远程主机的cpu个数决定

    [root@test ~]#ll
    总用量 4
    -rw-r--r-- 1 root root 212 11月 18 14:08 temnginx.yml
    drwxr-xr-x 2 root root  27 11月 18 14:05 templates
    [root@test ~]#tree
    .
    ├── temnginx.yml
    └── templates
        └── nginx.conf.j2
    
    1 directory, 2 files
    [root@test ~]#head templates/nginx.conf.j2 
    # For more information on configuration, see:
    #   * Official English Documentation: http://nginx.org/en/docs/
    #   * Official Russian Documentation: http://nginx.org/ru/docs/
    
    user nginx;
    worker_processes {{ ansible_processor_vcpus }};
    error_log /var/log/nginx/error.log;
    pid /run/nginx.pid;
    
    # Load dynamic modules. See /usr/share/nginx/README.dynamic.
    [root@test ~]#cat temnginx.yml 
    ---
    - hosts: websers
      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
     
    [root@test ~]#
    

      说明:以上playbook里是使用template模板去动态生成的配置文件,不是拷贝,拷贝是将文件原封不动的拷贝过去,还需要注意的是template模块不能在ad-hoc命令行里使用,只能在playbook里使用,且模板文件必须是".j2"结尾的

    示例:playbook中template算数运算

    还是以上的示例,我们可以这样写

    vim nginx.conf.j2
    worker_processes {{ ansible_processor_vcpus**2 }};
    

      说明:我们可以用ansible内置变量做算术运算后的值作为模板文件的值,在playbook中还是用template模块去调用就好了

    示例:模板文件中 for循环的用法

    [root@test ~]#tree
    .
    ├── temnginx.yml
    └── templates
        └── nginx.conf.j2
    
    1 directory, 2 files
    [root@test ~]#cat templates/nginx.conf.j2 
    {% for vhost in nginx_vhosts %}
    server {
    listen {{ vhost.listen }}
    }
    {% endfor %}
    [root@test ~]#cat temnginx.yml 
    ---
    - hosts: websers
      remote_user: root
      vars:
        nginx_vhosts:
          - listen: 8080
      tasks:
        - name: install nginx
          yum: name=nginx 
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
     
    [root@test ~]#  

    生成结果:

    [root@test ~]#ansible-playbook  temnginx.yml   
    
    PLAY [websers] ******************************************************************************************************
    
    TASK [Gathering Facts] **********************************************************************************************
    ok: [192.168.0.128]
    ok: [192.168.0.218]
    
    TASK [install nginx] ************************************************************************************************
    changed: [192.168.0.128]
    changed: [192.168.0.218]
    
    TASK [template config to remote hosts] ******************************************************************************
    changed: [192.168.0.128]
    changed: [192.168.0.218]
    
    PLAY RECAP **********************************************************************************************************
    192.168.0.128              : ok=3    changed=2    unreachable=0    failed=0   
    192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   
    
    [root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf'
    192.168.0.128 | SUCCESS | rc=0 >>
    server {
    listen 8080
    }
    
    192.168.0.218 | SUCCESS | rc=0 >>
    server {
    listen 8080
    }
    
    [root@test ~]#
    

      示例:模板文件中if的用法

    [root@test ~]#tree
    .
    ├── temnginx.yml
    └── templates
        └── nginx.conf.j2
    
    1 directory, 2 files
    [root@test ~]#cat temnginx.yml 
    ---
    - hosts: websers
      remote_user: root
      vars:
        nginx_vhosts:
          - web1:
            listen: 8080
            server_name: "web1.test.com"
            root: "/var/www/nginx/web1/"
          - web2:
            listen: 8080
            root: "/var/www/nginx/web2/"
          - web3:
            listen: 8080
            server_name: "web2.test.com"
            root: "var/www/nginx/web3/" 
      tasks:
        - name: template config to remote hosts
          template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
     
    [root@test ~]#cat templates/nginx.conf.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 %}
    [root@test ~]#
    

    生成结果:

    [root@test ~]#ansible-playbook temnginx.yml 
    
    PLAY [websers] ******************************************************************************************************
    
    TASK [Gathering Facts] **********************************************************************************************
    ok: [192.168.0.128]
    ok: [192.168.0.218]
    
    TASK [template config to remote hosts] ******************************************************************************
    changed: [192.168.0.128]
    changed: [192.168.0.218]
    
    PLAY RECAP **********************************************************************************************************
    192.168.0.128              : ok=2    changed=1    unreachable=0    failed=0   
    192.168.0.218              : ok=2    changed=1    unreachable=0    failed=0   
    
    [root@test ~]#ansible websers -m shell -a 'cat /etc/nginx/nginx.conf'
    192.168.0.128 | SUCCESS | rc=0 >>
    server {
            listen 8080
                    server_name web1.test.com
                    root /var/www/nginx/web1/
    }
    server {
            listen 8080
                    root /var/www/nginx/web2/
    }
    server {
            listen 8080
                    server_name web2.test.com
                    root var/www/nginx/web3/
    }
    
    192.168.0.218 | SUCCESS | rc=0 >>
    server {
            listen 8080
                    server_name web1.test.com
                    root /var/www/nginx/web1/
    }
    server {
            listen 8080
                    root /var/www/nginx/web2/
    }
    server {
            listen 8080
                    server_name web2.test.com
                    root var/www/nginx/web3/
    }
    
    [root@test ~]#
    

      说明:可以看到第二个server里是没有server_name,因为定义的变量列表里web2没有定义server_name

      四、playbook中使用when条件测试

      条件测试:如果需要根据变量、facts或此前任务的执行结果来作为某task执行与否的前提时需要用到条件测试,通过when语句实现,在task中使用jinja2的语法格式,when语句支持jinja2表达式语法;

    示例:

    [root@test ~]#cat test.yml 
    ---
    - hosts: all 
      remote_user: root
    
      tasks:
        - name: set hostname centos6
          hostname: name=ansible_centos6
          when: ansible_distribution_major_version == "6"
        - name: set hostname centos7
          hostname: name=ansible_centos7
          when: ansible_distribution_major_version == "7" 
    [root@test ~]#ansible all -m shell -a 'hostname'
    192.168.0.128 | SUCCESS | rc=0 >>
    localhost
    
    192.168.0.218 | SUCCESS | rc=0 >>
    localhost.localdomain
    
    192.168.0.217 | SUCCESS | rc=0 >>
    centos7
    
    [root@test ~]#ansible-playbook test.yml 
    
    PLAY [all] **********************************************************************************************************
    
    TASK [Gathering Facts] **********************************************************************************************
    ok: [192.168.0.128]
    ok: [192.168.0.218]
    ok: [192.168.0.217]
    
    TASK [set hostname centos6] *****************************************************************************************
    skipping: [192.168.0.217]
    changed: [192.168.0.218]
    changed: [192.168.0.128]
    
    TASK [set hostname centos7] *****************************************************************************************
    skipping: [192.168.0.128]
    skipping: [192.168.0.218]
    changed: [192.168.0.217]
    
    PLAY RECAP **********************************************************************************************************
    192.168.0.128              : ok=2    changed=1    unreachable=0    failed=0   
    192.168.0.217              : ok=2    changed=1    unreachable=0    failed=0   
    192.168.0.218              : ok=2    changed=1    unreachable=0    failed=0   
    
    [root@test ~]#ansible all -m shell -a 'hostname'
    192.168.0.128 | SUCCESS | rc=0 >>
    ansible_centos6
    
    192.168.0.218 | SUCCESS | rc=0 >>
    ansible_centos6
    
    192.168.0.217 | SUCCESS | rc=0 >>
    ansible_centos7
    
    [root@test ~]#
    

      说明:以上playbook利用when语句判断系统版本号,实现了通过不同的系统版本号,设置不同的主机名。

      五、playbook迭代with_items

      迭代:当有需要重复性执行的任务时,可使用迭代机制;对迭代项的引用,ansible有固定不变的变量,名为“item”;要在task中使用with_items给定要迭代的元素列表,列表格式可以为字符串、字典。

    示例:批量创建用户

    [root@test ~]#cat adduser.yml 
    ---
    - hosts: websers
      remote_user: root
      
      tasks:
        - name: add users
          user: name={{ item }} state=present home=/home/{{ item }} groups=root,bin,wheel
          with_items:
            - user1
            - user2
            - user3
    [root@test ~]#ansible-playbook adduser.yml
    
    PLAY [websers] ******************************************************************************************************
    
    TASK [Gathering Facts] **********************************************************************************************
    ok: [192.168.0.128]
    ok: [192.168.0.218]
    
    TASK [add users] ****************************************************************************************************
    changed: [192.168.0.128] => (item=user1)
    changed: [192.168.0.218] => (item=user1)
    changed: [192.168.0.128] => (item=user2)
    changed: [192.168.0.218] => (item=user2)
    changed: [192.168.0.128] => (item=user3)
    changed: [192.168.0.218] => (item=user3)
    
    PLAY RECAP **********************************************************************************************************
    192.168.0.128              : ok=2    changed=1    unreachable=0    failed=0   
    192.168.0.218              : ok=2    changed=1    unreachable=0    failed=0   
    
    [root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd'
    192.168.0.128 | SUCCESS | rc=0 >>
    user1:x:503:503::/home/user1:/bin/bash
    user2:x:504:504::/home/user2:/bin/bash
    user3:x:505:505::/home/user3:/bin/bash
    
    192.168.0.218 | SUCCESS | rc=0 >>
    user1:x:1213:1213::/home/user1:/bin/bash
    user2:x:1214:1214::/home/user2:/bin/bash
    user3:x:1215:1215::/home/user3:/bin/bash
    
    [root@test ~]#ansible websers -m shell -a 'id user1'           
    192.168.0.218 | SUCCESS | rc=0 >>
    uid=1213(user1) gid=1213(user1) 组=1213(user1),0(root),1(bin),10(wheel)
    
    192.168.0.128 | SUCCESS | rc=0 >>
    uid=503(user1) gid=503(user1) 组=503(user1),0(root),1(bin),10(wheel)
    
    [root@test ~]# 

    示例:迭代嵌套子变量

    [root@test ~]#cat adduser2.yml 
    ---
    - hosts: websers
      remote_user: root
      
      tasks:
        - name: create groups
          group: name={{ item }}
          with_items:
            - group1
            - group2
            - group3
        - name: create users
          user: name={{ item.name }} group={{ item.group }} state=present
          with_items:
            - {name: 'test1',group: 'group1'}
            - {name: 'test2',group: 'group2'}
            - {name: 'test3',group: 'group3'}
    [root@test ~]#ansible-playbook adduser2.yml
    
    PLAY [websers] ******************************************************************************************************
    
    TASK [Gathering Facts] **********************************************************************************************
    ok: [192.168.0.128]
    ok: [192.168.0.218]
    
    TASK [create groups] ************************************************************************************************
    changed: [192.168.0.128] => (item=group1)
    changed: [192.168.0.218] => (item=group1)
    changed: [192.168.0.128] => (item=group2)
    changed: [192.168.0.218] => (item=group2)
    changed: [192.168.0.128] => (item=group3)
    changed: [192.168.0.218] => (item=group3)
    
    TASK [create users] *************************************************************************************************
    changed: [192.168.0.128] => (item={u'group': u'group1', u'name': u'test1'})
    changed: [192.168.0.218] => (item={u'group': u'group1', u'name': u'test1'})
    changed: [192.168.0.128] => (item={u'group': u'group2', u'name': u'test2'})
    changed: [192.168.0.218] => (item={u'group': u'group2', u'name': u'test2'})
    changed: [192.168.0.128] => (item={u'group': u'group3', u'name': u'test3'})
    changed: [192.168.0.218] => (item={u'group': u'group3', u'name': u'test3'})
    
    PLAY RECAP **********************************************************************************************************
    192.168.0.128              : ok=3    changed=2    unreachable=0    failed=0   
    192.168.0.218              : ok=3    changed=2    unreachable=0    failed=0   
    
    [root@test ~]#ansible websers -m shell -a 'tail -3 /etc/passwd'
    192.168.0.128 | SUCCESS | rc=0 >>
    test1:x:506:506::/home/test1:/bin/bash
    test2:x:507:507::/home/test2:/bin/bash
    test3:x:508:508::/home/test3:/bin/bash
    
    192.168.0.218 | SUCCESS | rc=0 >>
    test1:x:1216:1216::/home/test1:/bin/bash
    test2:x:1217:1217::/home/test2:/bin/bash
    test3:x:1218:1218::/home/test3:/bin/bash
    
    [root@test ~]#ansible websers -m shell -a 'id test1'           
    192.168.0.218 | SUCCESS | rc=0 >>
    uid=1216(test1) gid=1216(group1) 组=1216(group1)
    
    192.168.0.128 | SUCCESS | rc=0 >>
    uid=506(test1) gid=506(group1) 组=506(group1)
    
    [root@test ~]#ansible websers -m shell -a 'id test2'
    192.168.0.128 | SUCCESS | rc=0 >>
    uid=507(test2) gid=507(group2) 组=507(group2)
    
    192.168.0.218 | SUCCESS | rc=0 >>
    uid=1217(test2) gid=1217(group2) 组=1217(group2)
    
    [root@test ~]#ansible websers -m shell -a 'id test3'
    192.168.0.128 | SUCCESS | rc=0 >>
    uid=508(test3) gid=508(group3) 组=508(group3)
    
    192.168.0.218 | SUCCESS | rc=0 >>
    uid=1218(test3) gid=1218(group3) 组=1218(group3)
    
    [root@test ~]#
    

      说明:以上playbook实现了对应用户创建时加入对应的组里

  • 相关阅读:
    SQL Server中游标的使用
    SQL Server之内连接 左连接 右连接 全连接 交叉连接
    C#后台格式化JSON字符串显示
    使用反射、特性简化代码
    JQuery方法扩展
    .NET强制进行即时垃圾回收
    .NET中的Queue和Stack
    如何解决firefox下window.event的问题
    【JS对象、JSON字符串】之间的相互转换
    Javascript模块化编程(一):模块的写法
  • 原文地址:https://www.cnblogs.com/qiuhom-1874/p/11882025.html
Copyright © 2011-2022 走看看