How to read cookbook file at recipe compilation time?

二次信任 提交于 2020-01-01 05:28:09

问题


This kind of thing is commonly seen in Chef recipes:

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

But I want to read the items to loop over from a file which is kept with the cookbook, for example:

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

This works if I give the full path to blah.txt where chef-client happens to cache it, but it's not portable. It doesn't work if I write it like in the example, "hoping" that the current directory is the root of the cookbook. Is there a way to obtain the cookbook root directory as the recipes are compiled?


回答1:


In Chef 11, you can get clever and use Dir globbing to achieve your desired behavior:

  1. Disable lazy loading of assets. With lazy asset loading enabled, Chef will fetch assets (like cookbook files, templates, etc) as they are requested during the Chef Client run. In your use case, you need those assets to exist on the server before the recipe execution starts. Add the following to the client.rb:

    no_lazy_load true
    
  2. Find the path to the cookbook's cache on disk. This is a little bit of magic and experimentation, but:

    "#{Chef::Config[:file_cache_path]}/cookbooks/NAME"
    
  3. Get the correct file:

    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
    

You might also want to look at Cookbook.preferred_filename_on_disk if you care about using the File Specificity handlers.




回答2:


Another solution, for those who don't need the file content until converge time, but one that does not require any client.rb modifications, is to use cookbook_file to read the resource into your file_cache_path and then lazy load it. Here is an example where I read in a groovy script to be embedded into an xml template.

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



回答3:


For neatness' sake, I like to use a combination of File.join() and the "cookbook_name" variable.

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


来源:https://stackoverflow.com/questions/21006941/how-to-read-cookbook-file-at-recipe-compilation-time

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!