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.

386 lines
9.9 KiB

<!-- .slide: data-state="nologo-slide" style="text-align: center" -->
![Logo Ansible](images/logo-ansible.svg)
# Structures de contrôle
## _Facts_
* Variables délivrées par le système distant :
- Adresses IP
- Système d'exploitation
- ...
## Facts - module setup
* Liste des informations disponibles : module _setup_
<!-- .slide: data-state="medium-code" -->
```none
$ ansible my-host -i ./hosts -m setup
my-host | SUCCESS => {
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"10.6.214.74"
],
"ansible_all_ipv6_addresses": [
"fe80::250:56ff:fe9d:1aaa"
],
"ansible_architecture": "x86_64",
...
```
### Facts pour la gestion multi-os
* `ansible_pkg_mgr` : Le gestionnaire de paquets
* `ansible_os_family` : La famille d'OS
* `ansible_distribution` : Information détaillées sur la distribution
### Gestionnaire de paquets
<!-- .slide: data-state="medium-code" -->
```none
$ ansible my-host -i ./hosts -m setup | grep ansible_pkg_mgr
"ansible_pkg_mgr": "yum",
```
### Famille d'OS
<!-- .slide: data-state="medium-code" -->
```none
$ ansible my-host -i ./hosts -m setup | grep ansible_family
"ansible_os_family": "RedHat",
```
### Distribution
<!-- .slide: data-state="medium-code" -->
```none
$ ansible my-host -i ./hosts -m setup | grep ansible_distribution
"ansible_distribution": "CentOS",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "7",
"ansible_distribution_release": "Core",
"ansible_distribution_version": "7.5.1804",
```
### Exemple d'aiguillage multi-OS
<!-- .slide: data-state="small-code" -->
Arborescence du rôle
```none
my-role
├── README.md
├── tasks
   ├── CentOS.yaml -> RedHat.yaml
   ├── Debian.yaml
   ├── main.yaml
   ├── RedHat.yaml
   └── Ubuntu.yaml -> Debian.yaml
└── vars
   ├── CentOS-6.yaml
   ├── CentOS-7.yaml
   ├── Debian-8.yaml
   ├── Debian-9.yaml
   ├── RedHat-6.yaml
   ├── RedHat-7.yaml
   └── Ubuntu-16.yaml
```
<!-- .slide: data-state="medium-code" -->
`my-role/tasks/main.yaml`
```yaml
- name: Add the OS specific variables
include_vars: '{{ ansible_distribution }}-{{ ansible_distribution_major_version }}.yaml'
- include_tasks: '{{ansible_distribution}}.yaml'
```
## Utilisation des _conditionals_
* Action déclenchée de manière conditionnelle
(en fonction du résultat d’une variable).
* Utilisation de _when_.
<small>https://docs.ansible.com/ansible/playbooks_conditionals.html</small>
### Exemple
<!-- .slide: data-state="small-code" -->
```yaml
- hosts: web
tasks:
- name: Install Apache for CentOS system
yum:
name: httpd
state: present
update_cache: yes
when:
- ansible_os_family == "RedHat" # sera joué sur RedHat et Centos
- name: Install Apache for Ubuntu system
apt:
name: apache2
state: present
update_cache: yes
when:
- ansible_os_family == "Debian" # sera joué sur Debian et Ubuntu
```
Chaque tâche cible une famille
de système d'exploitation précise.
<!-- .slide: data-state="small-code" -->
```none
$ ansible-playbook playbook.yaml -i ./hosts
PLAY [web] *******************************************************************
TASK [setup] *****************************************************************
ok: [centos-vm]
ok: [ubuntu-vm]
TASK [Install Apache for CentOS system] **************************************
ok: [centos-vm]
skipping: [ubuntu-vm]
TASK [Install Apache for Ubuntu system] **************************************
skipping: [centos-vm]
ok: [ubuntu-vm]
PLAY RECAP *******************************************************************
centos-vm : ok=2 changed=0 unreachable=0 failed=0
ubuntu-vm : ok=2 changed=0 unreachable=0 failed=0
```
Les tâches sont exécutées ou non en fonction
de la famille du système d'exploitation.
## Utilisation des _loops_
* Boucles pour la réalisation d'actions répétitives.
* Permet de faire plusieurs actions dans une seule tâche.
* Création d'utilisateurs, installation de paquets, ...
* Utilisation de ~~with-x~~ _loop_
<small>https://docs.ansible.com/ansible/playbooks_loops.html</small>
### with-x
<!-- .slide: data-state="small-table" -->
Paramètre | Type | Example d'utilisation
- | - | -
`with_items` | Array | To create a group of users, directories, or to install a list of packages
`with_nested` | Nested loops | To create a list of MySQL users and grant them access to a group of databases
`with_dict` | Hashes | To parse a dictionary of key-value pairs and create virtual hosts
`with_fileglobs` |Files with pattern match | To parse a path and copy only those files that match a certain pattern
`with_together` | S ets | To join two arrays as a set and to loop over it
`with_subelements` | Hash sub element | To walk over the list of SSH keys and distribute them to a user
`with_sequence` | Integer sequence | To loop a sequence of numbers
`with_random_choice` | Random choice | To pick up items from the array in a random order
`with_indexed_items` | Array with index | Array with an index and is useful when an index for items is required
### Exemple avec with_items
```yaml
- hosts: my-host
tasks:
- name: Add some users
user:
name: "{{ item }}"
state: present
with_items:
- bob
- alice
- joe
```
Attention ! à partir d'Ansible 2.5 _with-x_ n'est plus la méthode recommandé pour effectué des boucles.
<!-- .slide: data-state="small-code" -->
```none
$ ansible-playbook playbook.yaml -i ./hosts
PLAY [my-host] ***************************************************************
TASK [setup] *****************************************************************
ok: [my-host]
TASK [Add some users] ********************************************************
changed: [my-host] => (item=bob)
changed: [my-host] => (item=alice)
changed: [my-host] => (item=joe)
PLAY RECAP *******************************************************************
my-host : ok=2 changed=1 unreachable=0 failed=0
```
La boucle a bien itéré sur les 3 utilisateurs.
### Migration vers loop
* A partir d'Ansible 2.5 _with-x_ n'est plus la méthode recommandée pour effectuer des boucles.
* La documentation sur les boucles propose une section pour aider à la migration de _with-x_ vers _loop_.
<small>https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html</small>
### Exemple avec loop
```yaml
- hosts: my-host
tasks:
- name: Add some users
user:
name: "{{ item }}"
state: present
loop:
- bob
- alice
- joe
```
On remplace simplement `with_items` par `loop`.
<!-- .slide: data-state="small-code" -->
```none
$ ansible-playbook -i inventories/formation/hosts playbook.yaml
PLAY [my-host] ***************************************************************
TASK [Gathering Facts] *******************************************************
ok: [my-host]
TASK [Add some users] ********************************************************
changed: [my-host] => (item=bob)
changed: [my-host] => (item=alice)
changed: [my-host] => (item=joe)
PLAY RECAP *******************************************************************
my-host : ok=2 changed=1 unreachable=0 failed=0
```
Le résultat final est strictement identique.
```yaml
- hosts: my-host
tasks:
- name: Add some users
user:
name: "{{ item.name }}"
state: present
groups: "{{ item.groups }}"
loop:
- { name: 'bob', groups: 'wheel' }
- { name: 'alice', groups: 'root' }
- { name: 'joe', groups: 'root' }
```
En plus des _strings_ , il est possible d'utiliser des _hashes_.
### Itérer sur l'inventaire
<!-- .slide: data-state="small-code" -->
```yaml
- hosts: centos7
tasks:
- name: Iterate on hosts in the group all in the inventory
debug:
msg: "{{ item }}"
loop: "{{ groups['all'] }}" # on itère sur les machines du groupe all
```
```none
$ ansible-playbook -i ./hosts playbook.yaml
PLAY [centos7] *****************************************************************
TASK [Iterate on hosts in the group all in the inventory] **********************
ok: [ansible-1] => (item=ansible-3) => {
"msg": "ansible-3"
}
ok: [ansible-1] => (item=ansible-1) => {
"msg": "ansible-1"
}
ok: [ansible-1] => (item=ansible-2) => {
"msg": "ansible-2"
}
ok: [ansible-2] => (item=ansible-3) => {
"msg": "ansible-3"
}
ok: [ansible-2] => (item=ansible-1) => {
"msg": "ansible-1"
}
ok: [ansible-2] => (item=ansible-2) => {
"msg": "ansible-2"
}
```
Chaque machine du Play (_centos7_) itère sur le groupe _all_.
### Itérer sur le Play
<!-- .slide: data-state="small-code" -->
```yaml
- hosts: centos7
tasks:
- name: Iterate on all the hosts in the current play
debug:
msg: "{{ item }}"
loop: "{{ ansible_play_batch }}" # variable qui contient les machines du Play
```
```none
$ ansible-playbook -i inventories/formation/hosts playbook.yaml
PLAY [centos7] *****************************************************************
TASK [Iterate on all the hosts in the current play] ****************************
ok: [ansible-1] => (item=ansible-1) => {
"msg": "ansible-1"
}
ok: [ansible-1] => (item=ansible-2) => {
"msg": "ansible-2"
}
ok: [ansible-2] => (item=ansible-1) => {
"msg": "ansible-1"
}
ok: [ansible-2] => (item=ansible-2) => {
"msg": "ansible-2"
}
```
Chaque machine du Play (_centos7_) itère
sur les machines du Play (_centos7_).
## Travaux pratiques
<!-- .slide: data-state="nologo-slide" style="text-align: center" -->
![Travaux pratiques](images/tp.gif)
<small>[TP Ansible : structures de contrôle](travaux-pratiques/tp-ansible-structures-de-controle.html)</small>