Comment interrompre / terminer un run de chef?

Sous certaines conditions, je dois interrompre / terminer un cycle Chef avec un code d’état différent de zéro, qui se propagera ensuite dans notre chaîne de déploiement et finalement dans Jenkins, ce qui donnera une grosse boule rouge.

Quelle est la meilleure façon de procéder?

Pour les lecteurs qui abordent cette question et qui pourraient ne pas être familiers avec Chef, une exécution de Chef «fait converger» le nœud ou le met en conformité avec la politique déclarée dans la ou les recettes en cours d’exécution. Ceci est aussi appelé “convergence”. Cela comporte deux phases, “comstack” et “execute”. La phase de compilation est lorsque Chef évalue (“comstack”) le code Ruby des recettes, à la recherche de ressources à append à la collection de ressources. Une fois que cela est terminé, il “exécute” les actions pour chaque ressource pour le mettre dans l’état souhaité. Les commandes système sont exécutées, etc.

Erik Hollensbe a écrit un excellent article sur son fonctionnement en 2013 .

Maintenant, pour la réponse:

Il existe plusieurs façons de mettre fin à une exécution de Chef ou de quitter une recette de Chef, selon la manière dont vous souhaitez procéder, car les recettes de Chef sont du code Ruby.

Si votre objective est d’arrêter le traitement d’une recette en fonction d’une condition, mais de poursuivre le rest de l’exécution, utilisez le mot-clé Ruby de return . Par exemple:

 file '/tmp/ponies' do action :create end return if node['platform'] == 'windows' package 'bunnies-and-flowers' do action :install end 

Nous supposons que si le système est Windows, il n’a pas de gestionnaire de paquets capable d’installer le paquet bunnies-and-flowers, donc nous revenons.

Si vous souhaitez abandonner le Chef, exécutez entièrement

Il y a deux autres choses que vous pouvez faire. Chef se ferme s’il rencontre une exception non gérée n’importe où dans l’exécution de Chef. Par exemple, si une ressource de modèle ne trouve pas son fichier source ou si l’utilisateur exécutant Chef n’a pas l’autorisation de créer un répertoire. C’est pourquoi l’utilisation de raise de terminer une parsing.

Où vous posez raise questions. Si vous l’utilisez dans une ressource ruby_block , elle ne sera augmentée que lors de la phase d’exécution dans la convergence. Si vous l’utilisez en dehors d’une ressource comme l’exemple de return ci-dessus, cela se produira pendant la phase de compilation.

 file '/tmp/ponies' do action :create end raise if node['platform'] == 'windows' package 'bunnies-and-flowers' do action :install end 

Nous avons peut-être un gestionnaire de paquets sous Windows, et nous voulons que ce paquet soit installé. La relance entraînera une sortie fatale de Chef et une trace de stack.

Une autre approche consiste à utiliser Chef::Application.fatal! . Cela enregistre un message fatal à l’enregistreur Chef et au STDERR et quitte l’application. Vous pouvez également lui donner un code de retour (peut-être avez-vous un script pour les vérifier?).

 Chef::Application.fatal!("Didn't expect the Spanish Inquistion", 42) if spanish_inquisition 

(bien sûr, spanish_inquisition est généralement nul puisque personne ne s’y attend … je m’écarte …)

Cela entraînera la sortie de Chef, l’envoi du message de journal et le code retour 42 du processus.

Remarque : Cela entraîne la fermeture de l’application entière, ce qui signifie qu’elle s’exécute en tant que service démonisé. Selon le mode de gestion du service, elle peut ou non redémarrer. Par exemple, un service init.d ne redémarrera pas, mais un service runit fera.

Comme les recettes sont Ruby, vous pouvez également gérer les conditions d’erreur avec un bloc begin..rescue .

 begin dater = data_bag_item(:basket, "flowers") rescue Net::HTTPServerException # maybe some retry code here? raise "Couldn't find flowers in the basket, need those to continue!" end 

data_bag_item effectue une requête HTTP pour un sac de données sur le serveur Chef et renvoie une Net::HTTPServerException s’il y a un problème du serveur (404 introuvable, 403 non autorisé, etc.). Nous pourrions essayer de réessayer ou d’effectuer d’autres manutentions, puis de revenir en arrière.

Signaler des erreurs

Il suffit de quitter et de lancer une trace de stack si vous exécutez Chef à partir de la ligne de commande. Toutefois, si vous l’exécutez dans cron ou en tant que démon sur quelques, voire plusieurs dizaines ou centaines de machines, ce n’est pas un bon moyen de garder la santé mentale en cas de problème.

Entrez la fonctionnalité du gestionnaire de rapport / exception du chef . Vous pouvez utiliser un gestionnaire pour vos exécutions de chef. Tous les gestionnaires de rapports sont exécutés à la fin d’un cycle Chef. Les gestionnaires d’exception sont exécutés à la fin d’un cycle Chef interrompu. Le statut de l’exécution est suivi et peut être vérifié dans le gestionnaire. Vous pouvez donc en écrire un qui gère les deux types d’exécution (réussie / terminée ou échouée / abandonnée).

La documentation vous indique comment en écrire un. Il comprend également une liste des gestionnaires open source disponibles que vous pouvez utiliser pour divers services, notamment:

  • E-mail via SMTP
  • IRC
  • Graphite
  • HipChat

Et plusieurs autres.

La méthode recommandée pour annuler ou modifier une exécution Chef consiste à générer une exception. Voici un exemple:

 ruby_block "some sortingcky operation" do block do OperationFoo raise "Operation Foo Failed" if some_condition end end 

Chef :: Application.fatal! devrait faire ce que vous cherchez. Voici un exemple de notre base de code qui pourrait être utile.

 cipher = case key.length when 16 then "AES-128-ECB" when 24 then "AES-192-ECB" when 32 then "AES-256-ECB" else Chef::Application.fatal!("AES Key must be 16, 24, or 32 characters in length but key #{key} has length of #{key.length}") end 

Utilisez simplement la déclaration ci-dessous lorsque vous souhaitez que le chef finisse après une action:

 throw :end_client_run_early 

Il va sortir sans aucune erreur.

Pour faire une sortie impure pendant une exécution en solo, essayez ceci:

 bash 'exit' do code 'killall -9 chef-solo' end