[chef] Re: "::Chef.Recipe.send(:include, ...)" versus "include ..." ??


Chronological Thread 
  • 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.

§