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:inmethod_missing’
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’
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:
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:
RANDOM CODE HERE
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 .
Hope that helps.
Seth Chisamore, Senior Technical Evangelist
IRC, Skype, Twitter, Github: schisamo
On Thursday, May 26, 2011 at 9:27 AM, Ringo De Smet wrote:
While investigating the setup of some cookbooks, I bumped into this line:
Can someone explain me why the meta-level invocation is used here
instead of just a direct invocation?