рецепт шеф-повара - методы модуля недоступны в ресурсах

Я расширил класс recipe через модуль, чтобы предоставить некоторые свойства, которые дают мне глобальный доступ к моим путям, которые создаются динамически. Пример:

module Variables
  def user
    "user_name"
  end
  def user_home
    "/home/#{node['user']}"
  end
end

class Chef::Recipe
  include Variables
end

Проблема в том, что внутри ресурсных блоков эти методы недоступны.

bash "do_something_with_property" do
  user user
  code "somecommand #{user_home}"
end

NoMethodError: неопределенный метод `user_home' для Chef::Resource::Bash

Странное поведение заключается в том, что свойство пользователя работает нормально, но свойство a, используемое в блоке кода, не работает.

После этого я также включил модуль во все ресурсы, выполнив следующие действия:

class Chef::Resource
  include Variables
end

Теперь мое свойство user_home ведет себя иначе внутри блоков ресурсов, чем при использовании «снаружи», что означает:

directory "#{user_home}/new_dir" do
  action :create
end

создает /home/user_name/new_dir

bash "create_dir" do
   code "mkdir #{user_home}/new_dir"
end

приводит к /home//new_dir

Я проверил это с помощью небольшого тестового скрипта, и все работает нормально.

module MyModule
def module_method
    puts "blablalba"
end
end

class A
def block_method (&block)
    block.call
end
end

class B
include MyModule

def doit
    a = A.new
    a.block_method { module_method }
end
end

B.new.doit

Так что мне кажется, что это должна быть проблема, специфичная для шеф-повара.

Может ли кто-нибудь объяснить мне, почему это происходит?

Есть ли лучшее решение для глобального доступа к моим путям и атрибутам, которые строятся динамически?

Спасибо.


person DELUXEnized    schedule 08.11.2012    source источник


Ответы (2)


Мне удалось успешно внедрить методы в область ресурса следующим образом:

libraries/helper.rb:

module MyCookbook
  module Helper
    def my_method
      "foobar"
    end
  end
end

Chef::Resource.send(:include, MyCookbook::Helper)

recipes/default.rb:

file 'foo' do
  content my_method
end

Ключевым здесь является Chef::Resource.send(:include, ...), который внедряет ваш модуль непосредственно в класс Chef::Resource, делая методы вашего модуля доступными для всех ваших ресурсов.

person jayhendren    schedule 26.04.2016

Не могли бы вы указать свои пути в качестве атрибутов?

Либо на уровне среды, либо на уровне узла?

Мы делаем что-то подобное с атрибутами поваренной книги, когда мы делаем это для создания инструкций по установке. В этом случае мы создаем инструкции по установке из базы данных.

default['splunk']['server'] = Chef::DataBagItem.load('Splunk', 'Install')["Server"]
default['splunk']['install_args'] = Chef::DataBagItem.load('Splunk', 'Install')["Arguments"]

default['splunk']['installcommands'] = "RECEIVING_INDEXER=\"#{default['splunk']['server']}\" #{default['splunk']['install_args']} /quiet"

С учетом всего сказанного, я думаю, что расширение класса ресурсов должно было вас устроить. Когда вы говорите, вел себя по-разному внутри ресурсов, в отличие от внешних. Каталог также является ресурсом, поэтому в этом случае он ведет себя по-разному между двумя ресурсами.

http://wiki.opscode.com/display/chef/Resources#Resources-Directory

Так что, возможно, это проблема с одним из ресурсов, который вызывает непоследовательное поведение?

person PatrickWalker    schedule 09.11.2012
comment
проблема с атрибутами заключается в том, что они не учитывают переопределенные значения в роли или среде: ‹br/› default['user'] = 'user_name' default['user_home'] = /home#{node['user']} вот почему я создаю свой путь user_home в рецепте (или там, где мне это нужно) - person DELUXEnized; 09.11.2012
comment
непоследовательное поведение вызвано тем, что по какой-то причине некоторые свойства оцениваются в контексте блока (например, атрибут кода в bash), а другие (например, пользователь и группа) оцениваются в контексте рецепта, где я определил свойства. В любом случае, мне не следует включать один и тот же модуль в класс Resource, потому что в его контексте узел недоступен и возвращает разные значения. - person DELUXEnized; 09.11.2012
comment
Не могли бы вы использовать рецепт для установки атрибута на уровне узла node['user_home'] = /home#{node['user']}, и тогда он будет воспроизводиться в модели приоритета, изложенной кодом операции. Этот рецепт можно добавить в начало роли? Значит ли это, что все рецепты могут просто использовать этот атрибут, и его можно будет передать в ресурсы? Может быть, это немного странно для того, что вы хотите сделать или использовать переменные среды? - person PatrickWalker; 09.11.2012