Beryl::Apply::Executor
Déroule des recettes déjà ordonnées (cf. Resolver) : pour chaque
recette, chaque step est dispatché vers sa primitive. Les valeurs
string des params sont interpolées ({{ var }}) à partir des
arguments/parameters de la recette.
Idempotence : c'est chaque primitive qui lit l'état réel et décide
skip/apply. En dry_run, rien n'est modifié.
Stop net sur erreur (décision de design) : un step qui échoue
(SSH::CommandFailed) est marqué failed, le déroulé s'arrête, le
rapport partiel est retourné. L'opérateur corrige et relance —
l'idempotence skippe ce qui était déjà OK.
Constants
Option d'étape deferred: true (valable pour TOUTE primitive) : l'étape
n'est pas jouée sur place mais UNE SEULE FOIS en fin d'apply, même si
plusieurs recettes la demandent (dédoublonnage sur primitive + params).
Sert au rechargement de monit : chaque recette qui dépose une sonde le
demandait, et chaque rechargement envoie une alerte « Monit instance
changed » (deux courriels identiques sur le builder, 6 oct. 2026).
Combinable avec if_changed: true (reporté seulement si la recette a
changé quelque chose). Jouée aussi après un échec, pour qu'une sonde déjà
posée soit chargée (sinon if_changed la sauterait au prochain apply).
⚠️ Pas pour nginx : une recette suivante peut avoir besoin de la conf
rechargée tout de suite (défi ACME en webroot).
Option d'étape if_changed: true (valable pour TOUTE primitive) :
l'étape n'est jouée que si une étape PRÉCÉDENTE de la même recette a
modifié quelque chose — l'équivalent des « handlers » d'Ansible. Sert
surtout aux rechargements (service-reload) : recharger nginx ou monit
à chaque apply sans changement est inutile (et, pour monit, chaque
rechargement envoie une alerte « instance changed »).
- file-write: { path: /usr/local/etc/nginx/nginx.conf, content: … }
- service-reload: { name: nginx, if_changed: true }
Options d'étape if_secret: VAR / unless_secret: VAR (valables pour
TOUTE primitive) : l'étape n'est jouée que si la variable du coffre
existe / n'existe pas pour ce serveur (variante VAR__HÔTE d'abord,
cf. Apply.secret). Sert aux variantes d'un même fichier selon ce que
le coffre contient : relais de mail avec ou sans authentification.
- secret-file: { path: …, env: { … }, if_secret: SMTP_RELAY_PASSWORD }
- file-write: { path: …, content: …, unless_secret: SMTP_RELAY_PASSWORD }
Primitives qui POSSÈDENT le fichier qu'elles écrivent (contenu complet).
line-in-file n'en fait pas partie : plusieurs recettes peuvent
légitimement ajouter chacune leur ligne au même fichier.
Option d'étape systems: (valable pour TOUTE primitive) : l'étape n'est
jouée que sur les systèmes listés (freebsd, linux, ou une liste).
Sert aux recettes portables dont UNE étape diffère d'un système à
l'autre (chemin du shell, nom du paquet) ; les autres restent communes.
- user-shell: { user: deploy, shell: /usr/local/bin/zsh, systems: freebsd }
- user-shell: { user: deploy, shell: /usr/bin/zsh, systems: linux }
Constructors
Class methods
Arguments imposés par les requires: en forme map (ex. monappli-base →
nginx-lite: { http_extra: "include monappli/*.conf;" }) : servent de BASE à chaque jeu
d'arguments de la dépendance ; ceux de l'hôte restent prioritaires.
Deux recettes qui imposent des valeurs différentes au même argument →
ConflictingRequiredArgs (aucune ne peut gagner silencieusement).
Raison du saut, ou nil si l'étape doit être jouée.