V předchozím tutoriálu o rozhodování v Ansible jste se naučili, jak provádět jednoduché úpravy souborů pomocí blockinfile nebo inline Ansible moduly.
V tomto tutoriálu se naučíte používat Jinja2 šablonovací engine k provádění složitějších a dynamičtějších úprav souborů.
Dozvíte se, jak přistupovat k proměnným a faktům v šablonách Jinja2. Dále se naučíte, jak používat podmíněné příkazy a smyčkové struktury v Jinja2.
Chcete-li vyzkoušet příklady v tomto tutoriálu, měli byste sledovat celou sérii tutoriálů RHCE Ansible ve správném pořadí.
Přístup k proměnným v Jinja2
Ansible vyhledá soubory šablon jinja2 ve vašem projektovém adresáři nebo v adresáři s názvem templates v adresáři vašeho projektu.
Pojďme vytvořit adresář šablon, aby byla věc čistší a organizovanější:
[[email protected] plays]$ mkdir templates
[[email protected] plays]$ cd templates/
Nyní vytvořte svou první šablonu Jinja2 s názvem index.j2 :
[[email protected] templates]$ cat index.j2
A message from {{ inventory_hostname }}
{{ webserver_message }}
Všimněte si, že názvy souborů šablon Jinja2 musí končit příponou .j2.
název_hostitele inventáře je další vestavěná proměnná Ansible (neboli speciální nebo magická), která odkazuje na toho „aktuálního“ hostitele, který je ve hře iterován. zpráva_webového_serveru je proměnná, kterou definujete ve svém playbooku.
Nyní se vraťte o krok zpět do adresáře projektu a vytvořte následující 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
Všimněte si, že httpd balíček byl již nainstalován v předchozím kurzu.
V této příručce se nejprve ujistěte, že Apache běží v první úloze Start httpd
. Poté použijte šablonu modulu ve druhé úloze Create index.html
pomocí Jinja2 ke zpracování a přenosu index.j2 Soubor šablony Jinja2, který jste vytvořili, do cílového umístění /var/www/html/index.html .
Pokračujte a spusťte příručku:
[[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
Všechno zatím vypadá dobře; spusťte rychlý ad-hoc příkaz Ansible ke kontrole obsahu index.html na uzlech webových serverů:
[[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.
Úžasný! Všimněte si, jak Jinja2 dokázala získat hodnoty inventory_hostname vestavěná proměnná a zpráva_webového_serveru proměnná ve vaší příručce.
Můžete také použít zvlnění příkaz, abyste zjistili, zda dostanete odpověď z obou webových serverů:
[[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.
Přístup k faktům v Jinja2
K faktům v šablonách Jinja2 můžete přistupovat stejným způsobem jako k faktům z vaší příručky.
Chcete-li to ukázat, přejděte na své šablony a vytvořte info.j2 Jinja2 soubor s následujícím obsahem:
[[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'] }}
Všimněte si, že info.j2 přistupuje k osmi různým faktům. Nyní se vraťte do adresáře projektu a vytvořte následující server-info.yml příručka:
[[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
Všimněte si, že vytváříte /tmp/server-info.txt na všech hostitelích založených na info.j2 soubor šablony. Pokračujte a spusťte příručku:
[[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
Všechno vypadá dobře! Nyní spusťte rychlý ad-hoc příkaz ke kontrole obsahu /tmp/server-info.txt soubor na jednom z uzlů:
[[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
Jak můžete vidět, Jinja2 měl přístup ke všem faktům a zpracoval je.
Podmíněné příkazy v Jinja2
Můžete použít pokud podmíněný příkaz v Jinja2 pro testování různých podmínek a porovnávání proměnných. To vám umožní určit tok provádění šablony souboru podle vašich testovacích podmínek.
Chcete-li to předvést, přejděte do šablon a vytvořte následující selinux.j2 šablona:
[[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 %}
První příkaz v šabloně vytvoří novou proměnnou selinux_statusand
nastavte jeho hodnotu na ansible_facts['selinux']['status']
.
Poté použijete selinux_status
ve vašem pokud testovací podmínky pro zjištění, zda SELinux je povoleno, zakázáno nebo není nainstalováno. V každém ze tří různých případů zobrazíte zprávu, která odráží stav Selinuxu.
Všimněte si, jak pokud příkaz v Jinja2 napodobuje if Pythonu prohlášení; jen nezapomeňte použít {% endif %}
.
Nyní se vraťte do adresáře projektu a vytvořte následující selinux-status.yml příručka:
[[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
Pokračujte a spusťte příručku:
[[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
Z výstupu playbooku; můžete vidět, že SELinux je povolen na obou uzlech1 a uzel3 . Zakázal jsem SELinux na node2 před spuštěním playbooku a node4 nemá nainstalovaný SELinux, protože Ubuntu místo SELinux používá AppArmor.
Nakonec můžete spustit následující ad-hoc příkaz ke kontrole obsahu selinux.out na všech spravovaných hostitelích:
[[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"
Otáčení v Jinja2
Můžete použít pro příkaz v Jinja2 pro opakování položek v seznamu, rozsahu atd. Například následující cyklus for bude opakovat čísla v rozsahu (1,11) a zobrazí tedy čísla od 1->10:
{% for i in range(1,11) %}
Number {{ i }}
{% endfor %}
Všimněte si, jak cyklus for v Jinja2 napodobuje syntaxi cyklu for Pythonu; znovu nezapomeňte ukončit smyčku pomocí {% endfor %}
.
Nyní vytvoříme úplný příklad, který ukazuje sílu smyček for v Jinja2. Přejděte do adresáře šablon a vytvořte následující hosts.j2 soubor šablony:
[[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 %}
Všimněte si, že jste použili novou vestavěnou speciální (magickou) proměnnou hostvars což je v podstatě slovník, který obsahuje všechny hostitele v inventáři a proměnné k nim přiřazené.
Iterovali jste všechny hostitele ve svém inventáři a poté pro každého hostitele; zobrazili jste hodnotu tří proměnných:
- {{ hostvars[host].ansible_facts.default_ipv4.address }}
- {{ hostvars[host].ansible_facts.fqdn }}
- {{ hostvars[host].ansible_facts.hostname }}
Všimněte si také, že tyto tři proměnné musíte zahrnout na stejný řádek vedle sebe, aby odpovídaly formátu souboru /etc/hosts soubor.
Nyní se vraťte do adresáře projektů a vytvořte následující local-dns.yml příručka:
[[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
Pak pokračujte a spusťte příručku:
[[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
Všechno zatím vypadá dobře; nyní spusťte následující ad-hoc příkaz k ověření, že /etc/hosts soubor je správně aktualizován na uzlu1 :
[[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
Perfektní! Vypadá správně naformátovaný, jak jste očekávali.
Doufám, že si nyní uvědomujete sílu šablon Jinja2 v Ansible. Zůstaňte naladěni na další tutoriál, kde se naučíte chránit citlivé informace a soubory pomocí Ansible Vault.