GNU/Linux >> Linux Esercitazione >  >> Linux

RHCE Ansible Series #7:Modelli Jinja2

Nel tutorial precedente sul processo decisionale in Ansible, hai imparato come apportare semplici modifiche ai file utilizzando il blockinfile o in linea Moduli sensibili.

In questo tutorial imparerai come usare Jinja2 motore di template per eseguire modifiche ai file più complesse e dinamiche.

Imparerai come accedere a variabili e fatti nei modelli Jinja2. Inoltre, imparerai come utilizzare le istruzioni condizionali e le strutture di loop in Jinja2.

Per provare gli esempi in questo tutorial, dovresti seguire l'intera serie di tutorial di RHCE Ansible nell'ordine corretto.

Accesso alle variabili in Jinja2

Ansible cercherà i file modello jinja2 nella directory del tuo progetto o in una directory denominata templates nella directory del tuo progetto.

Creiamo una directory di modelli per mantenere le cose più pulite e organizzate:

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

Ora crea il tuo primo modello Jinja2 con il nome index.j2 :

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

Nota che i nomi dei file dei modelli Jinja2 devono terminare con l'estensione .j2.

Il nome host_inventario è un'altra variabile incorporata di Ansible (aka speciale o magica) che fa riferimento a quell'host "corrente" che viene ripetuto nel gioco. Il messaggio_server_web è una variabile che definirai nel tuo playbook.

Ora torna indietro di un passo alla directory del tuo progetto e crea il seguente 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

Tieni presente che httpd il pacchetto era già installato in un tutorial precedente.

In questo playbook, devi prima assicurarti che Apache sia in esecuzione nella prima attività Start httpd . Quindi utilizza il modello modulo nella seconda attività Create index.html utilizzando Jinja2 per elaborare e trasferire index.j2 File modello Jinja2 che hai creato nella destinazione /var/www/html/index.html .

Vai avanti ed esegui il playbook:

[[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

Tutto sembra a posto finora; eseguiamo un rapido comando Ansible ad hoc per controllare il contenuto di index.html sui nodi dei server 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.

Sorprendente! Nota come Jinja2 è stato in grado di rilevare i valori di inventory_hostname variabile incorporata e il messaggio_server_web variabile nel tuo playbook.

Puoi anche usare il ricciolo comando per vedere se ricevi una risposta da entrambi i server 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.

Accesso ai fatti in Jinja2

Puoi accedere ai fatti nei modelli Jinja2 nello stesso modo in cui accedi ai fatti dal tuo playbook.

Per dimostrare, passa ai tuoi modelli directory e crea il info.j2 File Jinja2 con i seguenti contenuti:

[[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'] }}

Nota che info.j2 accede a otto diversi fatti. Ora torna alla directory del tuo progetto e crea il seguente server-info.yml playbook:

[[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

Nota che stai creando /tmp/server-info.txt su tutti gli host in base a info.j2 file modello. Vai avanti ed esegui il playbook:

[[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

Tutto sembra a posto! Ora eseguiamo un rapido comando ad hoc per ispezionare il contenuto di /tmp/server-info.txt file su uno dei nodi:

[[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

Come puoi vedere, Jinja2 è stato in grado di accedere ed elaborare tutti i fatti.

Dichiarazioni condizionali in Jinja2

Puoi utilizzare il se dichiarazione condizionale in Jinja2 per testare varie condizioni e confrontare variabili. Ciò ti consente di determinare il flusso di esecuzione del modello di file in base alle condizioni di test.

Per dimostrare, vai ai tuoi modelli directory e creare il seguente selinux.j2 modello:

[[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 prima istruzione nel modello crea una nuova variabile selinux_statusand imposta il suo valore su ansible_facts['selinux']['status'] .

Quindi usi selinux_status nel tuo se condizione di test per determinare se SELinux è abilitato, disabilitato o non installato. In ciascuno dei tre diversi casi, viene visualizzato un messaggio che riflette lo stato di Selinux.

Nota come il se dichiarazione in Jinja2 imita se di Python dichiarazione; non dimenticare di utilizzare {% endif %} .

Ora torna alla directory del tuo progetto e crea il seguente selinux-status.yml playbook:

[[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

Vai avanti ed esegui il playbook:

[[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  

Dall'output del playbook; puoi vedere che SELinux è abilitato su entrambi i node1 e nodo3 . Ho disabilitato SELinux su node2 prima di eseguire il playbook e node4 non ha SELinux installato perché Ubuntu usa AppArmor invece di SELinux.

Infine, puoi eseguire il seguente comando ad hoc per ispezionare il contenuto di selinux.out su tutti gli host gestiti:

[[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"

Looping in Jinja2

Puoi utilizzare per istruzione in Jinja2 per scorrere gli elementi in un elenco, un intervallo, ecc. Ad esempio, il seguente ciclo for iterarà sui numeri nell'intervallo(1,11) e quindi visualizzerà i numeri da 1->10:

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

Nota come il ciclo for in Jinja2 imita la sintassi del ciclo for di Python; ancora una volta non dimenticare di terminare il ciclo con {% endfor %} .

Ora creiamo un esempio completo che mostra la potenza dei loop for in Jinja2. Passa alla directory dei modelli e crea il seguente hosts.j2 file modello:

[[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 %}

Nota qui che hai utilizzato una nuova variabile speciale (magica) incorporata hostvars che è fondamentalmente un dizionario che contiene tutti gli host nell'inventario e le variabili a loro assegnate.

Hai ripetuto su tutti gli host nel tuo inventario e poi su ogni host; hai visualizzato il valore di tre variabili:

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

Nota anche che devi includere queste tre variabili sulla stessa riga una accanto all'altra in modo che corrispondano al formato di /etc/hosts file.

Ora torna alla directory dei tuoi progetti e crea il seguente local-dns.yml playbook:

[[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

Quindi vai avanti ed esegui il playbook:

[[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 

Tutto sembra a posto finora; ora esegui il seguente comando ad hoc per verificare che /etc/hosts il file è aggiornato correttamente su 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

Perfetto! Sembra formattato correttamente come previsto.

Spero che ora ti rendi conto della potenza dei modelli Jinja2 in Ansible. Resta sintonizzato per il prossimo tutorial in cui imparerai a proteggere informazioni e file sensibili utilizzando Ansible Vault.


Linux
  1. Decostruire un playbook Ansible

  2. Comprendere YAML per Ansible

  3. RHCE Ansible Series #8:Crittografia dei contenuti con Ansible Vault

  4. RHCE Ansible Series #6:Decision Making in Ansible

  5. RHCE Ansible Series #5:Ansible Loops

Come utilizzare il modello Jinja2 in Ansible

Un'introduzione ai fatti Ansible

RHCE Ansible Series #2:Esecuzione di comandi ad hoc

RHCE Ansible Series #1:Saluta Ansible

RHCE Ansible Series #3:Ansible Playbook

RHCE Ansible Series #12:Risoluzione dei problemi di Ansible