RHCE ansible Series # 7: Jinja2 Templates

¿Cómo estais? me llamo Luis. Os traigo un nuevo post sobre el sistema operativo mas molón. Un placer linuxeros.

Al tutorial anterior sobre la toma de decisiones a ansible, aprendisteis a hacer modificaciones de ficheros sencillas mediante el archivo blockinfile o bien en linea Módulos ansibles.

En este tutorial, aprenderá a utilizarlo Jinja2 motor de plantilla para realizar modificaciones de archivos más implicadas y dinámicas.

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

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

Acceso a variables a Jinja2

Ansible buscará archivos de plantillas jinja2 el directorio del proyecto o el directorio llamado plantillas en el directorio de su proyecto.

Creamos un directorio de plantillas para mantener las cosas más limpias y organizadas:

[elliot@control plays]$ mkdir templates
[elliot@control plays]$ cd templates/

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

[elliot@control templates]$ cat index.j2 
A message from  inventory_hostname 
 webserver_message 

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

el nom_inventari_inventari es otra variable incorporada ansible (también conocida como especial o mágica) que hace referencia al anfitrión actual ‘que se repite en la obra. el missatge_servidor web es una variable que define en su libro de juego.

Ahora haga un paso atrás en el directorio de su proyecto y cree el siguiente check-apache.yml:

[elliot@control 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 package ya estaba instalado en un tutorial anterior.

En este libro de juego, primero asegúrese de que Apache se ejecuta en la primera tarea Start httpd. A continuación, utilice el archivo plantilla en la segunda tarea Create index.html utilizando el proceso Jinja2to y transferir el archivo index.j2 Archivo de plantilla Jinja2 que ha creado al destino /var/www/html/index.html.

Siga adelante y ejecute el libro de reproducción:

[elliot@control 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 pinta hasta ahora; ejecutamos una orden rápida ansible ad-hoc para comprobar el contenido de index.html los nodos de los servidores web:

[elliot@control 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! Fíjese en cómo Jinja2 fue capaz de recoger los valores del archivo nom_inventari_inventari variable incorporada y el missatge_servidor web variable en su libro de juegos.

También puede utilizar el rizo para ver si se obtiene una respuesta de los dos servidores web:

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

Hechos de acceso a Jinja2

Puede acceder a los hechos a las plantillas Jinja2 igual que acceda a los hechos desde su libro de juego.

Para demostrar, cambie a su plantillas y cree el directorio info.j2 Archivo Jinja2 con el siguiente contenido:

[elliot@control 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'] 

Date cuenta que info.j2 accede a ocho hechos distintos. Ahora vuelva al directorio de su proyecto y cree el siguiente servidor-info.yml libro de juegos:

[elliot@control 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

Tenga en cuenta que está creando /tmp/server-info.txt en todos los anfitriones basados ​​en info.j2 archivo de plantilla. Siga adelante y ejecute el libro de reproducción:

[elliot@control 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 pinta bien! Ahora ejecutamos una orden ad-hoc rápida para inspeccionar el contenido del archivo /tmp/server-info.txt en uno de los nodos:

[elliot@control 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.

Afirmaciones condicionales a Jinja2

Puede utilizar el archivo si declaración condicional a Jinja2 para probar diversas condiciones y comparar variables. Esto le permite determinar el flujo de ejecución de la plantilla de archivo según las condiciones de prueba.

Para demostrar, vaya a su plantillas directorio y cree el siguiente selinux.j2 plantilla:

[elliot@control 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 sentencia de la plantilla crea una nueva variable selinux_statusand establece su valor a ansible_facts['selinux']['status'].

A continuación, utilice selinux_status a su si condición de prueba para determinar si SELinux está habilitado, desactivado o no instalado. En cada uno de los tres casos diferentes, se muestra un mensaje que refleja el estado de SELinux.

Fíjese en cómo si la declaración a Jinja2 imita la de Python si declaración; simplemente no se olvide de utilizar % endif %.

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

[elliot@control 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

Siga adelante y ejecute el libro de reproducción:

[elliot@control 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  

Desde la salida del libro de reproducción; puede ver que SELinux está habilitado a ambos nodo1 y node3. He desactivado SELinux activado node2 antes de ejecutar el libro de reproducción y nodo4 no tiene SELinux instalado para que Ubuntu utiliza AppArmor en lugar de SELinux.

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

[elliot@control 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 a Jinja2

Puede utilizar el archivo por instrucción a Jinja2 para hacer un recorrido por encima de elementos de una lista, rango, etc. Por ejemplo, el siguiente para bucle iterarà sobre los números de la rango (1,11)y, por tanto, mostrará los números del 1 al 10:

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

Fíjense como el bucle for de Jinja2 imita la sintaxis del bucle for de Python; de nuevo, no olvide terminar el bucle con % endfor %.

Ahora creamos un ejemplo completo que muestra el poder de los bucles de Jinja2. Cambie el directorio de plantillas y cree el siguiente hosts.j2 archivo de plantilla:

[elliot@control 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 %

Fíjense aquí que ha utilizado una nueva variable especial (mágica) incorporada hostvars que básicamente es un diccionario que contiene todos los hosts del inventario y las variables que se les asignan.

Ha iterado por todos los anfitriones de su inventario y luego para cada anfitrión; mostró 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 estas tres variables en la misma línea una al lado de la otra para coincidir con el formato del archivo / Etc / hosts dossier.

Ahora introduzca el directorio de proyectos y cree el siguiente local-dns.yml libro de juegos:

[elliot@control 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

A continuación, ejecute el libro de juego:

[elliot@control 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 pinta hasta ahora; ahora ejecute el ad-hoc siguiente para verificarlo / Etc / hosts el archivo se actualiza correctamente el nodo1:

[elliot@control 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! Parece tener un formato adecuado tal como esperaba.

Espero que ahora se da cuenta del poder de las plantillas Jinja2 a ansible. Estad atentos al próximo tutorial donde aprenderás a proteger la información y los archivos confidenciales mediante ansible Vault.

El Blog lo escribimos para colaborar y servir de referencia a la gente Linux. Esperamos que os guste.

Leave a Reply