chefを使っていて地味に困るのはCHEF-3694、同一リソースを複数回いじったときのこの警告です。
もちろん、同じリソースを何の考えもなしに複数回いじるのは問題がありますが、意図的に複数回いじる必要があることもあります。そんなときには、この警告は邪魔者以外の何物でも無い。
というわけで、自分がやっているCHEF-3694対策についてまとめます
2度目だとわかってて実行するとき
途中までの設定を反映するためにサービス再起動が必要だったりとか、意図的に2回実行したい事があります。こういう時のやりかた。
service "httpd" do
action :restart
end
# いろいろ処理して…
log "httpd-restart-again" do
level :info
notifies :restart, "service[httpd]", :immediately
# notifies(action, resource, timing=:delayed)
end
chefのresourceからは基本的にnotifiesで別のアクションを呼ぶことが出来ます。なので、無害なアクションからnotifiesで呼べば問題なく実行できます。デフォルトのタイミングは:delayedなので、最後でもよい場合は3つめの引数は省略できますが、その場で実行したい場合は:immediately
をつけます。
過去にやっているか定かではないけど、決まった処理を実行したいとき
主に複数cookbookを実行する場合だと思いますが、apacheのwelcome.confを削除する等、そのリソースに対する処理が決まりきっていて、とにかく1回実行しちゃえば問題ない時にやるやり方。
resources("file[/tmp/gomi]") rescue file "/tmp/gomi" do
action :delete
end
notifiesで指定するとき同様に、あるはずのresourceを指定します。このとき、resources()
は指定されたものが見つからないと例外が送出されるので、つまり、みつからなかったらここでresourceを定義すれば良いです。
上記のコードだとすっきりしない、もしくはもうちょっといろいろやりたい場合は、Chef::Exceptions::ResourceNotFound
に対して処理をすればOKです。
service "rsyslog" do
action :start
end
begin
resources("service[rsyslog]").nil?
Chef::Log::info("rsyslog found")
rescue Chef::Exceptions::ResourceNotFound
Chef::Log::info("rsyslog not found")
end
# output "rsyslog found"
begin
resources("service[no-such-resource]").nil?
Chef::Log::info("no-such-resource found")
rescue Chef::Exceptions::ResourceNotFound
Chef::Log::info("no-such-resource not found")
end
# output "no-such-resource not found"
このやり方だと「xxxを実行済みの場合は、yyyに切り替える」のような処理分岐も出来るようになります。