Aller au contenu principal

Les modules Ansible pour gérer les fichiers

· 18 minutes de lecture
Stéphane ROBERT
Consultant DevOps

Je vous propose dans ce billet tous les modules permettant de récupérer et de gérer des fichiers avec Ansible.

Au menu :

  • Création et destruction de fichiers, répertoires et liens.
  • Récupération des informations sur les fichiers distants.
  • Changement des droits, des propriétaires et attributs.
  • Récupération du contenu des fichiers distant.
  • Création et extractions d'archives.
  • Téléchargement de fichiers et de projets sur internet.

Vous pouvez compléter cette liste en consultant ces deux billets :

Dans le descriptif des paramètres vous trouverez des valeurs entre parenthèse. Il s'agit des valeurs par défaut.

Recommendations

Avant de commencer je vous rappelle deux règles importantes :

Ansible-lint préconise de définir dans chaque utilisation des modules file, copy, les droits avec le paramètre mode.

De même dans les documentations Ansible vous trouverez pour les booléens des valeurs yes et no. Ansible-Lint préconise plutôt l'emploi des valeurs true et false.

Les modules inclues dans Ansible Core

file

Ce premier module est le plus utilisé, mais on oublie parfois qu'il permet de gérer les attributs et les paramètres selinux :

Les principaux arguments :

  • path : Chemin du fichier sur la cible.
  • owner : Définit le propriétaire du fichier.
  • group : Définit le groupe du fichier.
  • mode : Définit les droits d'accès aux fichiers. Par défaut 0644
  • state : state prend avec des valeurs différentes des habituelles present/absent.
    • file : Le fichier ne sera pas créé s'il n'existe pas. Si vous voulez en créer un vide alors utilisé le state touch, avec du contenu alors tournez-vous vers les modules copy ou template.
    • touch : Comme dis haut-dessus, création d'un fichier vide.
    • link : Création d'un lien symbolique, donc s'utilise conjointement avec le paramètre src.
    • directory : Création si besoin de tous les répertoires du chemin indiqué.
    • hard : Création d'un lien physique, donc s'utilise conjointement avec le paramètre src.
    • absent :
  • src : chemin du fichier source pour la création de lien avec link et hard.

Quelques exemples :

- name: Création d'un simple fichier
  ansible.builtin.file:
    path: /tmp/foo.txt
    owner: foo
    group: foo
    mode: 0644
- name: Création d'un lien symbolique
  ansible.builtin.file:
    src: "/opt/rundeck-{{ rundeck_version }}"
    dest: /opt/rundeck
    owner: foo
    group: foo
    state: link
- name: Création des répertoires d'un path
  ansible.builtin.file:
    path: /tmp/test/de/creation/de/repertoires
    state: directory
    mode: 0755

La suite des arguments :

  • attributes : Définit les attributs du fichier. [aAcCdDeFijPsStTu].([])
  • access_time : Permet de modifier la date de dernier accès d'un fichier.
  • access_time_format : Par défaut "%Y%m%d%H%M.%S"
  • follow : Utilisé avec les liens symboliques. Si le lien existe, il est mis à jour.
  • force : Idem Force la création des liens même si la source n'existe pas.
  • modification_time : Comme pour access_time
  • modification_time_format : Par défaut "%Y%m%d%H%M.%S"
  • recurse : A utiliser avec le state directory pour que les attributs, droits et propriétaire soit propagé.
  • unsafe_writes : A utiliser avec précaution, en l'activant vous pouvez obtenir des corruptions sur les fichiers.

Pour la modification des droits SeLinux avec selevel, serole, setype, seuser

copy

Le module ansible copy permet de copier un fichier entre une source et une cible. La source est contrôlée par le paramètre remote_src.

Les principaux arguments :

  • src : Chemin relatif ou absolu de la source, un / à la fin du nom indique qu'il s'agit d'un répertoire.
  • content : A la place d'un fichier on utilise un contenu pour créer la cible
  • dest : Chemin sur la cible.
  • owner : Définit le propriétaire.
  • group : Définit le groupe.
  • mode : Définit les droits d'accès. Par défaut (0644)
  • remote_src : Indique si la source est sur la machine locale ou est sur la machine cible. (false)
  • backup : Fait un backup avant d'opérer (false). Création d'un fichier avec un horodatage ex : file.1239239.2022-03-28@09:07:33
  • directory_mode : Pour une copie récursive définit le mode des répertoires créés. Si les répertoires existent, ils ne seront pas modifiés. Pour les modifier, il faudra utiliser file.
  • validate : Souvent oublié. Permet de lancer une commande pour contrôler le contenu du fichier créé sur la cible. Si vous devez indiquer le nom du fichier dans la ligne de commande, il faut remplacer ce nom par %s.

Des exemples :

- name: Copie un fichier de la machine locale vers les machines cibles
  ansible.builtin.copy:
    src: /srv/myfiles/foo.conf
    dest: /etc/foo.conf
    owner: foo
    group: foo
    mode: '0644'

- name: Copie d'une configuration ngxinx avec validation
    src: rundeck.conf
    dest: /etc/nginx/conf.d/rundeck
    validate : "/usr/sbin/nginx -c /etc/nginx/nginx.conf -t"

La suite des arguments :

  • attributes : Définit les attributs du fichier. [aAcCdDeFijPsStTu].([])
  • follow : Utilisé avec les liens symboliques. Si le lien existe, il est mis à jour. (false)
  • force : Idem Force la création des liens même si la source n'existe pas. (false)
  • unsafe_writes : A utiliser avec précaution, en l'activant vous pouvez obtenir des corruptions sur les fichiers. (false)
  • decrypt : Si les fichiers sources sont dans un vault doivent-ils être décrypté. (true).

Pour la modification des droits SeLinux avec selevel, serole, setype, seuser

stat

Le module stat permet de remonter sous la forme de facts le retour de la commande Linux stat, mais pas que. Ensuite on peut utiliser le résultat pour réaliser ou pas des taches en utilisant des conditions (voir exemple).

stat /etc/passwd
  File: /etc/passwd
  Size: 2391            Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 69715970    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:passwd_file_t:s0
Access: 2022-03-27 14:02:14.195003241 +0000
Modify: 2022-03-03 09:47:13.451935905 +0000
Change: 2022-03-03 09:47:13.455935898 +0000
 Birth: 2022-03-03 09:47:13.451935905 +0000

Les principaux arguments :

  • path : Chemin du fichier à analyser.
  • follow : Si c'est un lien faut-il analyser la cible du lien ? Par défaut non.
  • get_attributes : Remonte aussi le retour de la commande lsattr. (false)
  • get_checksum : Faut-il remonter un checksum. (false)
  • checksum_algorithm : Algorithm du checksum : md5, (sha1), sha224, sha256, sha384, sha512
  • get_mime : Faut-il remonter le type mime ? (false)

Un exemple, ou je récupère la version en cours de rundeck via les informations récupérées sur le lien. Si le lien existe, j'extrais la version avec une expression régulière.

    - name: "Check rundeck-latest link stat in {{ rundeck_installation_dir }}"
      ansible.builtin.stat:
        path: "{{ rundeck_installation_dir }}/rundeck"
      register: running_version
      tags: version
    - name: Register current running version if any
      ansible.builtin.set_fact:
        rundeck_version_running: >-
          {{
            running_version.stat.lnk_target
            | regex_replace('^.*rundeck-(\d*\.\d*\.\d*-\d*)', '\1')
          }}
      when:
        - running_version.stat.exists | default(false)
        - running_version.stat.islnk | default(false)

find

Ce module est comparable à ce que fait la commande Linux find. On va en retrouver les principaux paramètres :

  • paths : Chemin absolu où lancer la recherche. Un ou plusieurs.
  • patterns : Liste de patterns à utiliser.
  • file_type : Type de fichier à rechercher : any, directory, (file) ou link
  • follow : Faut-il suivre le lien ? (false)
  • exclude : Liste de patterns à exclure.
  • use_regex : Les patterns sont ils de type regex ? (false)
  • age : Faut-il filtrer les fichiers par age ? en secondes (s), minutes(m), heures(h), jours(d) ou semaines(w). Une valeur négative retourne les plus récents.
  • age_stamp : Permet de changer la date d'information à utiliser : atime, ctime ou (mtime)
  • size : Filtrer par taille en b, k, m, f et t en ne gardant que ceux dont la taille est supérieur ou égale. On peut aussi utiliser une valeur négative pour retourner ceux dont la taille est négative ou égale.
  • depth : Limite la recherche à un n (entier) niveau.
  • contains : Recherche les fichiers contenant un pattern ou une expression régulière.
  • hidden : Faut-il inclure les fichiers par défaut (false)
  • recurse : Si la cible est un répertoire faut-il chercher dans les sous répertoires (false)

Exemple :

---
- hosts: all
  become_user: admuser
  become: true
  tasks:
    - name: On recherche les fichiers plus vieux que 4 semaines
      ansible.builtin.find:
        paths: /var/log
        file_type: file
        use_regex: yes
        patterns:
          - '^.*\.log.*$'
        age: 4w
        size: 1k
      register: find
    - name: debug
      ansible.builtin.debug:
        var: find

En retour :

ok: [devbox1] => {
    "find": {
        "changed": false,
        "examined": 24,
        "failed": false,
        "files": [
            {
                "atime": 1645617793.8855917,
                "ctime": 1648185728.1188698,
                "dev": 64771,
                "gid": 4,
                "gr_name": "adm",
                "inode": 28482,
                "isblk": false,
                "ischr": false,
                "isdir": false,
                "isfifo": false,
                "isgid": false,
                "islnk": false,
                "isreg": true,
                "issock": false,
                "isuid": false,
                "mode": "0640",
                "mtime": 1648185728.1188698,
                "nlink": 1,
                "path": "/var/log/cloud-init-output.log",
                "pw_name": "root",
                "rgrp": true,
                "roth": false,
                "rusr": true,
                "size": 16723,
                "uid": 0,
                "wgrp": false,
                "woth": false,
                "wusr": true,
                "xgrp": false,
                "xoth": false,
                "xusr": false
            },
            ...
        ],
        "matched": 2,
        "msg": ""
    }
}

fetch

Le module fetch va vous permettre de récupérer le contenu de fichiers présents sur les machines distantes.

  • src : Le chemin du fichier sur la machine distante.
  • dest : Indique dans quel répertoire copier le fichier.
  • flat : Permet de modifier le comportement de nommage des fichiers sur la machine locale. Si dest est un répertoire alors le fichier locale aura le même nom que le fichier distant. Donc si vous l'utilisez avec plusieurs hôtes ajouter un suffixe à dest pour les différencier.
  • fail_on_missing : On peut modifier le comportement par défaut la tâche échouera si le fichier est absent.
  • validate_checksum : Vérifie que les sommes de contrôle des fichiers source et destination correspondent.

Ce qui donne par exemple :

    - name: retrieve file on remote
      ansible.builtin.fetch:
        src: /etc/passwd
        dest: "/tmp/test/passwd-{{ ansible_hostname }}"
        flat: true

slurp

Le module slurp permet également de récupérer le contenu de fichiers distant, mais au lieu de déposer le résultat dans des fichiers locaux, slurp encode le contenu en mémoire.

  • src : le chemin du fichier à récupérer
    - name: retrieve file on remote
      ansible.builtin.slurp:
        src: /etc/passwd
      register: result

Pour utiliser le contenu du fichier, il suffit d'utiliser le filtre jinja b64decode sur content :

    - name: debug
      ansible.builtin.debug:
        msg: "{{ result['content'] | b64decode }}"

tempfile

Un peu comme pour find ce module reproduit le fonctionnement de la commande linux mktemp.

  • path : Chemin du répertoire où sera créé le fichier temporaire sur la cible. Par défault /tmp/
  • prefix : Par défaut les fichiers auront le suffixe ansible, mais vous pouvez le modifier.
  • suffix : Par défaut les fichiers n'auront pas de suffix, mais vous pouvez en ajouter un.
  • state : Permet de définir s'il s'agit d'un (file) ou d'un directory.

Exemple :

- name: Create temporary file
  ansible.builtin.tempfile:
    state: file
    suffix: tmp
  register: tempfile

Ce qui donne :

ok: [devbox1] => {
    "tempfile": {
        "changed": true,
        "failed": false,
        "gid": 1000,
        "group": "admuser",
        "mode": "0600",
        "owner": "admuser",
        "path": "/tmp/ansible.yVdLkZtmp",
        "size": 0,
        "state": "file",
        "uid": 1000
    }
}

get_url

get_url permet de télécharger des fichiers depuis des servers HTTP et FTP.

Les principaux arguments :

  • url : url à utiliser de la forme (http|https|ftp)://[user[:pass]]@host.domain[:port]/path
  • dest : Répertoire ou chemin du fichier ou sera déposé le téléchargement sur le serveur cible.
  • owner : Définit le propriétaire.
  • group : Définit le groupe.
  • mode : Définit les droits d'accès. Par défaut (0644)
  • timeout : Par défaut définit à (10)
  • force : Si dest n'est pas un répertoire et que force est défini à true alors le téléchargement sera toujours réalisé (false)
  • headers : Ajoute des paramètres d'entête à la requête. S'écrit sous la forme d'une chaine de caractère "key:value,key:value"
  • checksum : Chaine de controle s'écrit sous la forme d'une chaine de caractère contenant soit la valeur "sha256:D98291AC ... B6DC7B97" soit l'url "sha256:http://example.com/path/sha256sum.txt"
  • tmp_dest : Télécharge le fichier dans un répertoire temporaire avant de le
  • copier dans la destination. Utile dans le cas où il existe des triggers sur le répertoire

Exemple :

    - name: install rundeck
      become_user: rundeck
      ansible.builtin.get_url:
        url: "https://packagecloud.io/pagerduty/rundeck/packages/java/org.rundeck/rundeck-4.0.0-{{ rundeck_version }}.war/artifacts/rundeck-4.0.0-{{ rundeck_version }}.war/download"
        dest: "{{ rundeck_installation_dir }}/rundeck-{{ rundeck_version }}/rundeck.war"
        owner: "{{ rundeck_os_user }}"

La suite des arguments :

  • use_proxy : Désactive l'utilisation des variables d'environnement proxy (false)
  • use_gssapi : Utilise la méthode GSSAPI pour l'authenfication (false)
  • force_basic_auth : Force l'utilisation de l'authenfication basique (false)
  • url_username : Le user ou crédential à utiliser avec les paramètres use_gssapi et force_basic_auth.
  • url_password : Le mot de passe à utiliser avec les paramètres use_gssapi et force_basic_auth.
  • unsafe_writes : A utiliser avec précaution, en l'activant vous pouvez obtenir des corruptions sur les fichiers. (false)
  • sha256sum : Controle de l'intégrité du fichier avec la valeur founie ("")
  • attributes : Définit les attributs du fichier. [aAcCdDeFijPsStTu]. ([])
  • backup : Fait un backup avant d'opérer (false). Création d'un fichier avec un horodatage ex : file.1239239.2022-03-28@09:07:33
  • validate_certs : (true) Si on ne peut valider le certificat alors passer cet argument à true.
  • client_cert : Chaine de certificats à utiliser pour valider celui du serveur de téléchargement. format PEM
  • client_key : La clé privée de la chaine de certification. format PEM
  • unredirected_headers : Liste de paramètres d'entête à ne pas envoyer dans une éventuelle redirection.

Pour la modification des droits SeLinux avec selevel, serole, setype, seuser

Pour utiliser un proxy avec get_url il suffit de définir des variables d'environnement <protocol>_proxy sur le serveur cible. Un exemple en utilisant un fichier de variable de groupe :

---
# file: group_vars/test

proxy_env:
  http_proxy: <http://proxy.robert.local:8080>
  https_proxy: <http://proxy.robert.local:8080>

Pour désactiver l'utilisation du proxy il suffit d'utiliser le paramètre use_proxy avec comme valeur false.

unarchive

Ce module fonctionne comme le module copy sauf qu'il prend en charge les archives compressées de différents formats (zip, tar, gzip et bzip2). Attention les outils de décompression gtar et unzip doivent être présent sur les machines cible. Donc avant tout chose, utilisez le module package pour vous assurer quil sont présents.

Les principaux paramètres :

  • src : Chemin relatif ou absolu de l'archive source. Cette source peut également être une URL.
  • dest : Répertoire ou sera déposé l'archive sur la cible.
  • copy : Le fichier est copié sur la cible avec l'extraction. (true)
  • creates : Vérifie que le répertoire cible existe.
  • owner : Définit le propriétaire.
  • group : Définit le groupe.
  • mode : Définit les droits d'accès. Par défaut (0644)
  • remote_src : Indique si la source est sur la machine locale ou est sur la machine cible. (false)
  • include : Liste des fichiers à extraire. ([])
  • exclude : Liste des fichiers à exclure lors de l'extraction ([])
  • extra_opts : Permet d'ajouter des options aux commandes tar et unzip. ("")
  • keep_newer : Ne remplace pas les fichiers existants. (false)
  • list_files : Liste les fichiers décompressés. (false)
  • validate_certs : Si la source est une URL permet d'indiquer d'accepter
  • les connexions unsecure. C'est pas bien ! (true)

Exemple :

    - name: Create temporary file
      ansible.builtin.unarchive:
        src: archive.tar
        dest: /tmp/test/archive

Les autres paramètres :

  • attributes : Définit les attributs du fichier. [aAcCdDeFijPsStTu].([])
  • follow : Utilisé avec les liens symboliques. Si le lien existe, il est mis à jour. (false)
  • force : Idem Force la création des liens même si la source n'existe pas. (false)
  • unsafe_writes : A utiliser avec précaution, en l'activant vous pouvez obtenir des corruptions sur les fichiers. (false)
  • decrypt : Si les fichiers sources sont dans un vault doivent-ils être décrypté. (true).
  • io_buffer_size : Taille du buffer à utiliser pour la décompression (64 Kib).

Pour la modification des droits SeLinux avec selevel, serole, setype, seuser

uri

Ce module, à ne pas confondre avec get_url, permet d'interagir avec des webservices. Il prend en charge les système d'authentification digest, basic et wsse.

Les principaux paramètres :

  • url : url à utiliser de la forme (http|https)://host.domain[:port]/path
  • method : La methode HTTP à utiliser : GET, POST, DELETE, ...
  • body : Le corps de la requête dans le format indiqué avec le paramètre ci-dessous.
  • body_format : json, form-urlencoded, (raw), form-multipart
  • src : Chemin du fichier à envoyer au serveur. Ne peut pas être utilisé avec l'argument body. ("")
  • remote_src : Le fichier se trouve t'il déja sur la cible ? (false)
  • status_code : Liste des valeurs de retour qui permettent de définir le succès de la requête. ([200])
  • dest : Répertoire ou chemin du fichier ou sera déposé si besoin le téléchargement sur le serveur cible.
  • owner : Définit le propriétaire.
  • group : Définit le groupe.
  • mode : Définit les droits d'accès. Par défaut (0644)
  • timeout : Par défaut définit à (10)
  • force : Si dest n'est pas un répertoire et que force est défini à true alors le téléchargement sera toujours réalisé (false)
  • headers : Ajoute des paramètres d'entête à la requête. S'écrit sous la forme d'une chaine de caractère "key:value,key:value"
  • follow_redirects : Permet de définir la méthode de redirection : (safe), no, none, all, yes, urllib2
  • creates : Chemin d'un fichier qui quand il existe ne lance pas cette tache. ("")
  • removes : Chemin d'un fichier qui quand il n'existe pas ne lance pas cette tache. ("")
  • return_content : (false)
  • tmp_dest : Télécharge le fichier dans un répertoire temporaire avant de le
  • copier dans la destination. Utile dans le cas où il existe des triggers sur le répertoire

Exemple :

    - name: Create a JIRA issue
      uri:
        url: https://jira.robert.local/rest/api/2/issue/
        user: srobert
        password: monpassword
        method: POST
        body: "{{ lookup('file','issue.json') }}"
        force_basic_auth: yes
        status_code: 201
        body_format: json

La suite des paramètres :

  • use_proxy : Désactive l'utilisation des variables d'environnement proxy (false)
  • use_gssapi : Utilise la méthode GSSAPI pour l'authenfication (false)
  • force_basic_auth : Force l'utilisation de l'authenfication basique (false)
  • url_username : Le user ou crédential à utiliser avec les paramètres use_gssapi et force_basic_auth.
  • url_password : Le mot de passe à utiliser avec les paramètres use_gssapi et force_basic_auth.
  • unsafe_writes : A utiliser avec précaution, en l'activant vous pouvez obtenir des corruptions sur les fichiers. (false)
  • sha256sum : Controle de l'intégrité du fichier avec la valeur founie ("")
  • attributes : Définit les attributs du fichier. [aAcCdDeFijPsStTu]. ([])
  • backup : Fait un backup avant d'opérer (false). Création d'un fichier avec un horodatage ex : file.1239239.2022-03-28@09:07:33
  • validate_certs : (true) Si on ne peut valider le certificat alors passer cet argument à true.
  • ca_path : Le chemin de la chaine de certification permettant de valider le certificat du serveur distant.
  • client_cert : Chaine de certificats à utiliser pour valider celui du serveur de téléchargement. format PEM
  • client_key : La clé privée de la chaine de certification. format PEM
  • force_basic_auth : force l'utilisation de l'authenfication basique (false)
  • unredirected_headers : Liste de paramètres d'entête à ne pas envoyer dans une éventuelle redirection.
  • unix_socket : Chemin du socket Unix à utiliser
  • http_agent : Nom de l'agent à envoyer au serveur distant ("ansible-httpget")

Pour la modification des droits SeLinux avec selevel, serole, setype, seuser

git

Les principaux paramètres :

  • repo : Adressse du repository git au format ssh ou https.
  • clone : Clone ou pas le repository (true)
  • depth : Troncate de l'historique avec l'entier. La valeur la plus petite est 1.
  • dest : Le répertoire ou sera déposé le projet.
  • update : Récupère les nouvelles versions (true).
  • version : Permet d'indiquer le nom d'une branch, d'un tag ou d'un SHA-commit à récupérer.("HEAD")
  • recursive : Permet d'indiquer de ne pas récupérer les sous-modules (true).
  • force : Permet de détruire les mises à jour effectuer dans le répertoire (false).
  • executable : Chemin de l'executable de git., si besoin de changer de version que celle trouvée dans la variable $PATH.
  • remote : Nom du remote ("origin")
  • single_branch :

Exemple :

- name: Example clone of a single branch
  ansible.builtin.git:
    repo: https://github.com/ansible/ansible-examples.git
    dest: /src/ansible-examples
    single_branch: yes
    version: master

La suite des paramètres :

  • accept_hostkey : Ajoute l'expression "-o StrictHostKeyChecking=no" au option de la commande ssh. (false)
  • accept_newhostkey : idem mais avec l'option"-o StrictHostKeyChecking=accept-new" (false)
  • key_file : Chemin de la clé SSH privé à utiliser pour se connecter ("")
  • ssh_opts : Permet de spécifier d'autres arguments à passer à la connexion ssh ("")
  • archive : Permet de créer une archive du repo en indiquant le chemin ou elle doit être créer.("")
  • archive_prefix : Permet d'ajouter un prefix à l'archive. Valeur autorisée : zip, tar.gz, tar, tgz. ("")
  • bare : Création d'un bare repo sur la cible. (false)
  • verify_commit : Permet de verifier le contenu avec une empreinte GPG. (false)
  • gpg_whitelist : Liste d'empreinte GPG permettant de valider le commit ([])
  • reference : Reference repository
  • refspec : Un référence à utiliser pour être fetcher.
  • separate_git_dir : Le chemin ou déposer le projet cloné.
  • track_submodules : Permet de forcer la récupération des derniers commit de la branche master des sous-modules.
  • umask : Le umask à appliquer.

Les modules de la communauté

Certaines actions ne sont pas prises en charge par les modules de base Ansible. Mais la communauté Ansible propose plusieurs modules les apportant. Je compléterai ce billet dans les prochains jours.