Aller au contenu
Infrastructure as Code medium

Recettes et DSL Ruby de Chef

8 min de lecture

logo chef

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.

  • Écrire une recette lisible comme une liste de ressources ordonnée.
  • Utiliser variables, interpolation, condition if et boucle each.
  • Découper une recette avec include_recipe.
  • Éviter ce qui n'a pas sa place dans une recette.
  • Les ressources Chef comprises.
  • Un cookbook avec la configuration dokken du guide précédent (cinc generate cookbook portail, puis le kitchen.yml dokken).

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.

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 if inclut une ressource selon un cas : if environnement == "prod".
  • Une boucle each ré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"
end
end
if environnement == "prod"
file "#{doc_root}/robots.txt" do
content "User-agent: *\nDisallow:\n"
mode "0644"
end
end

%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.

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]
end

include_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.

Appliquez le tout :

Fenêtre de terminal
kitchen converge
Converging 7 resources
Recipe: 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.txt
Recipe: 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 seconds

La 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.

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, ou execute avec 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.

É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.

  • 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_recipe insè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.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn