2013-10-02 4 views
5

Я пытаюсь написать библиотеку для поваренной книги повара, которая упрощает некоторые обычные поиски.Как я могу получить доступ к текущему узлу из библиотеки в поваренной книге повара?

Например, я хотел бы быть в состоянии сделать что-то подобное в cookbook/libraries/library.rb, а затем использовать его из рецепта в том же поваренной книге:

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

Проблема заключается в том, что внутри файла библиотеки Chef ни объект 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', который делает вспомогательные функции доступными во всех рецептах (и может перезаписывать потенциально уже существующие с тем же именем). Я думаю, что это запах кода и предпочитает, чтобы моя версия включала только модуль «Помощники» в рецепт. –

+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 

Я не знаю, при использовании переменного класса неодобрения, но это работает во всех моих тестах, и это приятно и легко использовать.

Смежные вопросы