2013-01-31 5 views
11

Ich habe zwei LWRPs. Die erste befasst sich mit dem Erstellen eines Datenträgervolumes, dem Formatieren und dem Mounten auf einer virtuellen Maschine. Wir nennen diese Ressource cloud_volume. Die zweite Ressource (nicht wirklich wichtig, was sie tut) benötigt eine UUID für das neu formatierte Volume, was ein erforderliches Attribut ist, wir nennen diese Ressource foobar. Die Ressourcen cloud_volume und foobar werden in einem Rezept wie folgt verwendet. SoGibt es eine Möglichkeit, die Attributauflösung einer Ressource bis zur "Ausführen" -Phase zu verzögern?

volumes.each do |mount_point, volume| 
    cloud_volume "#{mount_point}" do 
    size volume['size'] 
    label volume['label'] 
    action [:create, :initialize] 
    end 
    foobar "#{mount_point}" do 
    disk_uuid node[:volumes][mount_point][:uuid] # This is set by cloud_volume 
    action [:do_stuff] 
    end 
end 

, wenn ich einen Koch laufen bekomme ich eine Required argument disk_identifier is missing! Ausnahme.

Nach einigen Graben entdeckte ich, dass Rezepte in zwei Phasen verarbeitet werden, eine Kompilierungsphase und eine Ausführungsphase. Es sieht so aus, als wäre das Problem zur Kompilierzeit, da node[:volumes][mount_point][:uuid] nicht gesetzt ist.

Leider kann ich nicht den Trick verwenden, die Opscode hat here als Benachrichtigungen wird in der cloud_volume LWRP verwendet wird (so würde es in das anti-Muster in der Dokumentation gezeigt fallen)

So, nach all dies, meine Frage ist, gibt es eine Möglichkeit, um die Anforderung, dass der Wert disk_uuid zur Kompilierzeit bekannt sein?

Antwort

15

Ein sauberer Weg wäre Lazy Attribute Evaluation zu verwenden. Dies wird node[:volumes][mount_point][:uuid] während der Ausführungszeit auswerten statt

foobar "#{mount_point}" do 
    disk_uuid lazy { node[:volumes][mount_point][:uuid] } 
    action [:do_stuff] 
end 
13

Haftungsausschluss: Das ist die Art und Weise mit älterem Chef zu gehen (< 11.6.0), bevor sie lazy attribute evaluation hinzugefügt.

Wickeln Sie Ihre foobar-Ressource in ruby_block und definieren Sie foobar dynamisch. Auf diese Weise erhalten Sie nach der Kompilierung einen Ruby-Code in der Ressourcen-Sammlung und dieser wird in der Run-Phase ausgewertet.

ruby_block "mount #{mount_point} using foobar" do 
    block do 
    res = Chef::Resource::Foobar.new(mount_point, run_context) 
    res.disk_uuid node[:volumes][mount_point][:uuid] 
    res.run_action :do_stuff 
    end 
end 

Auf diese Weise node[:volumes][mount_point][:uuid] wird nicht zum Zeitpunkt der Kompilierung bekannt sein, aber es wird auch nicht bei der Kompilierung zugegriffen werden. Es wird nur im laufenden Stadium aufgerufen, wenn es bereits eingestellt sein sollte.

+0

Ahhh kompilieren, das ist genau das, was ich suche! Arbeitete wie ein Zauber, danke :-) – Matt

+0

Ich habe dir schon +1 gegeben, aber danke, dass du die Version angegeben hast, in der faule Attributbewertung hinzugefügt wurde. –