This commit is contained in:
Eric SYLVIUS
2026-09-27 14:43:29 +02:00
parent d3bf57e46a
commit 5793b435ee

View File

@@ -1,7 +1,6 @@
# Automatisation update Portainer (Node-RED + Home Assistant)
Documentation basée sur l'export final du flow `pveSystem`, vérifiée ligne par ligne contre le JSON fourni. Aucune information ci-dessous n'est devinée ; là où un point reste incertain, un niveau de confiance est indiqué.
Documentation du flow `pveSystem`, section mise à jour automatique des conteneurs Portainer.
## Objectif
@@ -11,29 +10,28 @@ Détecter automatiquement quand un nombre suffisant de conteneurs Portainer ont
Node-RED, node inject **`triggerWedSun-1300`**, planification cron : `30 13 * * 3,0`.
Cela signifie : tous les **mercredis et dimanches à 13h30**. C'est ce planning, et non une vérification "si ce n'est pas vendredi" à l'exécution, qui limite les jours où l'automatisation peut se déclencher. Plus simple que l'approche initialement envisagée (un node function séparé), et ça respecte la règle "solution native la plus simple d'abord".
Cela signifie : tous les **mercredis et dimanches à 13h30**. C'est ce planning qui limite les jours où l'automatisation se déclenche, pas une vérification à l'exécution.
## Pipeline Node-RED (onglet pveSystem)
1. **triggerWedSun-1300** (inject, cron) déclenche tout le pipeline.
2. **portainer_auto** (node Get Entities) récupère les entités `update.*` qui remplissent DEUX conditions à la fois :
2. **portainer_auto** (node Get Entities) récupère les entités `update.*` qui remplissent deux conditions à la fois :
- `state == on` (une mise à jour est disponible)
- label registry `name == portainer_auto`
Sortie : tableau (`outputType: array`). Testé empiriquement le 27/09/2026 : 13 éléments retournés. Le champ `outputResultsCount: 1` présent dans la config ne limite pas le résultat, vérifié par ce même test.
3. **updateContainer>=10** (node switch), propriété `payload.length`, règle `gte 10`. En dessous de 10 mises à jour en attente, rien ne se passe, le pipeline s'arrête ici.
4. Si le seuil est atteint, **trois actions partent en parallèle**, pas en séquence :
- **containerUpdateAll** → appelle le service `update.install`, ciblé par label `portainer_auto` (tous les conteneurs labellisés d'un coup). C'est l'action qui lance réellement les mises à jour.
3. **updateContainer>=10** (node switch), propriété `payload.length`, règle `gte 10`. En dessous de 10 mises à jour en attente, le pipeline s'arrête ici.
4. Si le seuil est atteint, trois actions partent en parallèle :
- **containerUpdateAll** → appelle le service `update.install`, ciblé par label `portainer_auto`. C'est l'action qui lance les mises à jour.
- **portainerUpdateAllMsg** → déclenche l'automation HA `automation.portainerupdateallmsg` (notification "avant").
- Un délai de **10 minutes**, puis **portainerUpdatedAllMsg** → déclenche l'automation HA `automation.portainerupdatedallmsg` (message de suivi).
**Point de vigilance (confiance 90%, lecture directe du flow) :** la notification "avant" et le lancement réel de `update.install` partent au même instant. Le message Telegram n'est donc pas une alerte qu'on peut annuler avant exécution, c'est un avertissement envoyé en parallèle de l'action, conforme à ce qui avait été demandé ("exécution auto").
La notification "avant" et le lancement de `update.install` partent au même instant : le message Telegram est un avertissement envoyé en parallèle de l'action, pas une alerte qu'on peut annuler avant exécution.
## Les deux automations Home Assistant
### `automation.portainerupdateallmsg` — notification "avant"
Titre : 🚨Update is available!🚨
Liste, triée alphabétiquement par nom de conteneur (pas de sha256 affiché), tous les conteneurs actuellement en attente de mise à jour :
Liste, triée alphabétiquement par nom de conteneur, tous les conteneurs actuellement en attente de mise à jour :
```
{% for e in label_entities('portainer_auto') if states(e) == 'on' %}
@@ -41,42 +39,39 @@ Liste, triée alphabétiquement par nom de conteneur (pas de sha256 affiché), t
Envoyée en parallèle via :
- `telegram_bot.send_message` (avec `parse_mode: plain_text` obligatoire, sinon Telegram plante sur les underscores des noms de conteneurs comme `athtk_ctr`)
- `telegram_bot.send_message` (avec `parse_mode: plain_text`, requis car les noms de conteneurs contiennent des underscores qui cassent le Markdown Telegram)
- `persistent_notification.create`
### `automation.portainerupdatedallmsg` — message de suivi, +10 min
Titre : ✅Update is Done✅
Utilise **exactement le même filtre** (`states(e) == 'on'`) que l'automation précédente. Malgré son titre, elle ne confirme donc pas que tout est fini : elle recompte, 10 minutes après le lancement, ce qui est **encore** en attente et affiche "X update(s) remain!". Un résultat proche de 0 indique un succès ; un nombre non nul signale des conteneurs pas encore à jour (mise à jour en cours, lente, ou échouée).
**Point de vigilance :** 10 minutes est une valeur fixe, pas calculée. Sur une connexion lente ou avec beaucoup d'images volumineuses à tirer, ce délai peut être insuffisant et afficher un "reste X" alors que les mises à jour sont simplement encore en cours.
Utilise le même filtre (`states(e) == 'on'`) que l'automation précédente. Elle recompte, 10 minutes après le lancement, ce qui est encore en attente et affiche "X update(s) remain!". Un résultat proche de 0 indique un succès ; un nombre non nul signale des conteneurs pas encore à jour.
## Le label HA `portainer_auto`
Créé manuellement dans HA (Paramètres > Zones, étiquettes et emplacements > Étiquettes). Appliqué en masse aux **54 entités** `update.*` de l'intégration Portainer (Paramètres > Appareils et services > Entités, filtré par intégration "Portainer", sélection groupée + Add label).
Créé dans HA (Paramètres > Zones, étiquettes et emplacements > Étiquettes). Appliqué en masse aux 54 entités `update.*` de l'intégration Portainer (Paramètres > Appareils et services > Entités, filtré par intégration "Portainer", sélection groupée + Add label).
Toutes les entités Portainer portent ce label, qu'une mise à jour soit disponible ou non à un instant donné ; c'est le filtre `state == on`, présent à la fois côté Node-RED (rule "state_object") et côté Jinja (`if states(e) == 'on'`), qui isole celles ayant réellement une mise à jour en attente. Ces deux filtres sont indépendants l'un de l'autre et doivent être maintenus cohérents si la logique change un jour.
Toutes les entités Portainer portent ce label, qu'une mise à jour soit disponible ou non ; c'est le filtre `state == on`, présent à la fois côté Node-RED et côté Jinja, qui isole celles ayant réellement une mise à jour en attente.
## Comment ajuster les paramètres
| Paramètre | Où le changer |
| ------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
| Jours / heure de déclenchement | Champ crontab du node`triggerWedSun-1300` (syntaxe cron, jours 0-6, 0 = dimanche) |
| Seuil de déclenchement (actuellement 10) | Node`updateContainer>=10`, valeur de la règle `gte` |
| Délai avant le message de suivi (actuellement 10 min) | Node delay entre le switch et`portainerUpdatedAllMsg` |
| Conteneur à inclure/exclure du périmètre | Ajouter/retirer le label`portainer_auto` sur l'entité `update.*` correspondante dans HA |
|---|---|
| Jours / heure de déclenchement | Champ crontab du node `triggerWedSun-1300` (syntaxe cron, jours 0-6, 0 = dimanche) |
| Seuil de déclenchement (actuellement 10) | Node `updateContainer>=10`, valeur de la règle `gte` |
| Délai avant le message de suivi (actuellement 10 min) | Node delay entre le switch et `portainerUpdatedAllMsg` |
| Conteneur à inclure/exclure du périmètre | Ajouter/retirer le label `portainer_auto` sur l'entité `update.*` correspondante dans HA |
## Historique de debug (pour référence future, éviter de refaire les mêmes erreurs)
## Notes techniques (pièges connus)
- `attributes.labels` n'est **pas** le bon champ pour filtrer par label sur le node Get Entities. Utiliser le type de règle dédié "Label Property" (accessible via le bouton `+ add label`).
- Le nom de propriété exact pour compter un tableau dans un node switch est `payload.length` (attention à la faute de frappe `payload.lenght`, invalide silencieusement).
- L'action générique `notify.send_message` ne supporte **pas** le champ `parse_mode`. Il faut utiliser `telegram_bot.send_message`, avec `entity_id` à plat dans `data:` (pas sous `target:`).
- `persistent_notification.create` n'accepte pas `parse_mode` (erreur de validation si présent).
- Pour un message multi-lignes lisible dans un template YAML plié (`>-`), séparer chaque bloc Jinja (`{% %}` / `{{ }}`) par une ligne vide, sinon tout le texte est concaténé sur une seule ligne.
- `label_entities('label')` est la fonction de template HA pour récupérer les entity_id portant un label donné, confirmée sur home-assistant.io/template-functions/label_entities.
- `attributes.labels` n'est pas le bon champ pour filtrer par label sur le node Get Entities. Utiliser le type de règle dédié "Label Property" (bouton `+ add label`).
- Le nom de propriété exact pour compter un tableau dans un node switch est `payload.length`.
- L'action générique `notify.send_message` ne supporte pas le champ `parse_mode`. Utiliser `telegram_bot.send_message`, avec `entity_id` à plat dans `data:` (pas sous `target:`).
- `persistent_notification.create` n'accepte pas `parse_mode`.
- Dans un template YAML plié (`>-`), séparer chaque bloc Jinja (`{% %}` / `{{ }}`) par une ligne vide pour préserver les sauts de ligne du message final.
- `label_entities('label')` est la fonction de template HA pour récupérer les entity_id portant un label donné.
## Point non vérifié dans cette session
## Limites connues
Confiance 90%, pas 100% : le node `containerUpdateAll` n'a pas de propriété `disabled` dans son JSON, donc il est actif. Vérifie visuellement dans Node-RED (bordure pleine, pas pointillée/grisée) avant de considérer que ce README est à jour sur ce point précis, dans le cas où quelque chose aurait changé depuis cet export.
Aucun mécanisme de rollback automatique n'existe si un conteneur ne redémarre pas correctement après `update.install`.
- Aucun mécanisme de rollback automatique si un conteneur ne redémarre pas correctement après `update.install`.
- Le délai de 10 minutes avant le message de suivi est fixe, pas adaptatif ; sur une connexion lente avec beaucoup d'images à tirer, il peut être insuffisant.