2013-01-12 2 views
50

In determinate condizioni, ho bisogno di interrompere/terminare uno Chef eseguito con un codice di stato diverso da zero, che poi si propagherà attraverso la nostra catena di distribuzione e alla fine a Jenkins risultante in una grossa palla rossa grossa.Come si interrompe/termina una corsa Chef?

Qual è il modo migliore per farlo?

risposta

104

Per i lettori che vengono a questa domanda e risposta in futuro che potrebbe non essere familiarità con lo Chef, una corsa Chef "converge" il nodo, o lo porta in linea con la politica dichiarata in la/e ricetta/e in esecuzione. Questo è anche chiamato "convergenza". Questo ha due fasi, "compilare" ed "eseguire". La fase di compilazione è quando Chef valuta ("compila") il codice Ruby delle ricette, cercando le risorse da aggiungere alla Raccolta risorse. Una volta che è completo, "esegue" le azioni per ogni risorsa per metterlo nello stato desiderato. I comandi di sistema vengono eseguiti, ecc.

Erik Hollensbe ha scritto un eccellente a piedi di how this works in 2013.

Ora, per la risposta:

Ci sono diversi modi per terminare una corsa cuoco, o uscire da una ricetta Chef, a seconda di come si vuole andare a questo proposito, dal momento che le ricette Chef sono codice Ruby.

Se l'obiettivo è interrompere l'elaborazione di una ricetta in base a una condizione, ma continuare con il resto della corsa, utilizzare la parola chiave Ruby return. Per esempio:

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

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

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

Si presume che se il sistema è Windows, esso non ha un gestore di pacchetti in grado di installare il pacchetto coniglietti-e-fiori, così abbiamo tornare.

Se si desidera interrompere l'Chef gestita interamente

Ci sono un paio di altre cose che puoi fare. Lo chef esce se incontra un'eccezione non gestita in qualsiasi punto della corsa dello chef. Ad esempio, se una risorsa modello non riesce a trovare il suo file sorgente o se l'utente che esegue Chef non ha il permesso di fare qualcosa come creare una directory. Questo è il motivo per cui l'uso di raise funziona per terminare una corsa.

Dove si inserisce raise argomenti. Se lo si utilizza in una risorsa ruby_block, si solleverà solo durante la fase di esecuzione in convergenza. Se lo usi al di fuori di una risorsa come l'esempio return, succederà durante la fase di compilazione.

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

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

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

Forse abbiamo un gestore di pacchetti su Windows e vogliamo che questo pacchetto sia installato. Il rilancio porterà lo chef ad uscire fatalmente e a dare una traccia di pila.

Un altro approccio è utilizzare Chef::Application.fatal!. Questo registra un messaggio fatal nel registratore Chef e in STDERR ed esce dall'applicazione. Puoi anche dargli un codice di ritorno (forse hai uno script che controlla quelli?).

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

(ovviamente spanish_inquisition di solito è pari a zero in quanto nessuno si aspetta che ... sto divagando ...)

Ciò determinerà l'uscita di Chef, il messaggio di registro inviato e il codice di ritorno 42 dal processo.

Nota: questo fa uscire l'intera applicazione, ovvero se è in esecuzione come servizio daemonizzato, termina e, a seconda di come viene gestito il servizio, può o non può essere riavviato. Ad esempio, un servizio init.d non verrà riavviato, ma verrà effettuato il servizio runit.

Poiché le ricette sono Ruby, è anche possibile gestire con garbo le condizioni di errore con un blocco 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 effettua una richiesta HTTP per una borsa di dati sul Chef Server e restituirà un Net::HTTPServerException se c'è un problema dal server (404 not found, 403 non autorizzato, ecc). Potremmo tentare di riprovare o eseguire altre operazioni, quindi tornare a raise.

segnalazione di errori

Semplicemente in uscita e lanciare una traccia dello stack va bene se si sta eseguendo Chef dalla riga di comando. Tuttavia, se lo stai eseguendo in cron o come demone su pochi, o addirittura dozzine o centinaia di macchine, questo non è un ottimo modo per mantenere la sanità mentale quando ci sono problemi.

Inserire Chef's report/exception handler feature. Puoi utilizzare un gestore per le tue corse Chef. Tutti i gestori di rapporti vengono eseguiti alla fine di una corsa di Chef. I gestori di eccezioni vengono eseguiti alla fine di una corsa interrotta da Chef. Lo stato della corsa viene tracciato e può essere controllato nel gestore, in modo da poterne scrivere uno che gestisca entrambi i tipi di corsa (completata/completata o non andata a buon fine/interrotta).

Il documentation indica come scriverne uno. Esso include anche un elenco di disponibili open source handlers che è possibile utilizzare per una varietà di servizi, tra cui:

  • -mail tramite SMTP
  • IRC
  • Grafite
  • HipChat

e molti altri .

+2

Risposta stupenda! Molto utile. L'avevo cercato nelle varie risorse dello Chef, ma non l'ho trovato. Se lo avessi, questa domanda non esisterebbe.Recentemente, ho deciso che quando ho cercato la risposta a una domanda e non l'ho trovata su Stackoverflow o facilmente dalle risorse attese, una volta ottenuta una risposta avrei messo insieme una coppia Stackoverflow Domanda e Risposta per catturare ciò che ho imparato . –

+1

Non sono mai stato in grado di ottenere il salvataggio di Net :: HTTPServerException. Non salva l'eccezione. – Zabba

+0

ha adorato il commento dell'inquisizione spagnola :-) – Mamun

7

Il modo consigliato di interrompere o modificare una corsa di Chef è di sollevare un'eccezione. Ecco un esempio:

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

Chef :: Application.fatal! dovrebbe fare ciò che stai cercando. Ecco un esempio dal nostro codice base che potrebbe essere 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 
-3

Per fare un'uscita impuro durante una corsa cuoco-solista, provate questo:

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

Basta usare sotto economico quando si vuole chef finire dopo qualche azione:

throw :end_client_run_early 

Uscirà senza errori.