Using node attributes in a cookbook library

There’s a very old SO thread about making the node attributes hash available in a cookbook library. For usability reasons, I’m trying to avoid forcing recipes to instantiate the library and pass node to the constructor. That leaves me with the option of creating a module for the purpose of calling Chef::Recipe.send(:include, MyHelper), ie:

module NodeAttributes
  def self.inputs
    node.fetch
  end
end

Chef::Recipe.send(:include, ::NodeAttributes)

However, when I try to call ::NodeAttributes.inputs the variable node (in self.inputs()) is undefined.

Is there perhaps a better/different approach that has developed since the SO thread? Any thoughts on maybe what I’m doing wrong following this example code?

If context helps, my library is a wrapper for calling our Hashicorp Vault for secrets. The library only requires that you call ::MyCorp::Secrets.read(secret_name) from your recipe. It works great right now, but I want to extend it to support some other behaviors based on ec2/azure instance tags, or node tags. To do that, I need access to the node attributes.

The library automatically handles vault authentication, etc. It uses a singleton pattern with no initialize method, in large part because you’d have to create a new instance in every recipe where you need to get secrets, and I don’t want to force my consumer code to deal with that, or in this case also remember that it needs to pass node to properly initialize the library.

thanks for any suggestions

when using a module node attributes are already available using node[‘foo‘]. In that article you linked it’s saying using class method instead of module the node object is not available by default. The chef recipe send makes it available to recipes. if you add an include line in your recipe then you should be able to simply call it like NodeAttributes.inputs.

You can also add it to the chef dsl making it available every where by changing your last line to Chef::DSL::Universal.include(Mod_name::Module). Then you can use it in recipes, resouces etc without needing the :: nominclature. I would also recommend rewriting to something more like this:

module CBNAME
  module Helpers
    def node_attributes.inputs
      node.fetch
    end
  end
end

Chef::DSL::Universal.include(CBName::Helpers)

then in recipe, attributes, resources, and other libraries node_attributes.inputs is all you’d need to call it.