Chef NoMethodError when using library module method with registry_key in recipe

1.1k Views Asked by At

I receive the error

NoMethodError
-------------
undefined method `registry_key' for HashOperations:Module

when converging a Chef cookbook.

This is the short version of the code from libraries/hash_operations.rb:

module HashOperations
  # Tried: require 'chef/mixin/shell_out'
  # Tried: include Chef::Mixin::ShellOut

  def self.create_reg_keys(item_hash)
    item_hash.each do |item_name, item_props|
      # (...) construct the item_keys array
      registry_key "HKEY_LOCAL_MACHINE\\SOFTWARE\\#{item_name}" do
        recursive true
        values item_keys
        action :create
      end
    end
  end

  def self.generate_reg_keys_for_item_key(...)
    # some hash operations here
    create_reg_keys(item_hash)
  end

end unless defined?(HashOperations)

class Chef::Resource
  # Tried: Chef::Resource.send(:include, HashOperations)
  # Tried: include HashOperations
  extend HashOperations
end

and here is recipes/default.rb:

Chef::Resource.send(:include, HashOperations)

ruby_block "test" do
  block do
    # Tried: Chef::Recipe.send(:include, HashOperations)
    items_keys.each do |item_key|
      HashOperations.generate_reg_keys_for_item_key(..., item_key)
    end
  end
end

I guess the main problem comes from trying to use a Chef resource, registry_key, inside a method inside a module, which in turn is called from the recipe.

I have a working version if I'm not using a module, but I need a module if I want to test the code with ChefSpec, as several articles pointed (like this one: Stubbing library class methods in ChefSpec )

The link mentioned above is the reason for which I use end unless defined?(HashOperations) inside the module.

I've tried using include statements, it can be seen in the comments, or in the recipe's first line, as several StackOverflow posts suggested, with no luck. One post was discussing the usage of LWRP, but I really don't think it's the case here, as the code is strictly related to this recipe and wouldn't be used in some other cookbook.

As a note: I'm using self. in order for the defs to be visible to one another, otherwise I receive an error about generate_reg_keys_for_item_key not being available.

So, taking into account the fact that I've spent quite some hours searching for solutions on this, including the ones suggested by StackOverflow, the questions: what's the best approach to solve this error and have a simple solution that can be tested with ChefSpec (I'm not entirely excluding LWRPs though), and WHAT and HOW should I include for the registry_key to be visible on converge operation ?

1

There are 1 best solutions below

1
On

You can't use the recipe DSL from helpers like this unless the helper is itself set up as a DSL extension. Check out https://coderanger.net/chef-tips/#3 to see how to do that.