Kann mir bitte jemand erklären, wie der Koch arbeitet? Das ist eine ziemlich weit gefasste Frage. Um sie einzugrenzen, habe ich dieses sehr einfache Rezept, das eine Liste von Benutzern durchläuft und jedes einzelne erstellt, wenn sie noch nicht vorhanden sind. Es funktioniert nicht.
Soweit ich weiß, scheint die Schleife so zu verlaufen, wie ich es erwarten würde. Sobald die Schleife abgeschlossen ist, werden meine Bash-Befehle zum Erstellen jedes Benutzers einmal für jede Iteration in der Schleife ausgeführt. Wenn die Bash-Befehle ausgeführt werden, scheinen sie jedoch nur den Benutzerwert aus der ersten Schleifeniteration zu haben.
Was ist der richtige Weg, um ein Rezept zu schreiben, das ähnliche Daten wie in diesem Beispiel durchläuft?
Hier ist das Rezept:
node[:users].each do |user|
puts "in loop for #{user['username']}"
bash "create_user" do
user "root"
code do
puts "running 'useradd' for #{user['username']}"
"useradd #{user['username']}"
end
not_if do
puts "checking /etc/passwd for #{user['username']}"
"cat /etc/passwd | grep #{user['username']}"
end
end
end
Ich teste dies mit Vagrant mit dem folgenden Setup:
Vagrant::Config.run do |config|
config.vm.box = "precise32"
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
config.vm.provision :chef_solo do |chef|
chef.add_recipe "sample"
chef.json = {
:users => [
{:username => 'testA'},
{:username => 'testB'},
{:username => 'testC'},
{:username => 'testD'},
{:username => 'testE'},
],
}
end
end
Die Nachrichten, die von den Puts-Anweisungen im Rezept generiert werden, sehen folgendermaßen aus:
2013-03-08T01:03:46+00:00] INFO: Start handlers complete.
in loop for testA
in loop for testB
in loop for testC
in loop for testD
in loop for testE
[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA
[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA
[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA
[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA
[2013-03-08T01:03:46+00:00] INFO: Processing bash[create_user] action run (sample::default line 5)
checking /etc/passwd for testA
[2013-03-08T01:03:46+00:00] INFO: Chef Run complete in 0.026071 seconds
Das Verhalten, das Sie sehen, kann erklärt werden, indem Sie den Unterschied zwischen zwei der wichtigsten Phasen eines Chef-Client-Laufs verstehen: Kompilierung und Konvergenz.
Während der "Kompilierungs" -Phase führt der Chef-Client den Code in Ihren Rezepten aus, um eine Ressourcensammlung zu erstellen . Dies ist eine Liste der Ressourcen , die Chefkoch auf Ihrem System verwalten soll, sowie deren Zielstatus. Beispiel: Eine Verzeichnisressource, die besagt, dass
/tmp/foo
sie vorhanden sein und Eigentum von root sein sollte:Während der "Konvergenz" -Phase verwendet der Chef-Client Anbieter , um den aktuellen Status jeder Ressource zu laden, und vergleicht diesen dann mit dem Zielstatus. Wenn sie unterschiedlich sind, aktualisiert Chef das System. Für unsere Verzeichnisressource würde Chef das Verzeichnis erstellen, wenn es nicht vorhanden wäre, und seinen Besitzer bei Bedarf in "root" ändern.
Ressourcen werden durch ihren Namen und Typ eindeutig identifiziert - unser Verzeichnis wäre
directory[/tmp/foo]
. Seltsame Dinge passieren, wenn Sie zwei Ressourcen mit demselben Namen, aber unterschiedlichen Attributen haben - das erklärt Ihr Problem und kann mithilfe der Antwort von Darrin Holst behoben werden:In diesem speziellen Fall würden Sie jedoch von der Verwendung der Benutzerressource von Chef profitieren. Hier ist ein Ersatz für Ihr Rezept (ohne die Debugging-Meldungen):
Warum ist dies besser als eine Reihe von Bash-Ressourcen?
Der beste Grund, die richtigen Ressourcen zu verwenden, ist jedoch, dass Ihre Absicht klarer kommuniziert wird. Ihr Ziel ist es wahrscheinlich nicht, eine Reihe von Shell-Befehlen auszuführen, sondern sicherzustellen, dass einige Benutzer auf Ihrem System vorhanden sind. Die dazu verwendeten Befehle sind nur ein Implementierungsdetail.
Die Anbieter kapseln diese Details, sodass wir uns darauf konzentrieren können, zu beschreiben, was wir wollen.
quelle