--- # DÉGRADER, JAMAIS DEVINER. Sans cache sur le contrôleur, ce rôle ne fait rien et le DIT : # l'appelant installera depuis le dépôt distant, comme avant. On ne casse pas un # déploiement connecté parce qu'un cache manque. # LES ÉPINGLES D'ABORD — voir `epingles.yml`, que le socle appelle aussi pour TOUTES. - name: Épingler les paquets demandés (préférences apt) ansible.builtin.include_tasks: epingles.yml - name: Lire le manifeste du cache du contrôleur ansible.builtin.slurp: src: "{{ paquets_tiers_cache }}/MANIFESTE" delegate_to: localhost become: false register: paquets_tiers_manifeste failed_when: false changed_when: false # REMISE A ZERO AVANT DE REMPLIR. Un `set_fact` survit au role : appele deux fois dans # le meme play, ce dictionnaire garderait les paquets du premier appelant et les # reinstallerait chez le second. Une variable qui traine est une action qu'on ne demande # plus mais qui a toujours lieu. - name: Repartir d'un inventaire vide ansible.builtin.set_fact: paquets_tiers_disponibles: {} # Le manifeste porte une ligne `nom=version fichier.deb` par paquet mis en cache. On n'en # retient que les noms que l'appelant a DEMANDES : un role n'installe pas ce qu'il n'a # pas declare vouloir, meme si le cache le contient. - name: Établir ce que le cache peut fournir ansible.builtin.set_fact: paquets_tiers_disponibles: >- {{ paquets_tiers_disponibles | combine({ (item.split(' ')[0].split('=')[0]): item.split(' ')[1] }) }} loop: "{{ (paquets_tiers_manifeste.content | default('') | b64decode).splitlines() }}" when: - item is search('=') - item.split(' ') | length > 1 - item.split(' ')[0].split('=')[0] in paquets_tiers_noms loop_control: label: "{{ item.split(' ')[0] }}" - name: Dire que le cache ne couvre pas ces paquets ansible.builtin.debug: msg: >- Aucun paquet en cache pour {{ paquets_tiers_noms | join(', ') }} — ils seront tirés du dépôt distant. Une reconstruction SANS INTERNET échouera ici. Lancer `make cacher-paquets` depuis un poste connecté. when: - paquets_tiers_noms | length > 0 - paquets_tiers_disponibles | length == 0 - name: Assurer le répertoire des paquets déposés ansible.builtin.file: path: "{{ paquets_tiers_dest }}" state: directory owner: root group: root mode: "0755" when: paquets_tiers_disponibles | length > 0 - name: Déposer les paquets depuis le cache du contrôleur ansible.builtin.copy: src: "{{ paquets_tiers_cache }}/{{ item.value }}" dest: "{{ paquets_tiers_dest }}/{{ item.value }}" owner: root group: root mode: "0644" loop: "{{ paquets_tiers_disponibles | dict2items }}" loop_control: label: "{{ item.key }}" # GARDER LES FICHIERS DE CONFIGURATION QUE LES RÔLES ONT MODIFIÉS (2026-10-03). Tant que ce # rôle ne faisait que des PREMIÈRES installations, aucun fichier n'avait été touché. Depuis # que les épingles montent, il MET À JOUR : sur `site-dns-01`, `alloy` 1.19.2 -> 1.20.1 a # demandé quoi faire de `/etc/default/alloy` (le port y est imposé par `client_journal`), # sans personne pour répondre — « fin de fichier sur l'entrée standard », paquet déballé et # NON configuré. Mêmes options que le socle (`common_packages`) : garder la version locale. # # EN UN SEUL APPEL, ET C'EST LE POINT. `apt` sait résoudre un ENSEMBLE de fichiers locaux # — l'un dépendant de l'autre — alors qu'une installation paquet par paquet échouerait sur # l'ordre. Icinga en apporte dix-sept qui se dépendent mutuellement : les poser un à un # demanderait de connaître leur graphe, que seul apt connaît. # # Les dépendances Debian, elles, viennent du cache du site en HTTP, comme d'habitude. - name: Installer les paquets tiers depuis le cache ansible.builtin.command: argv: >- {{ ["apt-get", "install", "-y", "--no-install-recommends", "-o", "Dpkg::Options::=--force-confdef", "-o", "Dpkg::Options::=--force-confold"] + (paquets_tiers_disponibles.values() | map('regex_replace', '^', paquets_tiers_dest ~ '/') | list) }} environment: DEBIAN_FRONTEND: noninteractive register: paquets_tiers_pose # UNE MISE À JOUR EST UN CHANGEMENT (2026-10-03). La garde ne cherchait que « 0 nouvellement # installés », qu'apt écrit AUSSI quand il met à jour (« 1 mis à jour, 0 nouvellement # installés ») : `alloy` 1.19.2 -> 1.20.1 sur `site-cache-01` s'est rapporté « ok ». changed_when: "'0 mis à jour, 0 nouvellement installés' not in paquets_tiers_pose.stdout and '0 upgraded, 0 newly installed' not in paquets_tiers_pose.stdout" when: paquets_tiers_disponibles | length > 0