Set-OPS-Public/roles/paquets_tiers/tasks/epingles.yml
Daniel Allaire 715f9de84d paquets tiers : les épingles tiennent, cache ou pas
- épingles posées en préférences apt (990) par chaque rôle et par le socle
  avant son dist-upgrade ; garde : paquet plus récent ou épingle inopérante
- quatre épingles relevées (step-cli, icingadb-redis, icinga-php-*)
- paquets_tiers : --force-confold aux mises à jour ; une mise à jour compte
  comme un changement
- CHANGELOG 66

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:52:25 -04:00

75 lines
3.5 KiB
YAML

---
# 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