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
517 lines
9.0 KiB
2 years ago
|
<!-- .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>
|