課題
chef の include_recipe は2度呼んでも1度しか実行してくれない。深遠な理由があってなんとかして2回実行したい。
レシピサンプルはこんなかんじ
recipes/include_recipe.rb
node['log'] = 'foo1'
include_recipe "foo::log"
node['log'] = 'foo2'
include_recipe "foo::log"
recipes/log.rb
log node['log'] do
level :fatal
end
log リソースが1度目の include_recipe でしか実行されない
$ chef-solo -c solo.rb -o foo::include_recipe
Compiling Cookbooks...
Converging 1 resources
Recipe: foo::log
* log[foo1] action write[2015-02-06T04:04:38+09:00] FATAL: foo1
やりかた
libraries として次のような monkey patch を定義する。
libraries/reload_recipe.rb
require 'chef/dsl/include_recipe'
class Chef
module DSL
module IncludeRecipe
def reinclude_recipe(*recipe_names)
recipe_names.each {|recipe_name| run_context.instance_variable_get(:@loaded_recipes).delete(recipe_name) }
run_context.load_recipe(*recipe_names)
end
end
end
end
include_recipe の代わりにここで定義した reinclude_recipe を使えば2度呼べるようになる (本当は ruby にあわせて load という名前にしたかったのだが、すでに使われていたので reinclude にした)
レシピサンプルはこんなかんじ
recipes/reinclude_recipe.rb
node['log'] = 'foo1'
reinclude_recipe "foo::log"
node['log'] = 'foo2'
reinclude_recipe "foo::log"
recipes/log.rb
log node['log'] do
level :fatal
end
2度呼ばれてる
$ chef-solo -c solo.rb -o foo::reinclude_recipe
Compiling Cookbooks...
Converging 2 resources
Recipe: foo::log
* log[foo1] action write[2015-02-06T04:04:10+09:00] FATAL: foo1
* log[foo2] action write[2015-02-06T04:04:10+09:00] FATAL: foo2
おわりに
2回実行したいようなものは、レシピではなく definitions として定義するのが本筋。なので、良い子の皆は真似しないほうが良い。