Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I access the current node from a library in a Chef cookbook?

I'm attempting to write a library for a chef cookbook that simplifies some common searches.

For example, I'd like to be able to do something like this in cookbook/libraries/library.rb and then use it from a recipe in the same cookbook:

module Example
    def self.search_attribute(attribute_name)
        return search(:nodes, node[attribute_name])
    end
end

The problem is that, inside a Chef library file neither the node object or search function are available.

Search seems to be possible by using Chef::Search::Query.new().search(...), but I can't find anything that works to access node. The resulting error from this is:

undefined local variable or method `node' for Example:Module

Using Chef 10.16.4.

like image 956
borntyping Avatar asked Oct 02 '13 10:10

borntyping


People also ask

What does a node represent in Chef?

A node is any machine—physical, virtual, cloud, network device, etc. —that is under management by Chef. A physical node is typically a server or a virtual machine, but it can be any active device attached to a network that is capable of sending, receiving, and forwarding information over a communications channel.

How do you run a Chef cookbook in node?

You can assign the cookbook directly to a node by adding it to the node's run list. You can add a cookbook to the role and add the role to the node's run list. You can add the role to the run list of another role and add that other role to the node's run list.

What is Library in Chef?

Libraries in Chef provides a place to encapsulate compiled logic so that the cookbook recipes remain neat and clean.


1 Answers

What you can do is to include the module in your recipe. That way, your module functions get access to the methods of the recipe, including node.

I normally do this for my library modules:

# my_cookbook/libraries/helpers.rb
module MyCookbook
  module Helpers
    def foo
      node["foo"]
    end
  end
end

Then, in the recipe, I include the module into the current instance of a recipe:

# my_cookbook/recipes/default.rb
extend MyCookbook::Helpers

That way, only the current recipe gets the module included, not all of them in the whole chef run (you thus avoid name clashes).

Alternatively, you could pass the current node as a parameter to the function. That way, you don't need to include the module (which has the upside of keeping the module namespaces) but has the downside of a more convoluted method call.

like image 54
Holger Just Avatar answered Sep 28 '22 00:09

Holger Just