Help abstracting WET code to methods in a library cookbook

Greetings Chefizens,

I’m trying to abstract some WET code I have sprinkled around several of my
recipes into a library. I’m trying to define a method in a “library cookbook”,
and use that method in a different cookbook. But I’m failing. Below I show a few
techniques I’m trying. The examples below are contrived and very simple –
I want to start simple and actually get it, before I try more abstractions
layered on top (say, LWRP).

Docs I’m reading in an attempt to teach myself how to wield library cookbooks in
this manner:

[1] http://stackoverflow.com/questions/15595144/dry-within-a-chef-recipe
[2] http://stackoverflow.com/questions/17333486/how-do-i-share-code-across-chef-cookbooks-in-a-chef-repo
[3] http://www.opscode.com/blog/2013/09/04/demystifying-common-idioms-in-chef-recipes/
[4] http://dougireton.com/blog/2012/12/16/how-to-include-the-windows-cookbook-helper-methods-in-your-chef-recipe/
[5] http://docs.opscode.com/essentials_cookbook_libraries.html

All of my attempts result in:

Recipe Compile Error in /var/cache/chef/cookbooks/hoosier/recipes/default.rb
NameError
uninitialized constant Chef::Recipe::Urmom

And so:

The cookbook “urmom” has a “halper” library: cookbooks/urmom/libraries/halper.rb:

module Halper
def saywhat
return "urmom"
end
end

The cookbook “hoosier” has a dependency set in metadata.rb on “urmom”. It is in
hoosier’s default recipe that I’m trying these tests.

foo = Urmom::Halper.saywhat
Chef::Log.debug(“HIGGS-BOSON: result: #{foo}”)

I run it: chef-client -l debug -L /var/log/chef/client.log -o “recipe[hoosier]”

This technique is how I understood what [1] is saying.

Next I try this in recipe[hoosier::default], based on [3] and [4]:

::Chef::Recipe.send(:include, Urmom::Halper)
foo = Urmom::Halper.saywhat
Chef::Log.debug(“HIGGS-BOSON: result: #{foo}”)

Next I try:

extend Urmom::Halper
foo = Urmom::Halper.saywhat
Chef::Log.debug(“HIGGS-BOSON: result: #{foo}”)

Last, I change the Halper library, per Ranjib Dey’s comment in [3]:

class Chef::Recipe::Halper
def saywhat
return "urmom"
end
end

The calling recipe is still:

foo = saywhat
Chef::Log.debug(“HIGGS-BOSON: result: #{foo}”)

Any help graciously accepted :>
kallen

OK. This works:

urmom/libraries/halper.rb
module Urmom; module Halper;
def self.saysomethin(say)
puts "==================== HIGGS-BOSON: #{say} .. from the library call"
end
end

urmom/resources/default.rb
actions :saywhat, :sayinsult
default_action :saywhat
attribute :say, :kind_of => String, :default => "urmom", :name_attribute => true

urmom/providers/default.rb
include Urmom::Halper
action :saywhat do
say = new_resource.name + " .. from the LWRP"
::Urmom::Halper.saysomethin(say)
end

hoosier/recipes/default.rb
Chef::Recipe.send(:include, Urmom::Halper)

::Urmom::Halper.saysomethin("kerfuffle")

urmom "dooooooootdeedoo" do
end

jazzbutcher$ chef-client -z -o recipe[hoosier] | grep HIGGS
==================== HIGGS-BOSON: kerfuffle .. from the library call
==================== HIGGS-BOSON: dooooooootdeedoo .. from the LWRP .. from the library call

\o/
kallen

On Tue, 19 Nov 2013, kallen@groknaut.net wrote:

Greetings Chefizens,

I'm trying to abstract some WET code I have sprinkled around several of my
recipes into a library. I'm trying to define a method in a "library cookbook",
and use that method in a different cookbook. But I'm failing. Below I show a few
techniques I'm trying. The examples below are contrived and very simple --
I want to start simple and actually get it, before I try more abstractions
layered on top (say, LWRP).

Docs I'm reading in an attempt to teach myself how to wield library cookbooks in
this manner:

[1] ruby - DRY within a Chef recipe - Stack Overflow
[2] ruby - How do I share code across Chef cookbooks in a chef-repo? - Stack Overflow
[3] Demystifying Common Idioms in Chef Recipes - Chef Blog | Chef
[4] http://dougireton.com/blog/2012/12/16/how-to-include-the-windows-cookbook-helper-methods-in-your-chef-recipe/
[5] http://docs.opscode.com/essentials_cookbook_libraries.html

All of my attempts result in:

Recipe Compile Error in /var/cache/chef/cookbooks/hoosier/recipes/default.rb
NameError
uninitialized constant Chef::Recipe::Urmom

And so:

The cookbook "urmom" has a "halper" library: cookbooks/urmom/libraries/halper.rb:

module Halper
def saywhat
return "urmom"
end
end

The cookbook "hoosier" has a dependency set in metadata.rb on "urmom". It is in
hoosier's default recipe that I'm trying these tests.

foo = Urmom::Halper.saywhat
Chef::Log.debug("HIGGS-BOSON: result: #{foo}")

I run it: chef-client -l debug -L /var/log/chef/client.log -o "recipe[hoosier]"

This technique is how I understood what [1] is saying.

Next I try this in recipe[hoosier::default], based on [3] and [4]:

::Chef::Recipe.send(:include, Urmom::Halper)
foo = Urmom::Halper.saywhat
Chef::Log.debug("HIGGS-BOSON: result: #{foo}")

Next I try:

extend Urmom::Halper
foo = Urmom::Halper.saywhat
Chef::Log.debug("HIGGS-BOSON: result: #{foo}")

Last, I change the Halper library, per Ranjib Dey's comment in [3]:

class Chef::Recipe::Halper
def saywhat
return "urmom"
end
end

The calling recipe is still:

foo = saywhat
Chef::Log.debug("HIGGS-BOSON: result: #{foo}")

Any help graciously accepted :>
kallen