Posted at

ぼくのかんがえたCHEF-3694たいさく

More than 5 years have passed since last update.

chefを使っていて地味に困るのはCHEF-3694、同一リソースを複数回いじったときのこの警告です。

もちろん、同じリソースを何の考えもなしに複数回いじるのは問題がありますが、意図的に複数回いじる必要があることもあります。そんなときには、この警告は邪魔者以外の何物でも無い。

というわけで、自分がやっているCHEF-3694対策についてまとめます


2度目だとわかってて実行するとき

途中までの設定を反映するためにサービス再起動が必要だったりとか、意図的に2回実行したい事があります。こういう時のやりかた。


execute_twice

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回実行しちゃえば問題ない時にやるやり方。


execute_once_without_warning

resources("file[/tmp/gomi]") rescue file "/tmp/gomi" do

action :delete
end

notifiesで指定するとき同様に、あるはずのresourceを指定します。このとき、resources()は指定されたものが見つからないと例外が送出されるので、つまり、みつからなかったらここでresourceを定義すれば良いです。

上記のコードだとすっきりしない、もしくはもうちょっといろいろやりたい場合は、Chef::Exceptions::ResourceNotFoundに対して処理をすればOKです。


begin-rescue

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に切り替える」のような処理分岐も出来るようになります。