¿Cómo abortar/terminar una carrera de Chef?


Bajo ciertas condiciones, necesito abortar/terminar una carrera de Chef con un código de estado distinto de cero, que luego se propagará de nuevo a través de nuestra cadena de implementación y, finalmente, a Jenkins, lo que resultará en una gran bola roja.

¿Cuál es la mejor manera de hacer esto?

Author: Jordan Dea-Mattson, 2013-01-12

5 answers

Para los lectores que vienen a esta pregunta y respuesta en el futuro que pueden no estar familiarizados con Chef, una carrera de Chef "converge" el nodo, o lo alinea con la política declarada en la(s) receta (s) que está ejecutando. Esto también se llama " convergencia."Esto tiene dos fases, "compilar" y "ejecutar."La fase de compilación es cuando Chef evalúa ("compila") el código Ruby de las recetas, buscando recursos para agregar a la Colección de Recursos. Una vez que se completa, "ejecuta" las acciones para cada recursos para ponerlo en el estado deseado. Se ejecutan comandos del sistema, etc.

Erik Hollensbe escribió un excelente recorrido por cómo funciona esto en 2013 .

Ahora, para la respuesta:

Hay varias maneras de terminar una carrera de Chef, o salir de una receta de Chef, dependiendo de cómo quieras hacerlo, ya que las recetas de Chef son código Ruby.

Si su objetivo es dejar de procesar una receta basada en una condición, pero continuar con el resto de la ejecutar, a continuación, utilice la palabra clave Ruby return. Por ejemplo:

file '/tmp/ponies' do
  action :create
end

return if node['platform'] == 'windows'

package 'bunnies-and-flowers' do
  action :install
end

Suponemos que si el sistema es Windows, no tiene un gestor de paquetes que pueda instalar el paquete bunnies-and-flowers, así que volvemos.

Si desea abortar el Chef ejecutar por completo

Hay un par de otras cosas que puedes hacer. Chef sale si encuentra una excepción no controlada en cualquier parte de la carrera de Chef. Por ejemplo, si un recurso de plantilla no puede encontrar su archivo de origen, o si el usuario running Chef no tiene permiso para hacer algo como crear un directorio. Esta es la razón por la que usar raise funciona para finalizar una ejecución.

Donde pones raise importa. Si lo usa en un recurso ruby_block, solo se generará durante la fase de ejecución en convergence. Si lo usa fuera de un recurso como el ejemplo return anterior, ocurrirá durante la fase de compilación.

file '/tmp/ponies' do
  action :create
end

raise if node['platform'] == 'windows'

package 'bunnies-and-flowers' do
  action :install
end

Quizás tengamos un gestor de paquetes en Windows, y queremos que este paquete esté instalado. El aumento resultará en Chef fatalmente saliendo y dando un rastro de pila.

Otro enfoque es usar Chef::Application.fatal!. Esto registra un mensaje fatal al Chef logger y STDERR, y sale de la aplicación. También puede darle un código de retorno (tal vez usted tiene un script que comprueba los?).

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

(por supuesto spanish_inquisition suele ser nulo ya que nadie lo espera... Estoy divagando...)

Esto resultará en la salida de Chef, el mensaje de registro enviado y el código de retorno 42 del proceso.

Nota: Esto hace que toda la aplicación salga, lo que significa que si se está ejecutando como un servicio demonizado, terminará y, dependiendo de cómo se administre el servicio, puede o no comenzar de nuevo. Por ejemplo, un servicio init.d no se reiniciará, pero un servicio runit sí.

Dado que las recetas son Ruby, también puede manejar con gracia las condiciones de error con un bloque 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 realiza una solicitud HTTP para una bolsa de datos en el servidor Chef, y devolverá un Net::HTTPServerException si hay un problema desde el servidor (404 no encontrado, 403 no autorizado, etc). Posiblemente podríamos intentar reintentar o hacer algún otro manejo, y luego volver a raise.

Reportar errores

Simplemente salir y lanzar un seguimiento de pila está bien si está ejecutando Chef desde la línea de comandos. Sin embargo, si lo está ejecutando en cron o como un demonio en unas pocas, o incluso docenas o cientos de máquinas, esta no es una gran manera de mantener la cordura cuando hay problemas.

Enter Chef's función de manejador de informes/excepciones . Puede usar un controlador para sus carreras de chef. Todos los manejadores de informes se ejecutan al final de una carrera de chef. Los manejadores de excepciones se ejecutan al final de una ejecución de Chef abortada. El estado de la ejecución se realiza un seguimiento, y se puede comprobar en el controlador, por lo que puede escribir uno que maneja ambos tipos de ejecución (exitosa/completada o fallida/abortada).

La documentación te dice cómo escribir una. También incluye una lista de código abierto disponibles manejadores que puede usar para una variedad de servicios, incluyendo:

  • Correo electrónico a través de SMTP
  • IRC
  • Grafito
  • HipChat

Y varios más.

 106
Author: jtimberman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-28 19:28:29

La forma recomendada de abortar o editar una ejecución de Chef es generar una excepción. He aquí un ejemplo:

ruby_block "some tricky operation" do
  block do
    OperationFoo
    raise "Operation Foo Failed" if some_condition
  end
end
 7
Author: Jordan Dea-Mattson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-13 01:02:32

Chef:: Aplicación.fatal! debería hacer lo que buscas. Aquí hay un ejemplo de nuestra base de código que podría ser útil.

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
 5
Author: John T Dyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-02 20:35:18

Simplemente use la siguiente declaración cuando desee chef terminar después de alguna acción:

throw :end_client_run_early

Saldrá sin ningún error.

 -1
Author: Shivendra Sharma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-19 11:38:34

Para hacer una salida impura durante una carrera de chef en solitario, intente esto:

bash 'exit' do
    code 'killall -9 chef-solo'
end
 -3
Author: dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-08 16:25:40