GNU/Linux >> Tutoriales Linux >  >> Linux

Serie RHCE Ansible n.º 7:Plantillas Jinja2

En el tutorial anterior sobre la toma de decisiones en Ansible, aprendió cómo realizar modificaciones de archivos simples mediante el uso de blockinfile. o en línea Módulos de Ansible.

En este tutorial, aprenderá a usar Jinja2 motor de plantillas para realizar modificaciones de archivos más complejas y dinámicas.

Aprenderá a acceder a variables y hechos en las plantillas de Jinja2. Además, aprenderá a usar sentencias condicionales y estructuras de bucle en Jinja2.

Para probar los ejemplos de este tutorial, debe seguir toda la serie de tutoriales de RHCE Ansible en el orden correcto.

Accediendo a Variables en Jinja2

Ansible buscará archivos de plantilla jinja2 en el directorio de su proyecto o en un directorio llamado templates. en el directorio de su proyecto.

Vamos a crear un directorio de plantillas para mantener las cosas más limpias y organizadas:

[[email protected] plays]$ mkdir templates
[[email protected] plays]$ cd templates/

Ahora cree su primera plantilla Jinja2 con el nombre index.j2 :

[[email protected] templates]$ cat index.j2 
A message from {{ inventory_hostname }}
{{ webserver_message }}

Tenga en cuenta que los nombres de archivo de las plantillas Jinja2 deben terminar con la extensión .j2.

El nombre_de_host_de_inventario es otra variable integrada de Ansible (también conocida como especial o mágica) que hace referencia al host "actual" que se está iterando en el juego. El mensaje_del_servidor_web es una variable que definirá en su libro de jugadas.

Ahora retroceda un paso al directorio de su proyecto y cree el siguiente check-apache.yml :

[[email protected] plays]$ cat check-apache.yml 
---
- name: Check if Apache is Working
  hosts: webservers
  vars:
    webserver_message: "I am running to the finish line."
  tasks:
    - name: Start httpd
      service:
        name: httpd
        state: started

    - name: Create index.html using Jinja2
      template:
        src: index.j2
        dest: /var/www/html/index.html

Tenga en cuenta que httpd el paquete ya estaba instalado en un tutorial anterior.

En este libro de jugadas, primero asegúrese de que Apache se esté ejecutando en la primera tarea Start httpd . Luego use la plantilla módulo en la segunda tarea Create index.html usando Jinja2 para procesar y transferir el index.j2 Archivo de plantilla Jinja2 que creó para el destino /var/www/html/index.html .

Continúe y ejecute el libro de jugadas:

[[email protected] plays]$ ansible-playbook check-apache.yml 

PLAY [Check if Apache is Working] **********************************************

TASK [Gathering Facts] *********************************************************
ok: [node3]
ok: [node2]

TASK [Start httpd] *************************************************************
ok: [node2]
ok: [node3]

TASK [Create index.html using Jinja2] ******************************************
changed: [node3]
changed: [node2]

PLAY RECAP *********************************************************************
node2                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    
node3                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0

Todo se ve bien hasta ahora; ejecutemos un comando rápido ad-hoc de Ansible para verificar el contenido de index.html en los nodos de los servidores web:

[[email protected] plays]$ ansible webservers -m command -a "cat /var/www/html/index.html"
node3 | CHANGED | rc=0 >>
A message from node3
I am running to the finish line.
node2 | CHANGED | rc=0 >>
A message from node2
I am running to the finish line.

¡Increíble! Observe cómo Jinja2 pudo recoger los valores de inventory_hostname variable integrada y el webserver_message variable en su libro de jugadas.

También puedes usar el curl comando para ver si obtiene una respuesta de ambos servidores web:

[[email protected] plays]$ curl node2.linuxhandbook.local
A message from node2
I am running to the finish line.
[[email protected] plays]$ curl node3.linuxhandbook.local
A message from node3
I am running to the finish line.

Acceder a los hechos en Jinja2

Puede acceder a los datos en las plantillas de Jinja2 de la misma manera que accede a los datos de su libro de jugadas.

Para demostrarlo, cambie a sus plantillas directorio y cree el info.j2 Archivo Jinja2 con los siguientes contenidos:

[[email protected] templates]$ cat info.j2 
Server Information Summary
--------------------------

hostname={{ ansible_facts['hostname'] }}
fqdn={{ ansible_facts['fqdn'] }}
ipaddr={{ ansible_facts['default_ipv4']['address'] }}
distro={{ ansible_facts['distribution'] }}
distro_version={{ ansible_facts['distribution_version'] }}
nameservers={{ ansible_facts['dns']['nameservers'] }}
totalmem={{ ansible_facts['memtotal_mb'] }}
freemem={{ ansible_facts['memfree_mb'] }}

Observe que info.j2 accede a ocho hechos diferentes. Ahora regrese al directorio de su proyecto y cree el siguiente server-info.yml libro de jugadas:

[[email protected] plays]$ cat server-info.yml 
---
- name: Server Information Summary
  hosts: all
  tasks:
   - name: Create server-info.txt using Jinja2
     template:
       src: info.j2
       dest: /tmp/server-info.txt

Observe que está creando /tmp/server-info.txt en todos los hosts basados ​​en info.j2 archivo de plantilla. Continúe y ejecute el libro de jugadas:

[[email protected] plays]$ ansible-playbook server-info.yml 

PLAY [Server Information Summary] *******************************************

TASK [Gathering Facts] **********************************
ok: [node4]
ok: [node1]
ok: [node3]
ok: [node2]

TASK [Create server-info.txt using Jinja2] ********
changed: [node4]
changed: [node1]
changed: [node3]
changed: [node2]

PLAY RECAP *************************
node1                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    
node2                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    
node3                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    
node4                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0

¡Todo se ve bien! Ahora ejecutemos un comando rápido ad-hoc para inspeccionar el contenido de /tmp/server-info.txt archivo en uno de los nodos:

[[email protected] plays]$ ansible node1 -m command -a "cat /tmp/server-info.txt"
node1 | CHANGED | rc=0 >>
Server Information Summary
--------------------------

hostname=node1
fqdn=node1.linuxhandbook.local
ipaddr=10.0.0.5
distro=CentOS
distro_version=8.2
nameservers=['168.63.129.16']
totalmem=1896
freemem=1087

Como puede ver, Jinja2 pudo acceder y procesar todos los hechos.

Declaraciones condicionales en Jinja2

Puede utilizar el si declaración condicional en Jinja2 para probar varias condiciones y comparar variables. Esto le permite determinar el flujo de ejecución de su plantilla de archivo de acuerdo con sus condiciones de prueba.

Para demostrarlo, ve a tus plantillas directorio y cree el siguiente selinux.j2 plantilla:

[[email protected] templates]$ cat selinux.j2 
{% set selinux_status = ansible_facts['selinux']['status'] %}

{% if selinux_status == "enabled" %}
	"SELINUX IS ENABLED"
{% elif selinux_status == "disabled" %}
	"SELINUX IS DISABLED"
{% else %}
	"SELINUX IS NOT AVAILABLE"
{% endif %}

La primera declaración en la plantilla crea una nueva variable selinux_statusand establezca su valor en ansible_facts['selinux']['status'] .

Luego usa selinux_status en tu si condición de prueba para determinar si SELinux está habilitado, deshabilitado o no instalado. En cada uno de los tres casos diferentes, muestra un mensaje que refleja el estado de Selinux.

Observe cómo el si declaración en Jinja2 imita el if de Python declaración; simplemente no olvides usar {% endif %} .

Ahora regrese al directorio de su proyecto y cree el siguiente selinux-status.yml libro de jugadas:

[[email protected] plays]$ cat selinux-status.yml 
---
- name: Check SELinux Status
  hosts: all
  tasks:
    - name: Display SELinux Status
      debug:
        msg: "{{ ansible_facts['selinux']['status'] }}"

    - name: Create selinux.out using Jinja2
      template:
        src: selinux.j2
        dest: /tmp/selinux.out

Continúe y ejecute el libro de jugadas:

[[email protected] plays]$ ansible-playbook selinux-status.yml 

PLAY [Check SELinux Status] ****************************************************

TASK [Gathering Facts] *********************************************************
ok: [node4]
ok: [node2]
ok: [node3]
ok: [node1]

TASK [Display SELinux Status] **************************************************
ok: [node1] => {
    "msg": "enabled"
}
ok: [node2] => {
    "msg": "disabled"
}
ok: [node3] => {
    "msg": "enabled"
}
ok: [node4] => {
    "msg": "Missing selinux Python library"
}

TASK [Create selinux.out using Jinja2] *****************************************
changed: [node4]
changed: [node1]
changed: [node3]
changed: [node2]

PLAY RECAP *********************************************************************
node1                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    
node2                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    
node3                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0    node4                      : ok=3    changed=1    unreachable=0    failed=0    skipped=0  

De la salida del libro de jugadas; puede ver que SELinux está habilitado en ambos node1 y nodo3 . Desactivé SELinux en node2 antes de ejecutar el libro de jugadas y node4 no tiene SELinux instalado porque Ubuntu usa AppArmor en lugar de SELinux.

Finalmente, puede ejecutar el siguiente comando ad-hoc para inspeccionar el contenido de selinux.out en todos los hosts gestionados:

[[email protected] plays]$ ansible all -m command -a "cat /tmp/selinux.out"
node4 | CHANGED | rc=0 >>

	"SELINUX IS NOT AVAILABLE"
 
node2 | CHANGED | rc=0 >>

	"SELINUX IS DISABLED"
 
node3 | CHANGED | rc=0 >>

	"SELINUX IS ENABLED"
 
node1 | CHANGED | rc=0 >>

	"SELINUX IS ENABLED"

Bucle en Jinja2

Puede utilizar para declaración en Jinja2 para recorrer elementos en una lista, rango, etc. Por ejemplo, el siguiente ciclo iterará sobre los números en el rango (1,11) y por lo tanto mostrará los números de 1->10:

{% for i in range(1,11) %}
	Number {{ i }}
{% endfor %}

Observe cómo el bucle for en Jinja2 imita la sintaxis del bucle for de Python; de nuevo, no olvides finalizar el ciclo con {% endfor %} .

Ahora vamos a crear un ejemplo completo que muestre el poder de los bucles for en Jinja2. Cambie a su directorio de plantillas y cree el siguiente hosts.j2 archivo de plantilla:

[[email protected] templates]$ cat hosts.j2 
{% for host in groups['all'] %}
{{ hostvars[host].ansible_facts.default_ipv4.address }}  {{ hostvars[host].ansible_facts.fqdn }}  {{ hostvars[host].ansible_facts.hostname }}
{% endfor %}

Observe aquí que usó una nueva variable especial (mágica) incorporada hostvars que es básicamente un diccionario que contiene todos los hosts en el inventario y las variables asignadas a ellos.

Hizo iteraciones sobre todos los hosts en su inventario y luego para cada host; mostraste el valor de tres variables:

  1. {{ hostvars[host].ansible_facts.default_ipv4.address }}
  2. {{ hostvars[host].ansible_facts.fqdn }}
  3. {{ hostvars[host].ansible_facts.hostname }}

Tenga en cuenta también que debe incluir esas tres variables en la misma línea una al lado de la otra para que coincidan con el formato de /etc/hosts archivo.

Ahora regrese a su directorio de proyectos y cree el siguiente local-dns.yml libro de jugadas:

[[email protected] plays]$ cat local-dns.yml 
---
- name: Dynamically Update /etc/hosts File
  hosts: all
  tasks:
    - name: Update /etc/hosts using Jinja2
      template:
        src: hosts.j2
        dest: /etc/hosts

Luego continúe y ejecute el libro de jugadas:

[[email protected] plays]$ ansible-playbook local-dns.yml 

PLAY [Dynamically Update /etc/hosts File] *********************************************

TASK [Gathering Facts] ***************************
ok: [node4]
ok: [node2]
ok: [node1]
ok: [node3]

TASK [Update /etc/hosts using Jinja2] ***********************************************
changed: [node4]
changed: [node3]
changed: [node1]
changed: [node2]

PLAY RECAP **********************
node1                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    
node2                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    
node3                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0    
node4                      : ok=2    changed=1    unreachable=0    failed=0    skipped=0 

Todo se ve bien hasta ahora; ahora ejecute el siguiente comando ad-hoc para verificar que /etc/hosts el archivo se actualizó correctamente en node1 :

[[email protected] plays]$ ansible node1 -m command -a "cat /etc/hosts"
node1 | CHANGED | rc=0 >>
10.0.0.5  node1.linuxhandbook.local  node1
10.0.0.6  node2.linuxhandbook.local  node2
10.0.0.7  node3.linuxhandbook.local  node3
10.0.0.8  node4.linuxhandbook.local  node4

¡Perfecto! Se ve correctamente formateado como esperabas.

Espero que ahora se dé cuenta del poder de las plantillas Jinja2 en Ansible. Estén atentos al próximo tutorial en el que aprenderá a proteger información y archivos confidenciales con Ansible Vault.


Linux
  1. Deconstruyendo un libro de jugadas de Ansible

  2. Comprender YAML para Ansible

  3. RHCE Ansible Series #8:Cifrado de contenido con Ansible Vault

  4. RHCE Ansible Series #6:Toma de decisiones en Ansible

  5. Serie RHCE Ansible n.º 5:bucles Ansible

Cómo usar la plantilla Jinja2 en Ansible

Una introducción a los hechos de Ansible

Serie RHCE Ansible n.º 2:Ejecución de comandos ad-hoc

Serie RHCE Ansible n.º 1:Salude a Ansible

Serie RHCE Ansible n.º 3:Manuales de Ansible

Serie RHCE Ansible n.º 12:solución de problemas de Ansible