Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access Node attributes in Chef Library

I'd like to create a Chef library that:

  • Provides a few namespaced functions
  • Accesses the node's attributes

That library is meant to interface with an external system and retrieve some inputs from there. I need to access the node attributes to allow the user to override the inputs received from the external system:

Desired Usage (Recipe)

inputs = MyLib.get_inputs

Library (What I have now)

This is inspired by those docs.

class Chef::Recipe::MyLib
  def self.get_inputs
    override_inputs = node.fetch(:mylib, Hash.new).fetch(:override_inputs, nil)

    unless override_inputs.nil?
      return override_inputs
    end

    # Do stuff and return inputs (no problem here)
    # ...
  end
end

Problem

Right now I'm getting:

undefined local variable or method `node' for Chef::Recipe::Scalr:Class
like image 391
Thomas Orozco Avatar asked Feb 27 '14 19:02

Thomas Orozco


People also ask

What is node attribute in chef?

An attribute is a specific detail about a node. Attributes are used by the chef-client to understand: The current state of the node. What the state of the node was at the end of the previous chef-client run.

How do chefs use attributes?

The sources of Chef attribute in Recipes (in cookbooks) We can specify the attribute at node level while running chef-client. Those attributes are referred to as node attributes. You must precede the attribute name with node. when you set an attribute directly in a recipe.


2 Answers

You don't have access to the node object in a library unless you pass it into the initializer:

class MyHelper
  def self.get_inputs_for(node)
    # Your code will work fine
  end
end

Then you call it with:

inputs = MyHelper.get_inputs_for(node)

Alternative, you can to create a module and mix it into the Chef Recipe DSL:

module MyHelper
  def get_inputs
    # Same code, but you'll get "node" since this is a mixin
  end
end

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

Then you have access to the get_inputs method right in a recipe:

inputs = get_inputs

Notice this is an instance method versus a class method.

In short, libraries don't have access to the node object unless given as a parameter. Modules will, if they are mixed into the Recipe DSL. Additionally, the node object is actually an instance variable, so it's not available at the class level (i.e. self.).

like image 160
sethvargo Avatar answered Sep 19 '22 09:09

sethvargo


I think there is a scoping issue here as the Node's scope is under Chef::Recipe. So try omitting MyLib in the definition and see if it works. I have a library defined this way that works:

class Chef
  class Recipe
    def my_library_method
      #access node stuff here should be fine
    end
  end
end
like image 22
Arya Avatar answered Sep 22 '22 09:09

Arya