--- # LES ÉPINGLES, POSÉES COMME PRÉFÉRENCES APT — cache ou pas (voir defaults/main.yml). # Une préférence par paquet : plusieurs rôles appellent celui-ci sur la même machine, et # un fichier commun serait réécrit par chacun avec ses seuls paquets. - name: Lire les épingles du dépôt ansible.builtin.set_fact: paquets_tiers_toutes: >- {{ (lookup('ansible.builtin.file', paquets_tiers_fichier_epingles) | from_yaml).depots | dict2items | map(attribute='value.paquets') | list | combine }} - name: Retenir celles de cet appel (toutes, pour le socle) ansible.builtin.set_fact: paquets_tiers_epingles: >- {{ paquets_tiers_toutes if (paquets_tiers_toutes_epingles | bool) else (paquets_tiers_toutes | dict2items | selectattr('key', 'in', paquets_tiers_noms) | items2dict) }} - name: Épingler les paquets tiers (préférence apt) ansible.builtin.copy: dest: "/etc/apt/preferences.d/setops-{{ item.key }}" content: | # Géré par Set-OPS (rôle paquets_tiers, depuis paquets-tiers.yml). Ne pas éditer. Package: {{ item.key }} Pin: version {{ item.value }} Pin-Priority: {{ paquets_tiers_priorite }} owner: root group: root mode: "0644" loop: "{{ paquets_tiers_epingles | dict2items }}" loop_control: label: "{{ item.key }}={{ item.value }}" # CE QUE L'ÉPINGLE NE PEUT PAS FAIRE, ET QU'IL FAUT DIRE. Deux cas où elle ne tient pas : # - le paquet est DÉJÀ plus récent : 990 ne rétrograde pas (c'est voulu) — l'épingle est # en retard sur la machine, et il faut la relever, pas laisser l'écart dormir ; # - la version épinglée n'est PAS dans l'index du dépôt : apt ignore la préférence sans # un mot et reprend la dernière version — la candidate est alors plus récente. # Ce second contrôle n'a pas cours en simulation : la préférence n'y est pas écrite, et la # candidate lue serait celle d'avant l'épingle — une fausse alerte à chaque `--check`. - name: Comparer installé, candidat et épingle ansible.builtin.shell: | set -uo pipefail {% for nom, version in paquets_tiers_epingles.items() %} inst=$(dpkg-query -W -f='${Version}' {{ nom }} 2>/dev/null || true) cand=$(apt-cache policy {{ nom }} 2>/dev/null | awk '/Candidate:/ {print $2}') if [ -n "$inst" ] && dpkg --compare-versions "$inst" gt "{{ version }}"; then echo "PLUS_RECENT {{ nom }} installe=$inst epingle={{ version }}" fi {% if not ansible_check_mode %} if [ -n "$cand" ] && [ "$cand" != "(none)" ] && dpkg --compare-versions "$cand" gt "{{ version }}" \ && { [ -z "$inst" ] || dpkg --compare-versions "$cand" gt "$inst"; }; then echo "INOPERANTE {{ nom }} candidat=$cand epingle={{ version }}" fi {% endif %} {% endfor %} true args: executable: /bin/bash environment: LC_ALL: C register: paquets_tiers_ecarts changed_when: false check_mode: false when: paquets_tiers_epingles | length > 0 - name: Refuser une épingle qui ne tient pas ansible.builtin.assert: that: - paquets_tiers_ecarts.stdout_lines | default([]) | length == 0 fail_msg: >- Épingle(s) de paquets-tiers.yml qui ne tiennent pas sur {{ inventory_hostname }} : {{ paquets_tiers_ecarts.stdout_lines | default([]) | join(' ; ') }}. PLUS_RECENT : relever l'épingle sur la version installée (puis `make cacher-paquets`). INOPERANTE : la version épinglée n'est pas dans l'index du dépôt — en choisir une qui y est. when: paquets_tiers_epingles | length > 0