2013-10-02 33 views
5

我正在嘗試爲簡化一些常見搜索的廚師食譜編寫一個庫。如何從廚師食譜的圖書館訪問當前節點?

例如,我希望能夠做這樣的事在cookbook/libraries/library.rb,然後在相同的食譜使用它從配方:

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

的問題是,一個廚師庫文件中node對象或search函數都不可用。

搜索似乎有可能通過使用Chef::Search::Query.new().search(...),但我找不到任何作品訪問node。由此產生的錯誤是:

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

使用廚師10.16.4。

+0

相關http://stackoverflow.com/a/22081109/1626687 – spuder

回答

6

你可以做的是將模塊包含在你的食譜中。這樣,您的模塊功能就可以訪問配方的方法,包括node

我通常這樣做對我的庫模塊:

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

然後,在配方,包括我的模塊爲配方的當前實例:

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

這樣,只有目前的食譜包含模塊,並非全部都在整個廚師中運行(因此避免了名稱衝突)。

或者,您可以將當前節點作爲參數傳遞給函數。這樣,你不需要包含模塊(它具有保持模塊名稱空間的好處),但是具有更復雜的方法調用的缺點。

+0

可能是一個愚蠢的問題,但你是什麼意思的「這樣,只有當前的食譜獲取模塊包括在內,並不是全部在整個廚師跑」? –

+2

人們通常會調用'Chef :: Recipe.include MyCookbook :: Helpers',它使輔助函數在所有食譜中都可用(並且可以覆蓋可能已經存在的同名的輔助函數)。我認爲這是一種代碼味道,並且更喜歡我的版本,以便只將'Helpers'模塊明確包含在配方中。 –

+0

我想我明白了。使用Ruby的擴展只會將模塊中的方法添加到正在運行的單個配方對象,而使用像您所提到的include會將它添加到所有Chef :: Recipe對象。謝謝! –

0

我試圖訪問庫中的當前環境時遇到了這個問題。我真的不知道如何使用模塊來訪問節點,我不想將節點傳遞給每個方法調用(或實例化調用),所以我這樣做(例如代碼..不是實際的功能):

# 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 

我不知道如果使用類變量是皺眉,但它適用於我所有的測試,它很好用,易於使用。