- From: Seth Chisamore <
>
- To:
- Subject: [chef] Re: "::Chef.Recipe.send(:include, ...)" versus "include ..." ??
- Date: Thu, 26 May 2011 10:42:37 -0400
Ringo,
To avoid this :)
[Thu, 26 May 2011 13:32:20 +0000] FATAL: NoMethodError: undefined method
`include' for #<Chef::Recipe:0xb6c36764>
Full stack trace looks like this:
NoMethodError: undefined method `include' for #<Chef::Recipe:0xb6c36764>
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/mixin/recipe_definition_dsl_core.rb:56:in
`method_missing'
/var/chef/cache/cookbooks/mysql/recipes/server.rb:22:in `from_file'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/cookbook_version.rb:578:in
`load_recipe'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/mixin/language_include_recipe.rb:40:in
`include_recipe'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/mixin/language_include_recipe.rb:27:in
`each'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/mixin/language_include_recipe.rb:27:in
`include_recipe'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/run_context.rb:72:in
`load'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/run_context.rb:69:in
`each'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/run_context.rb:69:in
`load'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/client.rb:195:in
`setup_run_context'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/client.rb:159:in `run'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/application/client.rb:239:in
`run_application'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/application/client.rb:229:in
`loop'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/application/client.rb:229:in
`run_application'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/../lib/chef/application.rb:66:in
`run'
/usr/lib/ruby/gems/1.8/gems/chef-0.10.0/bin/chef-client:26
/usr/bin/chef-client:19:in `load'
But seriously, the main reason is that recipe files are not regular
Ruby...that is to say they are a DSL that is evaluated by the chef-client at
runtime. Chef uses some of Ruby's method_missing magic to evaluate the recipe
DSL (resource definitions) in your recipe code, in this case 'include' cannot
be evaluated as it is passed up the method_missing chain.
The variant we use in 'mysql::recipe'
::Chef::Recipe.send(:include, Opscode::OpenSSL::Password)
actually sends the 'include' message to Chef::Recipe class definition with
the Opscode::OpenSSL::Password module as a payload. In this case we want to
make the method 'secure_password' available to this instance of Chef::Recipe
(ie Chef::Recipe:0xb6c36764). So essentially we are in an instance of
Chef::Recipe sending a message to it's class definition.
We could have also used 'extend' like so:
extend Opscode::OpenSSL::Password
That would make every method in the Opscode::OpenSSL::Password module
available to EVERY instance of Chef::Recipe, but that feels dirty.
We could have accomplished the same thing as using extend by creating our
library slightly differently also:
class Chef
class Recipe
def secure_password
# RANDOM CODE HERE
end
end
end
This essential would open up the Chef::Recipe class at runtime and add a
secure_password method and thus making it available to every instance of
Chef::Recipe. I believe this is the example you will see on the wiki in the
Libraries section [0].
Hope that helps.
Seth
--
Opscode, Inc.
Seth Chisamore, Senior Technical Evangelist
IRC, Skype, Twitter, Github: schisamo
[0]
http://wiki.opscode.com/display/chef/Libraries
On Thursday, May 26, 2011 at 9:27 AM, Ringo De Smet wrote:
>
Hello,
>
>
While investigating the setup of some cookbooks, I bumped into this line:
>
>
https://github.com/opscode/cookbooks/blob/master/mysql/recipes/server.rb#L20
>
>
Can someone explain me why the meta-level invocation is used here
>
instead of just a direct invocation?
>
>
So
>
>
::Chef::Recipe.send(:include, Opscode::OpenSSL::Password)
>
>
instead of
>
>
include Opscode::OpenSSL::Password
>
>
>
Cheers,
>
>
Ringo
Archive powered by MHonArc 2.6.16.