2013-01-31 10 views
11

私は2つのLWRPを持っています。最初は、ディスクボリュームの作成、フォーマット、および仮想マシンへのマウントについて説明します。このリソースはcloud_volumeと呼ばれます。 2番目のリソース(それほど重要ではない)は、必要な属性である新しくフォーマットされたボリュームのUUIDが必要です。このリソースはfoobarと呼ばれます。「実行」フェーズまでリソースの属性解決を遅らせる方法はありますか?

リソースcloud_volumeおよびfoobarは、次のようなレシピで使用されます。

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 

シェフを実行すると、Required argument disk_identifier is missing!例外が発生します。私はレシピを2つの段階、コンパイルフェーズと実行フェーズで処理されていることを発見し、いくつかの掘削を行った後

node[:volumes][mount_point][:uuid]が設定されていない時点であるため、コンパイル時に問題が発生しているようです。

通知はすべてこの後、だから、cloud_volume LWRP(それが文書に示されているアンチパターンに陥るでしょう)

に使用されているとして残念ながら、私は、OpsCodeはhereを持っていることのトリックを使用することはできません私の質問は、コンパイル時にdisk_uuidの値がわかっているという要件を回避する方法はありますか?

答えて

15

クリーンな方法はLazy Attribute Evaluationを使用することです。これはコンパイルではなく実行時間中にnode[:volumes][mount_point][:uuid]と評価されます

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

免責事項lazy attribute evaluationを追加する前に、これは古いシェフ(< 11.6.0)と一緒に行く方法です。

foobarリソースをruby_blockにラップし、foobarを動的に定義します。このようにしてコンパイル段階の後、リソースコレクションにルビコードがあり、実行段階で評価されます。

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 

この方法node[:volumes][mount_point][:uuid]は、コンパイル時に知られることはありませんが、それはまた、コンパイル時にアクセスされることはありません。既に設定されている実行ステージでのみアクセスされます。

+0

ああ、まさに私が探しているものです!魅力のように働きました、ありがとうございます:-) – Matt

+0

私はすでにあなたを+1しましたが、怠惰な属性評価が追加されたバージョンを示すのに大変感謝しています。 –