How does Chef include files generated on runtime as a template source

1.1k Views Asked by At

Using Chef recipe, I am first generating a .erb file dynamically based on inputs from a CSV file and then I want to use that .erb file as a template source. But unfortunately the changes made (in .erb file) are not considered while the recipe is converging the resources. I also tried to use lazy evaluation but not able to figure out how to use it for the template source.

2

There are 2 best solutions below

0
On

Quoting the template documentation:

source Ruby Types: String, Array

The location of a template file. By default, the chef-client looks for a template file in the /templates directory of a cookbook. When the local property is set to true, use to specify the path to a template on the local node. This property may also be used to distribute specific files to specific platforms. See “File Specificity” below for more information. Default value: the name of the resource block. See “Syntax” section above for more information.)

And

local 

Ruby Types: TrueClass, FalseClass

Load a template from a local path. By default, the chef-client loads templates from a cookbook’s /templates directory. When this property is set to true, use the source property to specify the path to a template on the local node. Default value: false.

so what you can do is:

# generate the local .erb file let's say source.erb

template "/path/to/file" do
  source "/path/to/source.erb"
  local true
end

Your question sounds like and XY problem, reading a csv file to make a template sounds counter-productive and could probably be done with attributes and taking advantage of the variable attribute of template resource.

0
On

Assuming you know how to capture the values from the CSV file as a local variable in the recipe.

Examples:
 csv_hostname
 csv_fqdn

Here is what you do to create a template with lazy loading attributes. The following example creates a config file.

example.erb file

# Dynamically generated by awesome Chef so don't alter by hand.
HOSTNAME=<% @host_name %>
FQDN=<% @fqdn %>

recipe.rb file

template 'path\to\example.config' do
  source 'example.erb'
  variables(
    lazy {
      :host_name => csv_hostname,
      :fqdn => csv_fqdn
  })
end

If you need it to run at compile time, add the action to the block.

template 'xxx' do
  # blah blah
end.run_action(:create)