Skip to main content

Fonctionnement avancés de l'éditeur de packages.

Fonctionnement avancés de l'éditeur de packages

Un package Medulla est une liste d'étapes exécutées dans l'ordre sur les machines cibles. Au-delà de ce déroulé linéaire, Medulla offre plusieurs mécanismes pour piloter dynamiquement un déploiement : réagir au résultat de chaque étape, rediriger l'exécution, réutiliser les fichiers d'un autre package, et enchaîner conditionnellement plusieurs packages.

Cette documentation s'adresse à l'ensemble des utilisateurs de Medulla. Elle regroupe ces mécanismes en un seul document, organisé pour une progression du plus local (une étape) au plus global (plusieurs packages) :

  • le chapitre 2 montre comment faire dépendre le déroulement d'un package du résultat de ses étapes, et comment sauter d'une étape à l'autre ;
  • le chapitre 3 explique comment réutiliser, dans un package, les fichiers d'un autre package déjà déployé ;
  • le chapitre 4 décrit comment déclencher automatiquement un package en fonction de l'état ou du résultat d'un autre ;
  • l'annexe en fin de document récapitule les variables Meta utilisables dans les étapes.

1. Vue d'ensemble : ce que permet chaque mécanisme

Vous voulez…Utilisez…
Sauter vers une étape **selon le code de retour** (sans pause)Règle « Ajouter aller à » dans les Options d'une étape (`==`, `!=`, `IN`, `OUT`, …)
Marquer une **pause** puis sauter vers une étape (sans condition)Action « Attendre et aller à l'étape » (délai en secondes + saut)
Nommer une étape pour pouvoir y sauterLibellé (« Step label ») de l'étape
Terminer proprement selon le casActions « Fin avec succès » / « Fin avec erreur »
Réutiliser les fichiers d'un autre packageOption « Package alternatif »
Déclencher un package selon l'état/le résultat d'un autreMarqueur + groupe dynamique ciblé par le second déploiement

2. Codes de retour, libellés et sauts « Goto »

Ce chapitre explique comment faire dépendre le déroulement d'un package du résultat de ses étapes, et comment rediriger l'exécution vers une étape précise au lieu d'un déroulé purement linéaire.

Prérequis : savoir construire un package dans l'éditeur (voir « L'éditeur de Package — comment cela fonctionne »).

Comment s'exécute un package

Un package est une séquence d'étapes numérotées, exécutées dans l'ordre, de la première à la dernière. Chaque étape produit en fin d'exécution :

  • une sortie textuelle (ce que la commande ou le script a écrit) ;
  • un code de retour numérique (l'« exit code » : 0 = succès par convention, toute autre valeur ayant une signification propre à l'outil appelé).

Ces deux informations sont réutilisables par l'étape suivante via les variables Meta @@@PREC_RESULT@@@ (sortie textuelle) et @@@PREC_RETURNCODE@@@ (code de retour) — voir l'annexe en fin de document pour la liste complète des variables Meta.

Le libellé (label) : nommer une étape pour pouvoir y sauter

Chaque étape possède un libellé unique (label). Ce libellé est le point d'ancrage qui permet à une autre étape de pointer vers elle : tant qu'une étape porte un libellé, n'importe quelle autre étape du package peut demander « aller à ce libellé » au lieu de continuer linéairement.

![L'éditeur d'étapes : la palette « Actions disponible » (à gauche) et le « Flux de déploiement » (à droite), avec la Section d'installation, une étape « Exécuter le script », puis « Fin avec succès » et « Fin avec erreur ».]01-plan-de-deploiement.png

Le champ Libellé (« Step label ») et les règles de saut se configurent dans les Options d'une étape :

![Les Options d'une étape « Exécuter le script » : le champ « Step label » (libellé), l'option « Package alternatif », et une règle « Sur code retour, aller à » (Return Code !=0 → Goto Label END_ERROR).][!(https://docs.medulla-tech.io/uploads/images/gallery/2026-09/scaled-1680-/VS1UIGZ2vddi2koc-01-plan-de-deploiement.png)]

Il n'existe pas d'étape isolée qui ne ferait que « Goto Label ». Il faut bien distinguer deux mécanismes de saut différents, qui n'ont pas le même rôle :

1. L'action « Attendre et aller à l'étape » — c'est une étape à part entière, que l'on glisse depuis la palette. Elle attend un délai (champ « Attendre pendant (secondes) », 10 s par défaut) puis saute vers une étape cible (champ goto), sans condition. C'est le seul mécanisme qui introduit une pause. Utile, par exemple, pour laisser un service démarrer avant de poursuivre. ![L'action « Attendre et aller à l'étape » : le champ « Attendre pendant (secondes) » (10 par défaut) et le champ goto (ici « END_SUCCESS »).](01ter-attendre-et-aller-a.png)

2. Le bouton « Ajouter aller à », dans les Options d'une étape — il ajoute une règle de saut conditionnel sur code de retour (« Return Code → Goto Label », cf. capture ci-dessus). Le saut ne se déclenche que si le code de retour satisfait la condition ; il n'y a aucune pause. C'est le mécanisme utilisé pour brancher selon le résultat d'une étape (voir la section suivante).

Autrement dit, le comportement « Goto Label » existe bien, mais toujours rattaché à une étape : soit l'étape dédiée « Attendre et aller à l'étape » (pause + saut), soit une règle de saut conditionnel ajoutée aux Options d'une étape (sans pause). Il n'y a pas de « type Goto Label » isolé.

Réagir à un code de retour

Le principe

Convention : un code de retour 0 = succès. Tout code différent de 0 = erreur.

C'est la convention à suivre pour concevoir vos packages. Attention toutefois à la façon dont le moteur l'applique concrètement :

  • une étape qui renvoie 0 sans règle particulière est considérée comme réussie et le déroulé continue à l'étape suivante ;
  • une étape qui renvoie un code différent de 0 n'est pas automatiquement redirigée en erreur : s'il n'y a aucune règle couvrant ce code, le moteur passe simplement à l'étape suivante (souvent « Fin avec succès ») — et le déploiement peut alors être marqué en succès alors que l'étape a échoué.

⚠️ À retenir : pour qu'un code d'échec termine réellement le package en erreur, il faut le déclarer explicitement avec une règle !=0END_ERROR. Ne comptez pas sur une mise en erreur automatique.

Traiter les cas avec des règles

Les règles de code de retour servent à la fois à appliquer la convention (==0END_SUCCESS, !=0END_ERROR) et à traiter les exceptions (considérer un code pourtant ≠ 0 comme un succès, par ex. 3010, ou rediriger vers une étape précise). Chaque règle associe une condition (opérateur + valeur) à une action (aller à un libellé, END_SUCCESS, ou END_ERROR). Les règles sont évaluées dans l'ordre, et la première qui correspond l'emporte.

Opérateurs disponibles :

OpérateurSignification
`==1`Code de retour exactement égal à 1
`!=1` ou `<>1`Code de retour différent de 1
`<1` / `>1` / `<=1` / `>=1`Comparaisons numériques
`IN1,5`Code de retour compris dans l'intervalle `[1;5]`
`OUT1,5`Code de retour hors de l'intervalle `[1;5]`

Bonne pratique : sur toute étape dont le résultat compte, déclarez au moins les deux règles ==0END_SUCCESS et !=0END_ERROR (plus vos codes particuliers, comme ==3010). C'est le seul moyen fiable de garantir qu'un succès soit un succès et qu'un échec soit un échec.

Exemple 1 — Un installeur qui demande un redémarrage

Beaucoup d'installeurs MSI renvoient le code 3010 pour signifier « installation réussie, un redémarrage est nécessaire ». Par défaut, ce code ≠ 0 serait considéré comme un échec. On le traite ainsi :

Les libellés END_SUCCESS et END_ERROR sont ceux, réservés, des étapes « Fin avec succès » et « Fin avec erreur » : on y saute directement, il n'y a pas à créer de libellés de fin personnalisés.

Étape 1  [libellé: install]   Exécuter une commande : setup.exe /qn
           Règle : ==3010  → aller à [reboot]
           Règle : ==0     → aller à END_SUCCESS
           Règle : !=0     → aller à END_ERROR

Étape 2  [libellé: reboot]    Redémarrer la machine
                              (puis enchaîne naturellement sur END_SUCCESS)

Étape 3  Fin avec succès      (libellé END_SUCCESS, inventaire forcé)

Étape 4  Fin avec erreur      (libellé END_ERROR)

Résultat : le code 3010 n'est plus vu comme un échec, la machine redémarre proprement, et le déploiement est marqué en succès.

Exemple 2 — Réessayer puis basculer sur une méthode alternative

Cas typique : on tente une installation « propre », et en cas d'échec on bascule vers une méthode de secours avant d'abandonner.

Étape 1  [libellé: tentative1]  Exécuter un script : installation standard
           Règle : ==0   → aller à END_SUCCESS
           Règle : !=0   → aller à [tentative2]

Étape 2  [libellé: tentative2]  Exécuter un script : installation de secours (mode forcé)
           Règle : ==0   → aller à END_SUCCESS
           Règle : !=0   → aller à [echec]

Étape 3  Fin avec succès        (libellé END_SUCCESS)

Étape 4  [libellé: echec]       Ajouter au journal : "Les deux méthodes ont échoué (code @@@PREC_RETURNCODE@@@)"
                                (puis enchaîne sur END_ERROR)

Étape 5  Fin avec erreur        (libellé END_ERROR)

Attention aux boucles : un saut vers une étape antérieure (par exemple pour réessayer) peut créer une boucle infinie si la condition de sortie n'est jamais atteinte. Prévoyez toujours un compteur (via une variable d'environnement incrémentée) ou une condition de sortie stricte.

Sections d'un package : installation, mise à jour, désinstallation

Un même package peut contenir jusqu'à trois modes d'exécution :

  • Installation — la section par défaut ;
  • Mise à jour — déclenchée par les convergences négatives ;
  • Désinstallation — forcée via un paramètre dynamique JSON, par exemple {"section": "uninstall"}.

Les sauts et codes de retour fonctionnent à l'intérieur de chaque section. La valeur d'un paramètre dynamique passé au déploiement est lisible dans les étapes via @@@DYNAMIC_PARAM@@@section@@@, ce qui permet d'adapter le comportement au mode demandé.

3. L'option « Package alternatif »

Ce chapitre explique comment un package peut réutiliser les fichiers d'un autre package déjà déployé sur la machine, grâce à l'option « Package alternatif ».

Ce que fait l'option

Par défaut, une action (commande, script, extraction, téléchargement) travaille dans le dossier local du package en cours sur le poste client. L'option « Package alternatif » apparaît sous forme d'une case à cocher dans les Options de ces actions : une fois cochée, l'action ne travaille plus dans le dossier du package en cours mais depuis le dossier d'un autre package déjà déployé sur la machine, sélectionné dans la liste déroulante juste à côté.

Concrètement, cela permet à un package « léger » d'aller piocher des fichiers déposés par un package « lourd » — sans avoir à re-télécharger ces fichiers.

Les actions qui supportent ce paramètre optionnel :

ActionEffet avec « Package alternatif »
**Exécuter une commande**La commande s'exécute depuis le dossier de l'autre package
**Exécuter un script**Le script s'exécute depuis le dossier de l'autre package
**Dézipper un fichier**L'archive est extraite dans/depuis le dossier de l'autre package
**Télécharger un fichier**Le fichier est déposé dans le dossier de l'autre package

Ce que l'option ne fait PAS : elle ne « lance » pas l'autre package et n'exécute pas ses étapes. Elle donne uniquement accès à son dossier de fichiers. Pour déclencher réellement l'exécution d'un autre package, voir le chapitre 4 — Groupes dynamiques et enchaînement conditionnel de packages.

![Dans les Options d'une action « Exécuter la commande », la case « Package alternatif » cochée et la liste déroulante permettant de choisir le package cible (ici « notepad++ »).]02-package-alternatifBIS.png

Prérequis

Pour qu'un package alternatif soit utilisable sur la machine cible :

  1. Il doit déjà avoir été déployé sur ce poste client (son dossier local doit exister) ;
  2. Son contenu ne doit pas avoir été supprimé. En particulier, si le package source contient une étape « Supprimer les fichiers transférés » ou une « Fin avec succès » configurée pour nettoyer le package, son dossier n'existera plus.

Bonnes pratiques :

  • Le package « bibliothèque » (celui dont on réutilise les fichiers) ne doit pas se nettoyer : ne pas y placer d'étape « Supprimer les fichiers transférés », et configurer sa « Fin avec succès » sans suppression du package.
  • Garantir l'ordre de déploiement : le package bibliothèque doit être arrivé sur la machine avant le package qui le consomme. Voir le chapitre 4 — Groupes dynamiques et enchaînement conditionnel de packages pour automatiser cet enchaînement.

Comportement si le package alternatif est absent

Si le package alternatif est introuvable (jamais déployé, ou dossier nettoyé), l'étape n'échoue pas et ne renvoie pas de code d'erreur dédié : un simple avertissement est journalisé (« Requested package directory missing »), puis l'exécution se poursuit dans le répertoire courant et passe à l'étape suivante. C'est alors l'action qui utilise ces fichiers (commande, script…) qui renvoie un code d'échec, car elle s'exécute au mauvais endroit.

Mais attention : ce code d'échec ne suffit pas à faire échouer le déploiement. Comme expliqué au chapitre 2 — Codes de retour, libellés et sauts « Goto », sans règle de code de retour explicite, un code ≠ 0 non traité fait simplement passer à l'étape suivante (« Fin avec succès ») : le déploiement peut donc se terminer en succès alors que la bibliothèque manquait.

Extrait de journal typique d'un package alternatif absent, sans règle de code retour (le déploiement finit en succès à tort) :

Warning : Requested package directory missing!!!: <uuid du package>
[GoTo] Received return code: 1
[GoTo] Attempting jump to next step.
Branching to next step 1        ← passe à « Fin avec succès »

Recommandation : sur l'action qui consomme le package alternatif, déclarez toujours une règle !=0END_ERROR (et ==0END_SUCCESS). Ainsi, si la bibliothèque est absente, l'échec de la commande est bien remonté en erreur. Pour un contrôle encore plus explicite, vous pouvez tester la présence du dossier dans une étape « Exécuter un script » avant de le consommer.

Exemple — Une charge utile partagée

Situation : un runtime volumineux (2 Go) doit être disponible pour trois applications métier différentes. Plutôt que de l'embarquer trois fois :

Package "Runtime-Commun"   (déployé une seule fois, ne se nettoie pas)
   └── contient les 2 Go de fichiers du runtime

Package "AppA"  →  Exécuter une commande : install_appA.exe
                   [Package alternatif : Runtime-Commun]
                   (l'installeur trouve le runtime dans le dossier de Runtime-Commun)

Package "AppB"  →  idem, package alternatif : Runtime-Commun
Package "AppC"  →  idem, package alternatif : Runtime-Commun

Gain : les 2 Go ne transitent qu'une fois sur le réseau, et les trois packages applicatifs restent légers.

4. Groupes dynamiques et enchaînement conditionnel de packages

Ce chapitre explique comment déclencher automatiquement un package en fonction de l'état ou du résultat d'un autre, à l'aide des groupes dynamiques et de la convergence de déploiement.

Le principe : on ne « chaîne » pas les packages, on pilote leur cible

Medulla ne propose pas d'instruction « à la fin de ce package, lance cet autre package ». L'enchaînement conditionnel se construit autrement :

On fait entrer (ou sortir) une machine d'un groupe dynamique en fonction de son état, et un déploiement est configuré pour cibler ce groupe. Quand la machine rejoint le groupe, le package s'y déploie automatiquement.

Le résultat perçu est identique à un « appel conditionnel d'un package depuis un autre », mais le mécanisme est déclaratif (basé sur l'état de la machine) plutôt qu'impératif. C'est plus robuste : si une machine était éteinte au moment du premier package, elle est prise en compte dès qu'elle réunit les conditions.

Le maillon clé : refléter le résultat d'un package dans l'inventaire

Pour qu'un package B se déclenche « à la suite » d'un package A, il faut que le résultat du package A soit visible dans l'inventaire, afin qu'un groupe dynamique puisse le détecter. Deux approches :

  1. S'appuyer sur l'effet réel du package A. Le package A installe le logiciel X ; le groupe dynamique « machines où X est installé » se peuple naturellement après la prochaine remontée d'inventaire. C'est le cas le plus simple et le plus fiable.

    • Astuce : une « Fin avec succès » peut forcer un inventaire en fin de package A, pour que l'état soit remonté immédiatement.
  2. Poser un marqueur explicite — la clé de registre (méthode recommandée sous Windows). Le module de groupes dynamiques expose nativement les critères « Register key » et « Register key value ». Le package A écrit une clé de registre dans sa branche de succès, et le groupe dynamique cible « Register key value = <votre valeur> ».

    • Prérequis : pour qu'une clé de registre remonte dans l'inventaire (et devienne exploitable comme critère), elle doit faire partie du périmètre de collecte registre de l'inventaire (règles de collecte FusionInventory/GLPI). Ajoutez la clé à collecter dans la configuration d'inventaire, sinon le critère restera vide.
    • Autres marqueurs utilisables comme critères sans configuration spécifique : la présence d'un logiciel installé ou d'une version de logiciel, ou l'appartenance à une entité / un groupe.

![Les critères « Register key » et « Register key value » exposés par le module glpi : ils permettent de cibler une clé de registre déposée par un package comme marqueur.]

Rendre l'appel conditionnel

La condition se code entièrement dans le marqueur et dans les critères du groupe :

  • Conditionner au succès : le marqueur n'est posé qu'en cas de succès (dans la branche END_SUCCESS). Une machine en échec ne pose pas le marqueur, n'entre pas dans le groupe, et ne reçoit donc pas le package B.
  • Conditionner à un code de retour précis : posez un marqueur différent selon la branche de code de retour empruntée (par exemple resultat=reboot_requis vs resultat=ok), et créez un groupe dynamique par valeur de marqueur.
  • Exclure les machines déjà traitées : ajoutez au groupe le critère « package B non encore installé », pour éviter les redéploiements.

Exemple — Déployer l'agent de supervision uniquement après une installation réussie

Objectif : n'installer l'agent de supervision (package B) que sur les machines où l'application métier (package A) s'est installée avec succès.

1. Package A "Install-AppMetier"
      … étapes d'installation …
      Branche END_SUCCESS :
          Poser un marqueur : écrire la clé de registre  HKLM\Software\MonOrga\AppMetier = OK
          Fin avec succès (inventaire forcé)
      Branche END_ERROR :
          (aucun marqueur posé)
          Fin avec erreur

2. Groupe dynamique "AppMetier-OK-sans-superviseur"
      Critère 1 : clé de registre HKLM\Software\MonOrga\AppMetier = OK
      Critère 2 : agent de supervision NON installé

3. Package B "Install-Superviseur"
      Déploiement configuré pour cibler le groupe "AppMetier-OK-sans-superviseur"
      → toute machine qui rejoint le groupe reçoit automatiquement le package B

Déroulé : une machine où A réussit pose le marqueur → à la remontée d'inventaire, elle entre dans le groupe → le package B s'y déploie automatiquement. Une machine où A échoue ne pose pas le marqueur, reste hors du groupe, et ne reçoit jamais B. Une fois B installé, le critère 2 n'est plus satisfait : la machine sort du groupe, ce qui évite tout redéploiement.

Combiner avec le « Package alternatif »

Le déclenchement conditionnel et la réutilisation de fichiers se complètent pour les dépendances :

  • Utilisez un groupe dynamique pour garantir que le package « bibliothèque » est déployé avant le package qui le consomme (critère : « bibliothèque présente »).
  • Une fois la bibliothèque en place, le package consommateur utilise l'option « Package alternatif » (chapitre 3) pour accéder à ses fichiers.

Vous obtenez ainsi une chaîne complète : déploiement ordonné (groupes dynamiques) + réutilisation de fichiers (package alternatif) + branchement selon résultat (codes de retour et sauts, chapitre 2).

Annexe — Variables Meta

Les variables Meta sont encadrées par @@@ et remplacées au moment de l'exécution sur la machine. Elles sont utilisables dans les commandes, scripts et paramètres des étapes.

VariableContenu
`@@@PREC_RESULT@@@`Sortie textuelle de l'étape précédente
`@@@PREC_RETURNCODE@@@`Code de retour de l'étape précédente
`@@@DYNAMIC_PARAM@@@section@@@`Valeur d'un paramètre dynamique du déploiement (ex. la section)
`@@@PACKAGE_NAME@@@`Nom du package
`@@@UUID_PACKAGE@@@`Identifiant unique du package
`@@@HOSTNAME@@@` / `@@@IP_MACHINE@@@` / `@@@OS_FAMILY@@@`Métadonnées de la machine cible