
Une recette est une liste ordonnée de ressources, écrite dans un DSL Ruby. Le mot « Ruby » intimide, mais vous n'avez besoin que d'une petite partie du langage : des variables, l'interpolation, une condition if, une boucle each. Ce guide montre ce Ruby utile appliqué à des ressources, puis comment découper une recette avec include_recipe. Public visé : débutant ayant compris les ressources Chef. Testé avec CINC Client 19.3.14 et kitchen-dokken sur Ubuntu 24.04.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Écrire une recette lisible comme une liste de ressources ordonnée.
- Utiliser variables, interpolation, condition
ifet boucleeach. - Découper une recette avec
include_recipe. - Éviter ce qui n'a pas sa place dans une recette.
Prérequis
Section intitulée « Prérequis »- Les ressources Chef comprises.
- Un cookbook avec la configuration dokken du guide précédent (
cinc generate cookbook portail, puis lekitchen.ymldokken).
Une recette : des ressources dans l'ordre
Section intitulée « Une recette : des ressources dans l'ordre »Une recette se lit de haut en bas. Chef compile d'abord toute la recette, puis exécute les ressources dans leur ordre d'écriture. L'ordre compte donc : on crée un répertoire avant d'y déposer un fichier, on installe un paquet avant de démarrer son service.
Le Ruby n'est là que pour organiser ces ressources : nommer des valeurs, répéter, choisir. Vous n'écrivez pas un programme, vous décrivez un état avec quelques facilités.
Le Ruby vraiment utile
Section intitulée « Le Ruby vraiment utile »Quatre outils suffisent pour la majorité des recettes.
- Une variable nomme une valeur :
doc_root = "/var/www/html". - L'interpolation insère une variable dans une chaîne :
"#{doc_root}/index.html". - Une condition
ifinclut une ressource selon un cas :if environnement == "prod". - Une boucle
eachrépète une ressource sur une liste :pages.each do |page| ... end.
Mettons-les en œuvre. Cette recette crée une page par entrée d'une liste, et ajoute un robots.txt uniquement en production. Ouvrez recipes/pages.rb :
doc_root = "/var/www/html"environnement = "prod"pages = %w(accueil contact mentions)
pages.each do |page| file "#{doc_root}/#{page}.html" do content "Page #{page}\n" mode "0644" endend
if environnement == "prod" file "#{doc_root}/robots.txt" do content "User-agent: *\nDisallow:\n" mode "0644" endend%w(accueil contact mentions) est un raccourci Ruby pour un tableau de chaînes. La boucle each génère une ressource file par page, avec le nom et le contenu interpolés. Le bloc if n'ajoute la ressource robots.txt que si la condition est vraie.
Découper avec include_recipe
Section intitulée « Découper avec include_recipe »Quand une recette grossit, on la découpe en plusieurs fichiers, rassemblés par include_recipe. Écrivez la recette principale recipes/default.rb qui installe le serveur, prépare le répertoire, puis inclut la recette des pages :
doc_root = "/var/www/html"
package "nginx"
directory doc_root do mode "0755"end
include_recipe "portail::pages"
service "nginx" do action [:enable, :start]endinclude_recipe "portail::pages" insère les ressources de pages.rb à cet endroit précis de l'ordre d'exécution : après le répertoire, avant le service.
Converger
Section intitulée « Converger »Appliquez le tout :
kitchen convergeConverging 7 resourcesRecipe: portail::default * apt_package[nginx] action install - install version 1.24.0-2ubuntu7.13 of package nginx * directory[/var/www/html] action create (up to date)Recipe: portail::pages * file[/var/www/html/accueil.html] action create - create new file /var/www/html/accueil.html * file[/var/www/html/contact.html] action create - create new file /var/www/html/contact.html * file[/var/www/html/mentions.html] action create - create new file /var/www/html/mentions.html * file[/var/www/html/robots.txt] action create - create new file /var/www/html/robots.txtRecipe: portail::default * service[nginx] action enable (up to date) * service[nginx] action start - start service service[nginx]Infra Phase complete, 6/8 resources updated in 03 secondsLa sortie raconte votre code : le bandeau Recipe: portail::pages prouve que include_recipe a bien inséré les pages ; les trois fichiers viennent de la boucle each ; robots.txt vient du if. Le répertoire est déjà là (up to date) car le paquet nginx l'a créé. Relancez kitchen converge : 0/8 resources updated, l'idempotence tient malgré la boucle et la condition.
Ce qu'il ne faut pas mettre dans une recette
Section intitulée « Ce qu'il ne faut pas mettre dans une recette »Le Ruby ouvre la porte à des tentations qu'il faut fuir.
- Pas de commandes système en Ruby (
system(...), backticks) : ce n'est ni idempotent ni portable. Utilisez la ressource adaptée, ouexecuteavec une garde. - Pas de logique lourde : si une recette devient un programme, c'est le signe qu'il faut une ressource personnalisée ou revoir la conception.
- Pas d'appels réseau ou de calculs à la compilation : la phase de compilation doit rester rapide et prévisible.
La règle tient en une phrase : le Ruby organise des ressources, il ne remplace pas les ressources.
Exercice : ajouter une page
Section intitulée « Exercice : ajouter une page »Étendez la liste. Cherchez la solution avant d'ouvrir la réponse.
Ajoutez une page cgv au site, sans écrire une nouvelle ressource file. Puis convergez : une page de plus doit être créée, et un second passage ne change rien.
Indice : tout se joue dans le tableau pages.
On ajoute simplement l'entrée au tableau, la boucle fait le reste :
pages = %w(accueil contact mentions cgv)À la convergence suivante, une seule ressource est mise à jour :
* file[/var/www/html/cgv.html] action create - create new file /var/www/html/cgv.htmlUn second passage affiche 0 ressource mise à jour. Une seule ligne de code a suffi à gérer une page de plus : c'est tout l'intérêt de la boucle each.
À retenir
Section intitulée « À retenir »- Une recette est une liste ordonnée de ressources ; Chef compile puis exécute dans l'ordre d'écriture.
- Le Ruby utile se résume à quatre outils : variables, interpolation,
if,each. include_recipeinsère les ressources d'une autre recette à sa position dans l'ordre.- Une variable locale ne traverse pas les recettes : pour partager, on utilise les attributs de nœud.
- Le Ruby organise des ressources, il ne les remplace pas : pas de
system(), pas de logique lourde.