I am developing a cookbook to deploy a simple jekyll based blog. I use 'application' cookbook as a base. Everything works smoothly except chef simply ignores my defined callbacks.
Chef log contains entries about my callback, but I see no errors or outcomes of the callback execution.
Here is recipes/default.rb file:
include_recipe "git"
application "example_com" do
path "/var/www/example.com"
repository "[email protected]:xxx/xxx.git"
revision "master"
deploy_key <<EOF
-----BEGIN RSA PRIVATE KEY-----
..skip...
-----END RSA PRIVATE KEY-----
EOF
# before_symlink "script/bootstrap"
before_deploy do
# raise
# Chef::Log.info("INSANE!")
execute "bundle exec rake generate" do
cwd release_path
end
end
end
Here is the log where chef-client says it executes before_deploy callback:
[2012-10-06T10:06:20-04:00] INFO: Processing ruby_block[example_com before_deploy] action create (/var/cache/chef/cookbooks/application/providers/default.rb line 107)
[2012-10-06T10:06:20-04:00] DEBUG: Got callback before_deploy: #<Proc:0x00007f0509788088@/var/cache/chef/cookbooks/example_com/recipes/default.rb:24>
[2012-10-06T10:06:20-04:00] INFO: application[example_com] running callback before_deploy
[2012-10-06T10:06:20-04:00] INFO: ruby_block[example_com before_deploy] called
[2012-10-06T10:06:20-04:00] INFO: Processing deploy_revision[example_com] action deploy (/var/cache/chef/cookbooks/application/providers/default.rb line 122)
I also tried to define callback using string, but the result is the same. Chef shows error when there is no file with callback definition and simply ignores the file if it is in the right place.
Update 1
After digging deeper inside Chef sources I realized that callbacks are executed in separate chef runner and this happens not instantly. When code in application cookbook calls _recipe_eval_ to evaluate callback body Chef creates separate runner and the code does not executed until something call converge method.
So, I modified application cookbook a bit. I added call converge just after _recipe_eval_ and everything started to work.
I think this is a bug and I am going to create an issue in official Opscode tracker. However, any comments are very welcome!
Here is modifed version of application/libraries/default.rb:
class Chef
class Provider
module ApplicationBase
# ...skip...
def callback(what, callback_code=nil)
Chef::Log.debug("Got callback #{what}: #{callback_code.inspect}")
@collection = Chef::ResourceCollection.new
case callback_code
when Proc
Chef::Log.info "#{@new_resource} running callback #{what}"
# recipe_eval(&callback_code)
recipe_eval(&callback_code)
converge # <--- Remove this line and no callbacks will work.
when String
callback_file = "#{release_path}/#{callback_code}"
unless ::File.exist?(callback_file)
raise RuntimeError, "Can't find your callback file #{callback_file}"
end
run_callback_from_file(callback_file)
when nil
nil
else
raise RuntimeError, "You gave me a callback I don't know what to do with: #{callback_code.inspect}"
end
end
end
end
end
Opscode just confirmed that it is a bug in Chef. If someone needs more details and status of the fix, please use these links:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With