Manipulation de fichiers sur les hôtes
Introduction
Outre la possibilité de développer votre propre module, Ansible est livré avec une bibliothèque de modules, lesquels sont développés au sein du projet communautaire Ansible. La liste des modules se situe à l’adresse : https://docs.ansible.com/ansible/latest/modules/list_of_all_modules.html
Ces modules peuvent être exécutés directement sur des hôtes distants ou par l’intermédiaire de playbooks. Ils servent à contrôler les ressources du système telles que les services, les paquets, les fichiers ou bien encore gérer l’exécution de commandes...
Ce chapitre va présenter les principaux modules de la bibliothèque Files.
Présentation des modules de fichiers
La bibliothèque de modules Files permet d’accomplir les tâches relatives à la gestion de fichiers. Le tableau ci-dessous fournit une liste de modules de gestion de fichiers fréquemment utilisés.
Nom du module |
Description |
acl |
Appliquer les ACL des fichiers. |
file |
Manipuler des fichiers et des attributs de fichiers. |
copy |
Copier un fichier depuis la machine locale vers une machine distante. Définir les attributs de fichiers. |
fetch |
Copier un fichier depuis une machine distante vers la machine locale. |
find |
Rechercher un fichier. |
stat |
Obtenir l’état d’un fichier. |
archiveunarchive |
Manipuler des archives de fichiers compressés. |
blockinfile |
Insérer, mettre à jour ou supprimer un bloc de texte multiligne. |
lineinfile |
Rechercher et/ou remplacer une ligne dans un fichier. |
replace |
Remplacer toutes les instances d’une chaîne particulière dans un fichier en utilisant une expression régulière. |
template |
Créer, à l’aide d’un fichier modèle Jinja2, un fichier sur un hôte distant. |
Ces modules et leurs paramètres sont étudiés ci-après.
Appliquer les ACL de fichiers
Le module ACL permet de définir ou de récupérer les informations ACL (Access Control List ou en français Liste de Contrôle d’Accès) d’un fichier.
Le paramètre state a trois valeurs possibles :
Valeur du paramètre |
Description |
absent |
L’ACL doit être supprimée. |
present |
L’ACL doit être définie. |
query |
Permet d’obtenir l’ACL courante sans la modifier afin de l’utiliser dans les opérations de registre. |
Exemple
Sur l’hôte server2 deux fichiers data.txt et info.txt sont présents dans le répertoire de base (/home/fred) du compte utilisateur fred.
L’objectif est de :
-
définir les permissions RW sur le fichier data.txt pour le compte fred ;
-
supprimer toutes les permissions sur le fichier info.txt pour le compte fred.
---
- name: Module FILES - ACL
hosts: server2
tasks:
- name: Définir les permissions RW pour fred
acl:
path: /home/fred/data.txt
entity: fred
etype: user
permissions: rw
state: present
- name: Supprimer les ACL pour fred
acl:
path: /home/fred/info.txt
entity:...
Modifier l’horodatage des fichiers
Manuellement, c’est la commande touch qui est utilisée pour modifier l’horodatage (timestamp) de dernier accès et de dernière modification d’un fichier. Cette commande permet également de créer un fichier vide.
Ansible, quant à lui, s’assure que l’utilisateur propriétaire, le groupe et les autorisations du fichier sont définis.
Exemple
Créez un fichier readme.txt dans le dossier /root sur les machines appartenant au groupe servers. L’utilisateur propriétaire sera john et le groupe propriétaire sera users. Les permissions de ce fichiers seront définies à 0640 :
---
- name: Module FILES - touch
hosts: servers
tasks:
- name: Touch a file and set permissions
file:
path: /root/readme.txt
owner: john
group: users
mode: 0640
state: touch
Dans un terminal, constatez le résultat :
[root@server2 ~]# ll /root/readme.txt
-rw-r-----. 1 john users 0 14 janv. 16:39 /root/readme.txt
[root@server2 ~]#
La gestion des attributs de fichier peut s’effectuer grâce à plusieurs modules. Il est utile parfois de se documenter avec la commande...
Copie de fichiers
1. Module copy
Le module copy est utilisé pour copier un fichier situé dans un dossier sur le nœud de contrôle vers les hôtes gérés.
Exemple
Copier depuis le nœud de contrôle le fichier ~/workspace/prog.conf vers l’hôte /opt/app/prog.conf. L’utilisateur et le groupe propriétaires sont root. Les permissions sont définies ainsi : u=rw,g=r,o=r.
---
- name: Module FILES - copy
hosts: server2
tasks:
- name: Copie du fichier prog.conf
copy:
src: ~/workspace/prog.conf
dest: /opt/app/prog.conf
owner: root
group: root
mode: u=rw,g=r,o=r
Le paramètre mode accepte également l’écriture des permissions en nombre octal. Vous disposez de deux syntaxes pour cela.
La première consiste à ajouter un zéro devant la valeur (par exemple 0644) pour que l’analyseur YAML de Ansible sache que c’est bel et bien un nombre octal.
La seconde consiste à encadrer la valeur avec de simples quotes (par exemple ‘644’) pour que Ansible reçoive une chaîne de caractères et puisse la convertir en nombre.
Si vous ne respectez pas l’une de ces deux règles, alors la valeur octale se traduira par un nombre décimal. Ce qui peut provoquer des résultats inattendus.
Par défaut, le module copy a le paramètre force à yes. Il écrase donc le fichier distant. Si vous ne voulez pas de ce comportement, mettez force à no :
tasks:
- name: Copie du fichier prog.conf
copy:
src: ~/workspace/prog.conf
dest: /opt/app/prog.conf
owner: root
group: root
mode: 0644
force : no
La commande ansible-doc peut fournir les informations sur le module copy :
[root@server1 ~]# ansible-doc copy
**** sortie tronquée ****
= dest
...
Suppression de fichiers
Supprimer un fichier sur des hôtes gérés consiste à utiliser le module file avec le paramètre state: absent.
Exemple
Pour supprimer le fichier /home/fred/info.txt :
---
- name: Module file - Supprimer un fichier
hosts: server2
vars:
fic: /home/fred/info.txt
tasks:
- name: Supprimer le fichier
file:
state: absent
path: "{{ fic }}"
Déplacement et renommage des fichiers
Vous avez sans doute constaté dans le tableau au début de ce chapitre que la bibliothèque de modules files ne fournit pas de modules qui permettraient de déplacer ou de renommer des fichiers.
Cette section présente deux possibilités.
Première possibilité
En utilisant le module command et la commande mv du système d’exploitation Linux.
Exemple
Nous voulons déplacer le fichier /home/fred/data.txt dans le dossier /home/fred/old/ si le fichier est existant.
---
- name: Module command - déplacer/renommer un fichier
hosts: server2
vars:
fic_src: /home/fred/data.txt
fic_dest: /home/fred/old/
tasks:
- name: Fichier existe ou pas
stat:
path: "{{ fic_src }}"
register: resultat
- name: deplacer fichier si existe
command: mv "{{ fic_src }}" "{{ fic_dest }}"
when: resultat.stat.exists == True
Seconde possibilité
En utilisant le module copy pour copier le fichier vers une destination souhaitée. Puis, en utilisant le module file pour supprimer la source de la copie.
Exemple
En reprenant l’objectif de l’exemple précédent :...
Recherche de fichiers
Le module find permet de rechercher un ou plusieurs fichiers sur les hôtes gérés.
Dans le tableau suivant, vous trouverez les paramètres les plus courants de ce module. D’ailleurs, vous trouverez des similitudes avec la commande find du shell Linux.
Paramètre |
Description |
paths |
Lister des chemins d’accès parmi lesquels il faut rechercher. Tous les chemins doivent être pleinement qualifiés. |
age |
Trouver les fichiers dont l’âge est égal ou supérieur à la durée spécifiée. Utiliser un âge négatif pour trouver les fichiers dont l’âge est égal ou inférieur à la durée spécifiée. Il est possible de spécifier la première lettre de la durée :
Exemple : Pour une semaine, spécifier 1w. |
age_stamp |
Choisir la propriété du fichier par rapport à laquelle l’âge est comparé :
|
recurse |
Si recurse=yes et que la cible est un dossier, ce dernier sera parcouru récursivement à la recherche de fichiers. La valeur par défaut... |
Informations sur l’état d’un fichier
Le module stat est similaire à la commande qui porte le même nom.
Exemple
Vérifier que le dossier /root/database sur l’hôte server2 existe.
D’abord, le module stat va récupérer les faits de ce dossier. La variable ret va capturer le résultat.
Le module debug affiche le message "Chemin inexistant" si la condition définie avec la clause when « ret.stat.isdir is not defined » est vraie.
Nous utilisons une seconde fois ce module pour afficher le message "Chemin existant" si la condition définie avec la clause when « ret.stat.isdir is defined » est vraie.
Consultez ansible-doc stat pour connaître les paramètres et la valeur de retour.
---
- name: Module FILES - stat
hosts: server2
tasks:
- name: Tester si le dossier existe
stat:
path: /root/database
register: ret
- debug:
msg: "Chemin inexistant"
when: ret.stat.isdir is not defined
- debug:
msg: "Chemin existant"
...
Manipulation d’archives
Cette section va démontrer comment créer et extraire des fichiers d’une archive comme vous le feriez manuellement avec la commande tar.
1. Création d’une archive
Le module archive permet de concevoir une archive compressée. Le tableau ci-dessous décrit les principaux paramètres nécessaires :
Paramètre |
Description |
path |
Spécifie le(s) chemin(s) pour le(s) fichier(s) à archiver. |
exclude_path |
Spécifie le(s) chemin(s) à exclure de l’archive. |
dest |
Définit le nom de fichier de l’archive de destination. |
format |
Définit le format de l’archive qui peut être bz2, gz (valeur par défaut), tar, xz et zip. |
Exemple
Créer une archive, au format bzip2, qui contient les fichiers du répertoire /opt/app. Il faut exclure le sous-répertoire /opt/app/images :
---
- name: Module archive
hosts: server2
# Creation archive bz2 des fichiers /opt/app/*
# en excluant le dossier /opt/app/images
tasks:
- name: Creation archive
archive:
path: /opt/app/*
dest: /root/app.tar.bz2
exclude_path: /opt/app/images
format: bz2
2. Extraction d’une archive
Le module unarchive permet d’extraire des fichiers d’une...
Modification de fichiers
Pour modifier le contenu d’un fichier, ces trois modules sont disponibles :
-
lineinfile qui est utile lorsqu’une seule ligne est à modifier dans un fichier ;
-
blockinfile permet d’insérer, de mettre à jour ou de supprimer un bloc de lignes dans un fichier ;
-
replace permet de remplacer toutes les instances d’une chaîne particulière dans un fichier.
1. Module lineinfile
Le module lineinfile permet de s’assurer de la présence d’une ligne particulière dans un fichier ou de remplacer une ligne existante en utilisant une expression régulière.
Le tableau ci-dessous décrit les principaux paramètres qui sont essentiels :
Paramètre |
Description |
path |
Définit le chemin d’accès et le nom du fichier à traiter. |
regexp |
Spécifie le motif de recherche. |
line |
Spécifie la ligne à insérer ou à remplacer au sein du fichier. |
Exemple
Pour s’assurer que SELinux est en mode enforcing : remplacer dans le fichier /etc/selinux/config la ligne qui commence par SELINUX par la nouvelle valeur SELINUX=enforcing :
---
- name: Module FILES - lineinfile
hosts: servers
tasks:
- name: Verifier que SELinux est en mode enforcing
lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: SELINUX=enforcing
2. Module blockinfile
Lorsque vous souhaitez ajouter un bloc de texte à un fichier existant, il faut utiliser le module blockinfile.
Le tableau ci-dessous décrit les principaux paramètres qui sont essentiels :
Paramètre |
Description |
path |
Définit le chemin d’accès et le nom du fichier à... |
Modifications de contexte de fichier SELinux
Le module file se comporte comme la commande chcon lors de la définition des contextes de fichier. Par conséquent, les modifications apportées avec ce module pourraient être annulées de manière inattendue en exécutant la commande restorecon.
Après avoir défini le contexte avec le module file, vous pouvez utiliser le module sefcontext de la bibliothèque de modules system afin de mettre à jour la politique SELinux. Ces manipulations sont similaires à l’utilisation de la commande semanage fcontext.
Les paquets suivants sont nécessaires pour l’hôte qui exécute ce module :
-
libselinux-python ;
-
policycoreutils-python.
Exemple
Créer un dossier /common sur l’hôte server2 pour une utilisation future de SAMBA. SELinux est, sur cette machine cible, en mode enforcing.
Faisons manuellement la manipulation avant de concevoir le playbook. Il est nécessaire, tout d’abord, de définir quatre valeurs booléennes SELinux. Par exemple :
[root@server2 /]# setsebool -P samba_enable_home_dirs on
[root@server2 /]# setsebool -P use_samba_home_dirs on
[root@server2 /]# setsebool -P samba_export_all_ro on
[root@server2 /]# setsebool -P samba_export_all_rw on
Pour vérifier, utilisez la commande getsebool :
[root@server2 /]# getsebool -a | grep...
Synchronisation de fichiers
Le module synchronize est un « wrapper » qui fonctionne autour de la commande rsync qui doit être installé sur le nœud de contrôle et sur l’hôte géré.
Ce module ne fournit pas toute la puissance de la commande rsync. Il facilite, cependant, la mise en œuvre des fonctionnalités les plus courantes. Vous pouvez, néanmoins, avoir besoin d’appeler parfois la commande rsync via les modules command ou shell selon votre cas d’utilisation.
Exemple
Le dossier /root/files du nœud de contrôle (server1) doit être synchronisé avec le dossier /common/files situé sur l’hôte géré (server2) :
---
- name: Module FILES - synchronize
hosts: server2
tasks:
- name: Synchronisation depuis server1 vers l'hôte server2
synchronize:
src: /root/files
dest: /common/files
Utilisez la commande ansible-doc synchronize pour plus d’informations sur les paramètres et les exemples de playbook fournis.
Modèles JINJA2
1. Présentation de Jinja2
Jinja2 est un moteur de modèles (templates) pour le langage Python qui est basé sur celui du framework Django. Initialement, il était utilisé pour créer des pages HTML à partir d’un modèle préformaté dans lequel sont injectées des données sous forme de variables, mais aussi, permettant d’utiliser des conditions et des boucles. Vous disposez d’une documentation sur le site : https://jinja.palletsprojects.com/en/2.10.x/templates/
Un modèle Jinja2 est tout simplement un fichier texte avec une extension .j2.
Ansible Engine utilise la syntaxe Jinja2 pour référencer les variables dans les playbooks.
La syntaxe pour définir des commentaires est :
{# mon commentaire #}
Les expressions, les boucles et les conditions sont exprimées dans cette balise :
{% expression %}
La balise suivante est utilisée pour générer le résultat d’une expression ou d’une variable :
{{ adresse_IP }}
Dans les modèles, vous pouvez utiliser des boucles et des conditions Jinja2. Ce qui n’est pas le cas dans les playbooks.
2. Conception et application d’un modèle
Comme vu précédemment, des données, des variables et des expressions composent un modèle Jinja2. Les variables qui sont utilisées peuvent être définies dans la section vars du playbook. Elles sont remplacées par leurs valeurs lorsqu’un modèle est « rendu ». C’est aussi le cas pour les expressions. Vous pouvez utiliser les faits (facts) des hôtes gérés, que nous avons vus dans le chapitre Gestion des faits, comme variables sur un modèle.
Dans le playbook suivant, le module template est utilisé :
tasks:
- name: template render
template:
src: fichier_modele.j2
dest: /home/bob/data/fichier_rendu.txt
Il nécessite plusieurs paramètres :
Paramètre |
Description |
src |
Spécifie le chemin et le nom du fichier modèle (template) au format Jinja2. Il est situé sur le nœud de contrôle. Le répertoire par défaut est ./templates. |
dest |
Définit... |