6

我通过一个模块扩展了配方类以提供一些属性,这些属性使我能够全局访问我的路径,这些路径是动态构造的。例子:

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:Chef::Resource::Bash 的未定义方法“user_home”

奇怪的行为是,用户属性工作正常,但代码块中使用的 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

所以对我来说,这似乎是厨师特有的问题。

谁能解释一下,为什么会这样?

是否有更好的解决方案来全局访问动态构建的路径和属性?

谢谢。

4

2 回答 2

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类中,使您的模块方法可用于所有资源。

于 2016-04-26T19:20:21.713 回答
0

你能把你的路径作为属性吗?

是在环境层面还是节点层面?

如果我们这样做是为了构建安装说明,我们会对食谱属性做类似的事情。在这种情况下,我们从数据包构建安装说明

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

所以也许这是导致行为不一致的资源之一的问题?

于 2012-11-09T09:40:26.597 回答