Créez et récupérez les planches-contact

AnsibleBeginner
Pratiquer maintenant

Introduction

L’éditeur de Field Notes dispose de deux postes photo contenant des sélections différentes à traiter. Une planche-contact et sa liste de fichiers correspondante permettent de sélectionner les photographies, mais un travail lancé en arrière-plan ou un ancien fichier homonyme ne constitue pas une livraison terminée. Créez un petit exemple, puis utilisez Ansible pour attendre et récupérer les véritables résultats actuels de chaque poste.

Vous devez savoir naviguer dans le terminal et avoir pratiqué un petit inventaire Ansible, les variables et les tâches command/file. L’accès SSH, les photographies sous licence et l’outil d’images sont prêts. Ce laboratoire explique les listes d’arguments, les boucles, les identifiants par hôte, les contrôles de fin et les destinations fetch avant leur utilisation. La durée est une estimation de l’auteur comprenant lecture et corrections habituelles, pas un temps mesuré auprès de débutants.

Créez une petite planche-contact

Dans cette étape, vous exécuterez un petit travail photo avec Ansible, récupérerez son image et sa liste réelles et utiliserez ces résultats comme modèle pour le travail plus important.

Ouvrez l’onglet Photo Desk. Dans A previous walk, cliquez sur Open contact sheet. Une planche-contact rassemble de petites versions de plusieurs photographies sur une page afin de comparer les cadrages sans ouvrir tous les originaux. Cet exemple historique porte l’étiquette previous-walk : il sert de référence, pas de travail terminé pour aujourd’hui. Sur un écran étroit, faites défiler l’intérieur du cadre de l’image pour lire les noms. Cliquez sur Back to photo desk pour revenir à la page dans le même onglet.

L’histoire et l’affectation des postes sont fictives. Les paysages constituent une collection pédagogique sous licence ; Photo credits indique leurs véritables photographes et sources. L’outil préparé lit de vrais fichiers JPEG et crée une planche PNG ainsi qu’une liste CSV. Vous automatiserez cet outil sans écrire de code de traitement d’images.

Passez à l’onglet Controller. Il démarre dans /home/labex/project. Le contrôleur exécute Ansible. Ses deux cibles SSH sont des conteneurs partageant le noyau de cette VM de formation, pas deux VM indépendantes. Chaque cible possède ses propres fichiers, même si les chemins portent les mêmes noms.

pwd affiche le répertoire courant et cat affiche un fichier. Lisez l’inventaire et les variables préparés :

pwd
cat inventory.yml
cat group_vars/all.yml
cat host_vars/camera-north.yml
cat host_vars/camera-south.yml

Le groupe cameras de l’inventaire contient camera-north et camera-south avec leurs véritables paramètres SSH. Le fichier ansible.cfg du projet sélectionne cet inventory.yml et les paramètres préparés de confiance des hôtes. Le fichier inventory.ini initial de l’image n’est pas l’inventaire du cours. Conservez la configuration, l’inventaire et les fichiers de variables.

Les accolades de style JSON de ces fichiers sont du YAML valide. group_vars/all.yml fournit les variables communes : input_root vaut /srv/photo-sheets/batches, output_root vaut /srv/photo-sheets/rendered et collection_root désigne le répertoire collected du contrôleur, à côté du playbook. Un fichier dans host_vars concerne l’hôte portant son nom. Ici, photo_batch sélectionne morning-walk sur le poste nord et afternoon-walk sur le poste sud. Les sélections du jour diffèrent par leur contenu et leur taille.

Utilisez d’abord l’entrée sample préparée avec deux photos sur le poste nord. Le module command d’Ansible exécute le programme préparé sur cette cible SSH. Sa liste argv transmet un argument par élément, sans demander à un shell d’interpréter une chaîne de commande. L’option --input choisit le répertoire source, --output celui des résultats et --station identifie le poste dans le résultat. Aucune photographie source n’est modifiée.

{{ variable }} insère une valeur Ansible. inventory_hostname est le nom de l’hôte courant dans l’inventaire ; playbook_dir est le répertoire contenant le playbook sur le contrôleur. gather_facts: false évite la collecte d’informations machine inutile pour ce travail photo.

Le module fetch transfère un fichier de la cible SSH vers le contrôleur, dans le sens inverse de copy. Une loop répète ce transfert pour les deux noms indiqués ; {{ item }} représente le nom courant. Par défaut, fetch conserve une arborescence comprenant l’hôte et le chemin source. Ici, flat: true retire le chemin source : la destination inclut donc explicitement inventory_hostname. Les fichiers homonymes de postes différents restent ainsi séparés. fetch crée les répertoires de destination nécessaires.

Créez sample.yml. cat > filename écrit un fichier et remplace un éventuel fichier homonyme. <<'YAML' commence un here-document : collez le texte jusqu’au YAML final, seul sur sa ligne. Le délimiteur entre guillemets conserve littéralement le texte collé ; Ansible traite les expressions lors de l’exécution du playbook. L’indentation YAML utilise des espaces :

cat > sample.yml <<'YAML'
- name: Build a small selection before scheduling both workstations
  hosts: camera-north
  gather_facts: false
  tasks:
    - name: Build the two-photo practice sheet
      ansible.builtin.command:
        argv:
          - /usr/local/bin/photo-sheet
          - --input
          - "{{ input_root }}/sample"
          - --output
          - "{{ output_root }}/sample"
          - --station
          - "{{ inventory_hostname }}"
    - name: Collect the practice image and file list
      ansible.builtin.fetch:
        src: "{{ output_root }}/sample/{{ item }}"
        dest: "{{ playbook_dir }}/sample/{{ inventory_hostname }}/"
        flat: true
      loop:
        - contact-sheet.png
        - files.csv
YAML

Vérifiez la syntaxe avant d’exécuter le travail. --syntax-check contrôle la structure du playbook ; il ne traite pas les photographies :

ansible-playbook sample.yml --syntax-check

En cas de faute de frappe ou d’indentation, recopiez le playbook complet et répétez le contrôle. Exécutez-le maintenant :

ansible-playbook sample.yml

La tâche d’image est synchrone par défaut : Ansible attend la fin du programme avant de récupérer les fichiers. Le récapitulatif doit afficher failed=0 et unreachable=0. Un travail photo effectue un traitement et peut signaler changed ; répéter un traitement d’images ne garantit pas l’absence de changements.

Lisez la liste récupérée :

cat sample/camera-north/files.csv

L’en-tête est station,batch,position,filename,sha256,width,height. Deux lignes doivent concerner camera-north et sample, dans le même ordre de gauche à droite que les images. Les fichiers s’appellent frame-01.jpg et frame-02.jpg. SHA256 est une empreinte du contenu de chaque fichier source ; inutile de mémoriser ces longues valeurs. Les dimensions décrivent la photographie originale, pas son petit aperçu.

Passez à Photo Desk et rechargez la page. Dans Small practice sheet, utilisez Open contact sheet pour examiner votre véritable résultat de deux photos. Revenez avec Back to photo desk, puis utilisez Download contact sheet (PNG) et Download file list (CSV) dans cette carte. Ouvrez l’image et le CSV téléchargés : les deux photos, les noms et l’ordre des lignes doivent correspondre. Le navigateur peut ajouter un numéro au nom d’un téléchargement répété.

La carte ci-dessous montre la véritable image de deux photos et les deux liens de téléchargement. Vérifiez le poste et l’étiquette sample avant d’utiliser les fichiers.

Planche d’exercice et téléchargements PNG et CSV correspondants

Si une commande indique « No such file or directory », ls affiche le répertoire courant pour vérifier l’orthographe. Utilisez cd /home/labex/project pour revenir à l’espace de travail, puis répétez la commande appropriée. Conservez toutes les sources, références historiques, notes de l’éditeur et connexions préparées. Les plus grandes sélections actuelles ne sont pas encore générées.

Attendez chaque travail avant la récupération

Dans cette étape, vous lancerez les sélections actuelles sur les deux postes, attendrez la réussite propre à chaque hôte et récupérerez les fichiers correspondants sans collision.

Restez dans Controller, dans /home/labex/project. Le groupe cameras sélectionne les deux cibles ; le photo_batch de chacune choisit toujours son entrée préparée. Utilisez ces variables pour adapter le même processus à d’autres membres, noms de lots et répertoires sans figer les noms des deux postes ni leurs chemins.

Une tâche synchrone attend avant qu’Ansible passe à la suivante. Avec async: 120, Ansible accorde à l’opération distante un budget d’exécution de 120 secondes. poll: 0 la lance sans attendre sa fin dans cette tâche. Réussir le lancement ne signifie pas réussir le traitement : le travail distant peut encore se terminer par une erreur.

register: photo_job conserve séparément le résultat du lancement pour chaque hôte de l’inventaire. Son ansible_job_id identifie ce travail sur cet hôte. Le JID d’un poste ne permet pas d’interroger le résultat sur l’autre. Le module debug affiche les observations sauvegardées pour visualiser les différentes affectations.

async_status interroge le même hôte sur son JID et enregistre chaque réponse dans photo_result. until: photo_result is finished répète la consultation jusqu’à ce que l’indicateur natif de fin soit vrai ; retries: 60 borne les tentatives et delay: 1 attend une seconde entre elles. Ces répétitions consultent l’état, elles ne créent pas de nouveaux travaux photo. SSH et le traitement ajoutent leur durée réelle. Un petit lot peut déjà être terminé à la première consultation ; aucun délai artificiel n’est ajouté à cet exercice.

La fin ne suffit pas à établir la réussite. Le rc du programme distant est son code de sortie : zéro signifie réussite. Par défaut, async_status propage un résultat non nul comme un échec. L’assert supplémentaire rend explicite l’exigence de sortie zéro ; il ne transforme pas une erreur en réussite. La sortie de débogage suivante permet de lire les véritables valeurs de finished et rc avant la récupération. Un processus équivalent peut se fier à la propagation native de l’échec sans cette assertion supplémentaire.

Les deux hôtes produisent les mêmes noms, contact-sheet.png et files.csv, sur leurs propres systèmes de fichiers. Récupérez-les uniquement après la réussite et rangez chaque paire dans son dossier d’hôte d’inventaire sur le contrôleur. Photo Desk accepte cette disposition plate explicite ou l’arborescence hôte/chemin source par défaut à l’intérieur du dossier du poste. Il ne complète jamais une collection absente avec les références.

Écrivez process-photos.yml avec le même here-document entre guillemets qu’à l’étape précédente :

cat > process-photos.yml <<'YAML'
- name: Build and collect each workstation's current photo selection
  hosts: cameras
  gather_facts: false
  tasks:
    - name: Start this workstation's contact sheet
      ansible.builtin.command:
        argv:
          - /usr/local/bin/photo-sheet
          - --input
          - "{{ input_root }}/{{ photo_batch }}"
          - --output
          - "{{ output_root }}"
          - --station
          - "{{ inventory_hostname }}"
      async: 120
      poll: 0
      register: photo_job
    - name: Show the job assigned to this workstation
      ansible.builtin.debug:
        msg:
          workstation: "{{ inventory_hostname }}"
          job: "{{ photo_job.ansible_job_id }}"
    - name: Wait for this workstation's own job
      ansible.builtin.async_status:
        jid: "{{ photo_job.ansible_job_id }}"
      register: photo_result
      until: photo_result is finished
      retries: 60
      delay: 1
    - name: Require successful processing before collecting
      ansible.builtin.assert:
        that: photo_result.rc == 0
    - name: Read the actual completion result
      ansible.builtin.debug:
        msg:
          workstation: "{{ inventory_hostname }}"
          finished: "{{ photo_result.finished }}"
          rc: "{{ photo_result.rc }}"
    - name: Collect the image and its file list by workstation
      ansible.builtin.fetch:
        src: "{{ output_root }}/{{ item }}"
        dest: "{{ collection_root }}/{{ inventory_hostname }}/"
        flat: true
      loop:
        - contact-sheet.png
        - files.csv
YAML

Vérifiez la syntaxe :

ansible-playbook process-photos.yml --syntax-check

Lancez ensuite le véritable travail :

ansible-playbook process-photos.yml

Chaque poste doit afficher son identifiant, puis finished: true et rc: 0 dans le message de fin. Le récapitulatif doit indiquer failed=0 et unreachable=0 pour les deux hôtes. La sélection nord contient trois photos, celle du sud six. Les travaux peuvent se terminer à des moments différents. Cette exécution montre une véritable planification asynchrone, sans garantir les performances de charges plus importantes.

Lisez les deux listes récupérées :

cat collected/camera-north/files.csv
cat collected/camera-south/files.csv

Les champs station et batch doivent correspondre à l’affectation de chaque hôte. Des noms identiques n’impliquent pas des photos sources identiques. La position, le nom, l’empreinte et les dimensions de chaque ligne décrivent une véritable image d’entrée ; la planche suit le même ordre.

Passez à Photo Desk et rechargez. Dans Current collections, ouvrez le lien Open contact sheet de chaque poste. Examinez en taille réelle les planches de trois et six photos et utilisez Back to photo desk entre les deux. Téléchargez le PNG et le CSV de chaque poste, ouvrez-les et vérifiez la correspondance entre images et lignes complètes. La référence et votre petite collection d’exercice doivent rester disponibles.

Comparez les étiquettes d’hôte et de lot des deux cartes. La planche nord comporte une rangée de trois images ; celle du sud, deux rangées de trois issues de sélections différentes.

Collections actuelles séparées des postes nord et sud

Un travail terminé peut quand même échouer

Revenez dans Controller. Choisissez maintenant volontairement une entrée inexistante sur le seul poste nord. --limit camera-north limite l’invocation à cet hôte de l’inventaire. --extra-vars photo_batch=missing remplace la variable du lot pour cette invocation uniquement, sans modifier le fichier préparé. Le travail démarre, puis signale un traitement terminé en échec. Les bons fichiers existants ne prouvent pas une nouvelle réussite.

L’échec de cette commande est attendu :

ansible-playbook process-photos.yml --limit camera-north --extra-vars photo_batch=missing

Affichez immédiatement le code de la commande précédente. $? conserve le dernier code de sortie ; echo l’affiche. Une autre commande exécutée avant le remplacerait :

echo $?

Attendez un code CLI Ansible non nul, normalement 2. Dans le message d’échec, le résultat distant est terminé, le rc du programme vaut 2 et l’erreur mentionne /srv/photo-sheets/batches/missing. Le code CLI et celui du programme distant sont deux valeurs distinctes ; ils valent ici tous deux 2. Un travail terminé en échec n’est pas une récupération réussie. La tâche fetch ne doit pas s’exécuter pour cette tentative. Le poste sud n’est pas concerné par cette invocation.

Corrigez la sélection en revenant à la valeur préparée et relancez uniquement le poste nord :

ansible-playbook process-photos.yml --limit camera-north

Cette exécution doit réussir et récupérer le véritable résultat morning-walk. La collection sud reste disponible depuis son travail réussi. Retournez dans Photo Desk, rechargez et téléchargez à nouveau le PNG et le CSV du nord pour confirmer les trois bonnes photos. Gardez process-photos.yml réutilisable, toutes les sources et sorties historiques intactes et les notes de l’éditeur privées.

Pour une erreur ordinaire de YAML ou de nom, utilisez ls, le retour au bon répertoire et la correction du bloc complet appris précédemment, puis revérifiez la syntaxe. Ne réinitialisez pas la VM et ne modifiez pas une photo source pour masquer une erreur d’entrée. Répéter un travail réussi effectue de nouveau le traitement ; une somme de contrôle fetch inchangée ne signifie pas qu’aucun traitement n’a eu lieu.

Ansible conserve un cache d’état après poll: 0. Après avoir examiné un travail terminé, async_status avec mode: cleanup et le jid de cet hôte peut supprimer son entrée. Cette maintenance est facultative ici. Le nettoyage du cache n’annule pas un travail en cours et ne supprime pas la planche-contact.

Résumé

Vous avez créé une véritable petite planche-contact, puis utilisé Ansible pour lancer et attendre deux travaux asynchrones appartenant à leurs hôtes respectifs. Vous avez récupéré chaque paire complète image/CSV par poste, distingué un échec terminé d’une réussite et corrigé une entrée absente en relançant uniquement l’hôte concerné.