11

私は2つのLWRPを持っています。1つ目は、ディスクボリュームの作成、フォーマット、および仮想マシンへのマウントを扱います。このリソースをこのリソースと呼びますcloud_volume。2番目のリソース(実際には重要ではありません)には、必須属性である、新しくフォーマットされたボリュームのUUIDが必要です。これをこのリソースと呼びますfoobar

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

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がここに持っているトリックを使用することはできません(したがって、ドキュメントに示されているアンチパターンに分類されます)

だから、このすべての後、私の質問は、disk_uuidコンパイル時にの値がわかっているという要件を回避する方法はありますか?

4

2 に答える 2

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
于 2013-11-20T00:17:35.060 に答える
13

免責事項:これは、遅延属性評価を追加する前に、古いChef(<11.6.0)を使用する方法です。

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

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]はコンパイル時に認識されませんが、コンパイル時にもアクセスされません。すでに設定されているはずの実行段階でのみアクセスされます。

于 2013-01-31T20:41:31.157 に答える