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?
In Chef 11, you can get clever and use Dir globbing to achieve your desired behavior:
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
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"
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With