Exécution conditionnelle basée sur la sortie shell
L'une des capacités les plus puissantes d'Ansible est la possibilité de prendre des décisions basées sur la sortie des commandes shell. Dans cette étape, nous allons apprendre à utiliser des conditions et des filtres pour traiter la sortie des commandes shell et rendre les playbooks plus dynamiques.
Utilisation des conditions avec la sortie shell
Créons un playbook qui prend des décisions basées sur la sortie des commandes shell :
- Créez un nouveau fichier appelé
conditional_playbook.yml dans le répertoire /home/labex/project.
- Ajoutez le contenu suivant :
---
- name: Conditional Tasks Based on Command Output
hosts: local
gather_facts: no
tasks:
- name: Check disk space
shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
register: disk_usage
- name: Display disk usage
debug:
msg: "Current disk usage: {{ disk_usage.stdout }}%"
- name: Disk usage warning
debug:
msg: "WARNING: Disk usage is high"
when: disk_usage.stdout|int > 50
- name: Disk usage normal
debug:
msg: "Disk usage is normal"
when: disk_usage.stdout|int <= 50
Ce playbook :
- Exécute une commande shell pour vérifier le pourcentage d'utilisation du disque sur le système de fichiers racine
- Utilise la condition
when basée sur la sortie de la commande
- Utilise le filtre
int pour convertir la sortie de la chaîne en un entier pour la comparaison
Exécutez le playbook :
ansible-playbook -i inventory.ini conditional_playbook.yml
La sortie variera en fonction de votre utilisation réelle du disque, mais ressemblera à ceci :
PLAY [Conditional Tasks Based on Command Output] ******************************
TASK [Check disk space] *******************************************************
changed: [localhost]
TASK [Display disk usage] *****************************************************
ok: [localhost] => {
"msg": "Current disk usage: 38%"
}
TASK [Disk usage warning] *****************************************************
skipped: [localhost]
TASK [Disk usage normal] ******************************************************
ok: [localhost] => {
"msg": "Disk usage is normal"
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Remarquez comment Ansible a exécuté une seule des tâches conditionnelles en fonction de la valeur réelle de l'utilisation du disque.
Gestion de la sortie JSON des commandes
De nombreux outils CLI modernes renvoient des données au format JSON. Ansible possède des capacités intégrées pour gérer la sortie JSON :
- Créez un nouveau fichier appelé
json_output.yml dans le répertoire /home/labex/project.
- Ajoutez le contenu suivant :
---
- name: Handling JSON Output
hosts: local
gather_facts: no
tasks:
- name: Create a JSON file for testing
copy:
dest: /tmp/services.json
content: |
{
"services": [
{
"name": "web",
"status": "running",
"port": 80
},
{
"name": "database",
"status": "stopped",
"port": 5432
},
{
"name": "cache",
"status": "running",
"port": 6379
}
]
}
- name: Read JSON file with shell
shell: cat /tmp/services.json
register: json_output
- name: Parse and display JSON content
debug:
msg: "{{ json_output.stdout | from_json }}"
- name: Extract and display service information
debug:
msg: "Service: {{ item.name }}, Status: {{ item.status }}, Port: {{ item.port }}"
loop: "{{ (json_output.stdout | from_json).services }}"
- name: Show only running services
debug:
msg: "Running service: {{ item.name }} on port {{ item.port }}"
loop: "{{ (json_output.stdout | from_json).services }}"
when: item.status == "running"
Ce playbook :
- Crée un exemple de fichier JSON pour la démonstration
- Lit le fichier JSON avec une commande shell
- Utilise le filtre
from_json pour analyser la chaîne JSON en une structure de données
- Parcourt la structure de données pour afficher les informations
- Utilise une logique conditionnelle pour filtrer uniquement les services en cours d'exécution
Exécutez le playbook :
ansible-playbook -i inventory.ini json_output.yml
Vous devriez voir une sortie similaire à ceci :
PLAY [Handling JSON Output] ***************************************************
TASK [Create a JSON file for testing] *****************************************
changed: [localhost]
TASK [Read JSON file with shell] **********************************************
changed: [localhost]
TASK [Parse and display JSON content] *****************************************
ok: [localhost] => {
"msg": {
"services": [
{
"name": "web",
"port": 80,
"status": "running"
},
{
"name": "database",
"port": 5432,
"status": "stopped"
},
{
"name": "cache",
"port": 6379,
"status": "running"
}
]
}
}
TASK [Extract and display service information] ********************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
"msg": "Service: web, Status: running, Port: 80"
}
ok: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432}) => {
"msg": "Service: database, Status: stopped, Port: 5432"
}
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
"msg": "Service: cache, Status: running, Port: 6379"
}
TASK [Show only running services] *********************************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
"msg": "Running service: web on port 80"
}
skipped: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432})
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
"msg": "Running service: cache on port 6379"
}
PLAY RECAP ********************************************************************
localhost : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Remarquez comment le playbook analyse le JSON, extrait des informations spécifiques et filtre les données en fonction des conditions.
Gestion des erreurs avec les commandes shell
Lors de l'exécution de commandes shell, il est important de gérer les erreurs potentielles avec élégance :
- Créez un nouveau fichier appelé
error_handling.yml dans le répertoire /home/labex/project.
- Ajoutez le contenu suivant :
---
- name: Error Handling with Shell Commands
hosts: local
gather_facts: no
tasks:
- name: Run a potentially failing command
shell: grep "nonexistent_pattern" /etc/passwd
register: command_result
ignore_errors: yes
- name: Display success or failure
debug:
msg: "Command {{ 'succeeded' if command_result.rc == 0 else 'failed with return code ' + command_result.rc|string }}"
- name: Run a custom failing command
shell: exit 3
register: exit_command
ignore_errors: yes
- name: Display detailed error information
debug:
msg: |
Return code: {{ exit_command.rc }}
Error message: {{ exit_command.stderr if exit_command.stderr else 'No error message' }}
Ce playbook :
- Exécute des commandes qui sont censées échouer
- Utilise
ignore_errors: yes pour continuer l'exécution du playbook même lorsque les commandes échouent
- Montre différentes méthodes pour gérer et afficher les informations d'erreur
Exécutez le playbook :
ansible-playbook -i inventory.ini error_handling.yml
Vous devriez voir une sortie similaire à ceci :
PLAY [Error Handling with Shell Commands] *************************************
TASK [Run a potentially failing command] **************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "grep \"nonexistent_pattern\" /etc/passwd", "delta": "0:00:00.002916", "end": "2023-07-14 16:10:23.671519", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 16:10:23.668603", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Display success or failure] *********************************************
ok: [localhost] => {
"msg": "Command failed with return code 1"
}
TASK [Run a custom failing command] *******************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "exit 3", "delta": "0:00:00.002447", "end": "2023-07-14 16:10:23.906121", "msg": "non-zero return code", "rc": 3, "start": "2023-07-14 16:10:23.903674", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Display detailed error information] *************************************
ok: [localhost] => {
"msg": "Return code: 3\nError message: No error message\n"
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=2
Cela démontre comment capturer et répondre à différentes conditions d'erreur lors de l'exécution de commandes shell.