7.2 KiB
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é.
Objectif
Détecter automatiquement quand un nombre suffisant de conteneurs Portainer ont une image à jour disponible, lancer la mise à jour de tous ces conteneurs d'un coup, et notifier (Telegram + notification persistante HA) avant et après.
Déclenchement
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".
Pipeline Node-RED (onglet pveSystem)
- triggerWedSun-1300 (inject, cron) déclenche tout le pipeline.
- 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_autoSortie : tableau (outputType: array). Testé empiriquement le 27/09/2026 : 13 éléments retournés. Le champoutputResultsCount: 1présent dans la config ne limite pas le résultat, vérifié par ce même test.
- updateContainer>=10 (node switch), propriété
payload.length, règlegte 10. En dessous de 10 mises à jour en attente, rien ne se passe, le pipeline s'arrête ici. - Si le seuil est atteint, trois actions partent en parallèle, pas en séquence :
- containerUpdateAll → appelle le service
update.install, ciblé par labelportainer_auto(tous les conteneurs labellisés d'un coup). C'est l'action qui lance réellement 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).
- containerUpdateAll → appelle le service
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").
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 :
{% for e in label_entities('portainer_auto') if states(e) == 'on' %}
Envoyée en parallèle via :
telegram_bot.send_message(avecparse_mode: plain_textobligatoire, sinon Telegram plante sur les underscores des noms de conteneurs commeathtk_ctr)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.
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).
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.
Comment ajuster les paramètres
| Paramètre | Où le changer |
|---|---|
| Jours / heure de déclenchement | Champ crontab du nodetriggerWedSun-1300 (syntaxe cron, jours 0-6, 0 = dimanche) |
| Seuil de déclenchement (actuellement 10) | NodeupdateContainer>=10, valeur de la règle gte |
| Délai avant le message de suivi (actuellement 10 min) | Node delay entre le switch etportainerUpdatedAllMsg |
| Conteneur à inclure/exclure du périmètre | Ajouter/retirer le labelportainer_auto sur l'entité update.* correspondante dans HA |
Historique de debug (pour référence future, éviter de refaire les mêmes erreurs)
attributes.labelsn'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 frappepayload.lenght, invalide silencieusement). - L'action générique
notify.send_messagene supporte pas le champparse_mode. Il faut utilisertelegram_bot.send_message, avecentity_idà plat dansdata:(pas soustarget:). persistent_notification.createn'accepte pasparse_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.
Point non vérifié dans cette session
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.