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

ぃ、小莉子 提交于 2019-11-30 08:33:14

问题


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.


回答1:


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.




回答2:


I just ran into this while trying to access the current environment in a library. I couldn't really figure out how to use modules to get access to the node and I didn't want to pass the node into each method call (or the instantiation call) so I did this (example code.. not the actual functionality):

# libraries/account.rb
class Account
  @@env = "_default"

  def self.env=(env)
    @@env = env
  end

  def settings
    Chef::EncryptedDataBagItem.load(@@env, "settings") || {}
  end
end

# recipes/accounts.rb
Account.env = node.chef_environment

Account.new.settings

I don't know if using class variables is frowned upon, but it works in all my tests and it's nice and easy to use.



来源:https://stackoverflow.com/questions/19134728/how-can-i-access-the-current-node-from-a-library-in-a-chef-cookbook

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!