如何在食谱编译时阅读食谱文件?

时间:2014-01-08 21:30:02

标签: chef

这种事情在厨师食谱中很常见:

%w{foo bar baz}.each do |x|
  file "#{x}" do
    content "whatever"
  end
end

但是我想从与食谱保存的文件中读取要循环的项目,例如:

File.open('files/default/blah.txt').each do |x|
  file "#{x}" do
    content "whatever"
  end
end

如果我给出blah.txt的完整路径,其中chef-client恰好缓存它,但它不可移植,这是有效的。如果我像在示例中那样编写它,它“无效”,“希望”当前目录是cookbook的根目录。有没有办法在编制食谱时获取cookbook根目录?

3 个答案:

答案 0 :(得分:4)

在Chef 11中,你可以变得聪明并使用Dir globbing来实现你想要的行为:

  1. 禁用延迟加载资源。启用延迟资源加载后,Chef将在Chef Client运行期间请求资产(如cookbook文件,模板等)。在您的用例中,您需要在强大的配方执行开始之前服务器上存在这些资产。将以下内容添加到client.rb

    no_lazy_load true
    
  2. 在磁盘上查找cookbook缓存的路径。这有点神奇和实验,但是:

    "#{Chef::Config[:file_cache_path]}/cookbooks/NAME"
    
  3. 获取正确的文件:

    path = "#{Chef::Config[:file_cache_path]}/cookbooks/NAME/files/default/blah.txt"
    File.readlines(path).each do |line|
      name = line.strip
    
      # Whatever chef execution here...
    end
    
  4. 如果您关心使用文件特定性处理程序,您可能还需要查看Cookbook.preferred_filename_on_disk

答案 1 :(得分:4)

另一个解决方案,对于那些不需要文件内容直到收敛时间但不需要任何client.rb修改的人来说,是使用cookbook_file将资源读入你的file_cache_path然后延迟加载它。这是一个示例,我在一个groovy脚本中读取嵌入到xml模板中。

script_file = "#{Chef::Config['file_cache_path']}/bootstrap-machine.groovy"
cookbook_file script_file do
    source 'bootstrap-machine.groovy'
end

config_xml = "#{Chef::Config['file_cache_path']}/bootstrap-machine-job.xml"

template config_xml do
    source 'bootstrap-machine-job.xml.erb'
    variables(lazy {{
        :groovy_script => File.open(script_file).read
    }})
end

答案 2 :(得分:0)

为了整洁'为了这个,我喜欢使用File.join()和{。}的组合 " cookbook_name"变量

File.join(
  Chef::Config[:file_cache_path],
  'cookbooks',
  cookbook_name,
  'path/to/blah.txt'
)