How to read cookbook file at recipe compilation time?

chef-infra

Solution

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.

Problem

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?

Original source