Resources attached to the Road To DevOps tutorial https://blog.noobtoroot.xyz/road-to-devops/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

517 lines
9.0 KiB

<!-- .slide: data-state="nologo-slide" style="text-align: center" -->
![Logo Ansible](images/logo-ansible.svg)
# Templates
## Syntaxe jinja2
* Documentation
- Jinja language :
http://jinja.pocoo.org/docs/
- Template formatting :
http://jinja.pocoo.org/docs/templates/
## Principe
* On créé les fichiers dans le dossier `templates` du Role.
* On indique l'emplacement des zones variables à l'aide de la syntaxe `{{ ma_variable }}`.
`templates/httpd.conf.j2`
```none
...
Listen {{ apache_port }}
DocumentRoot {{ apache_document_root }}
ServerName {{ apache_server_name }}
ServerAdmin {{ apache_server_admin }}
...
```
On utilise le module _template_
<!-- .slide: data-state="medium-code" -->
```yaml
- hosts: web
vars:
apache_port: 80
apache_document_root: /var/www/html
apache_server_name: my-server
apache_server_admin: admin@localhost
tasks:
- name: Deploy Apache configuration
template:
src: templates/httpd.conf.j2
dest: /etc/http/httpd.conf
owner: apache
group: apache
mode: 0600
```
Les variables sont automatiquement injectées dans le fichier sur la cible.
## Exemple pour une configuration du service NTP
<!-- .slide: data-state="small-code" -->
`./group_vars/all`
```none
ntp_servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
- 3.pool.ntp.org
```
`./roles/ntp/templates/ntp.conf.j2`
```none
...
{% for server in ntp_servers %}
server {{ server }}
{% endfor %}
...
```
`./roles/ntp/tasks/main.yaml`
```yaml
- name: Install NTP package
apt:
name: "ntp"
- name: Configure NTP
template:
src: ntp.conf.j2
dest: "/etc/ntp.conf"
owner: "root"
group: "root"
mode: 0644
notify: Restart ntp service
```
## Contrôle conditionnel
```none
{% if condition %}
do_some_thing
{% elif condition2 %}
do_another_thing
{% else %}
do_something_else
{% endif %}
```
## Filtres
Les variables peuvent être modifiées par des filtres.
<small>https://docs.ansible.com/ansible/playbooks_filters.html</small>
### Filtres Jinja2
* Les filtres Ansible reposent sur Jinja2.
* Ils sont utilisés pour transformer des données.
* Les filtres peuvent être chaînés.
* Il est possible de créer des filtres personnalisés.
### Fixer une valeur par défaut aux variables non-définies
```none
{{ variable | default(5) }}
```
### Formater des données
```none
{{ variable | to_json }}
{{ variable | to_yaml }}
```
```none
{{ variable | from_json }}
{{ variable | from_yaml }}
```
### Filtres de listes
Récupérer les valeurs minimales ou maximales
```none
{{ ma_liste | min }}
{{ [3, 4, 2] | max }}
```
Eliminer les doublons
```none
{{ list1 | unique }}
```
Combiner deux listes
```none
{{ list1 | union(list2) }}
```
Obtenir la différence entre deux listes (éléments dans list1 qui n'existent pas dans list2)
```none
{{ list1 | difference(list2) }}
```
### Filtres de nombres aléatoires
Obtenir un élément au hasard parmi une liste
```none
"{{ ['a','b','c'] | random }}"
# => 'c'
```
Obtenir un nombre au hasard entre 0 et une valeur spécifiée
```none
"{{ 60 | random}} * * * * root /script/from/cron“
# => '21 * * * * root /script/from/cron'
```
Obtenir un nombre au hasard entre 0 et 100 par pas de 10
```none
{{ 101 | random(step=10) }}
# => 70
```
### Tester des adresses IP
Tester si une chaîne est une adresse IP valide
```none
{{ myvar | ipaddr }}
```
Même chose en forçant la version du protocole IP
```none
{{ myvar | ipv4 }}
{{ myvar | ipv6 }}
```
### Filtres sur la notation CIDR
```none
{{ '192.0.2.1/24' | ipaddr('address') }}
'192.0.2.1/24'
```
```none
{{ '192.0.2.1/24' | ipaddr('prefix') }}
'24'
```
<small>https://docs.ansible.com/ansible/playbooks_filters_ipaddr.html</small>
### Fonctions de hashage
Obtenir l'empreinte sha1 ou md5 d'une chaîne
```none
{{ 'test1' | hash('sha1') }}
'dba7673010f19a94af4345453005933fd511bea9'
{{ 'test1' | hash('md5') }}
'3e7705498e8be60520841409ebc69bc1'
```
<small>https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#hashing-filters</small>
<!-- .slide: data-state="medium-code" -->
Obtenir un hashage de mot de passe sha512
```none
{{ 'passwordsaresecret' | password_hash('sha512') }}
```
Obtenir un hashage de mot de passe sha256 avec salage
```none
{{ 'secretpassword' | password_hash('sha256', 'mysecretsalt') }}
```
Exemple d'utilisation dans un fichier de variables
```none
user_password: "{{ 'Mon super password' | password_hash('sha256') }}"
```
### Filtres de commentaires
Il permettent de "décorer" un texte
avec un style de commentaire.
Exemple :
```none
{{ "Hello" | comment }}
```
produit :
```none
#
# Hello
#
```
Il est possible d'appliquer
différents types de commentaires :
```none
{{ "C style" | comment('c') }}
'// C style'
```
```none
{{ "C block style" | comment('cblock') }}
'/* C block style */'
```
```none
{{ "XML style" | comment('xml') }}
'<!--XML style-->'
```
### Filtres d'URL
<!-- .slide: data-state="small-code medium-table" -->
Obtenir une sous-partie d'une URL.
```none
{{ "http://bob:1234@www.test.com:81/dir/index.html?query=term#fragment"
| urlsplit('scheme') }}
# => 'http'
```
Filtre | Résultat
- | -
urlsplit('scheme') | 'http'
urlsplit('username') | 'bob'
urlsplit('password') | '1234'
urlsplit('hostname') | 'www.test.com'
urlsplit('port') | '81'
urlsplit('path') | '/dir/index.html'
urlsplit('query') | 'query=term'
urlsplit('fragment') | 'fragment'
### Autres filtres utiles
Ajouter des guillemets pour protéger des variables
(usage shell)
```none
- shell: echo {{ string_value | quote }}
```
Retourner une valeur si un test est vrai
et une autre si il est faux
```none
{{ (name == "John") | ternary('Mr','Mme') }}
```
Concatener une liste en chaîne
```none
{{ list | join(" ") }}
```
```none
{{ list | join(",") }}
```
Obtenir le dernier élément d'un chemin
```none
{{ '/etc/foo/bar.txt' | basename }}
'bar.txt'
```
Obtenir le début d'un chemin
```none
{{ '/etc/foo/bar.txt' | dirname }}
'/etc/foo'
```
Obtenir le chemin réel d'un lien
```none
{{ path | realpath }}
```
Expanser un chemin contenant un tilde (~)
```none
{{ path | expanduser }}
```
Expanser un chemin contenant des variables d'environnement
```none
{{ path | expandvars }}
```
Découper un nom de fichier
```none
{{ path | splitext }}
```
Avec `path` == `nginx.conf` le retour sera `('nginx', '.conf')`
## Tests
`variable` is `test expression`
<small>https://docs.ansible.com/ansible/playbooks_tests.html</small>
### Tester des chaînes de caractères
<!-- .slide: data-state="small-code" -->
```yaml
vars:
url: "http://example.com/users/foo/resources/bar"
tasks:
- debug:
msg: "matched pattern 1"
when: url is match("http://example.com/users/.*/resources/.*")
- debug:
msg: "matched pattern 2"
when: url is search("/users/.*/resources/.*")
- debug:
msg: "matched pattern 3"
when: url is search("/groups/")
```
```none
TASK [debug] *****************************************************************
ok: [my-host] => { "msg": "matched pattern 1" }
TASK [debug] *****************************************************************
ok: [my-host] => { "msg": "matched pattern 2" }
TASK [debug] *****************************************************************
skipping: [my-host]
```
### Tester des numéros de version
Si `ansible_facts['distribution_version']` est supérieur ou égal à 16.04, le test retourne `True`, sinon il retourne `False`.
<!-- .slide: data-state="medium-code" -->
```none
{{ ansible_facts['distribution_version'] is version('16.04', '>=') }}
```
Opérateurs acceptés :
`<`, `lt`, `<=`, `le`, `>`, `gt`, `>=`, `ge`, `==`, `=`, `eq`, `!=`, `<>`, `ne`
### Tester des chemins
<!-- .slide: data-state="small-code" -->
```yaml
- debug:
msg: "path is a directory"
when: mypath is directory
- debug:
msg: "path is a file"
when: mypath is file
- debug:
msg: "path is a symlink"
when: mypath is link
- debug:
msg: "path already exists"
when: mypath is exists
```
Chaque tâche est effectuée ou abandonnée
en fonction du résultat du test.
### Tester le résultat final d'une tâche
```yaml
- shell: /usr/bin/foo
register: result
ignore_errors: True
- debug:
msg: "it failed"
when: result is failed
- debug:
msg: "it succeeded"
when: result is succeeded
```
## Sortir prématurément en fonction de conditions
* Le module _fail_ permet de stopper l'exécution d'un playbook si un condition n'est pas remplie.
* Dans l'exemple suivant, l'exécution s'arrête car la variable `param2` n'est pas définie.
<!-- .slide: data-state="medium-code" -->
```yaml
---
- hosts: ansible-1
vars:
- param1: "test"
tasks:
- name: 'exit if param1 or param2 are null or invalid'
fail: msg="Please enter correct Params"
when: param1 is not defined or param2 is not defined
- debug:
msg: "other tasks..."
```
## Travaux pratiques
<!-- .slide: data-state="nologo-slide" style="text-align: center" -->
![Travaux pratiques](images/tp.gif)
<small>[TP Ansible : templates](travaux-pratiques/tp-ansible-templates.html)</small>