secretSauce
secretSauce

Reputation: 21

Chef: is it possible to define a Chef resource which uses a template, and call it from another cookbook?

I had a resource which used a template in Chef, and it worked fine. Other resources and recipes in the cookbook could call this resource. In my case, I defined a maven artifact resource, where given some maven params (repo name, artifact ID, etc), you could download a file from a Nexus maven repo.

However, when I call the resource from any other cookbook other than that in which it is defined (with metadata.rb specifying the dependency, of course), I get an error

 Chef::Exceptions::FileNotFound
           ------------------------------
           template[/usr/local/nexus-download.bash] (/tmp/kitchen/cache/cookbooks/cookbook-1/resources/nexus_http_artifact.rb line 52) had an error: Chef::Exceptions::FileNotFound: Cookbook 'cookbook-2' (1.0.0) does not contain a file at any of these locations:
[...]

The template was basically a bash script that was later run to download an artifact over the network from a maven repo (Nexus), after checking the MD5 sum and comparing to the current download using the Nexus HTTP API.

Upvotes: 2

Views: 524

Answers (1)

lamont
lamont

Reputation: 3974

You can control the cookbook the template comes from via the cookbook property of the template resource. For a custom resource the cookbook property defaults to the calling cookbook where the resource is used, rather than where it is declared. You can override this easily because you know the name of the cookbook you are writing. So we can so something like this:

cookbooks/mytemplate/resources/foo.rb

provides :foo

property :template_source, String, default: "foo.erb"
property :template_cookbook, String, default: "mytemplate"

action :run do
  template "/tmp/foo.xyz" do
    source new_resource.template_source
    cookbook new_resource.template_cookbook
  end
end

cookbooks/mytemplate/templates/foo.erb:

THIS IS THE DEFAULT TEMPLATE

cookbooks/test/metadata.rb:

name "test"
version "0.0.1"

depends "mytemplate"

cookbooks/test/recipes/default.rb:

foo "whatever"

Callers can then override this like with their own template names and locations and "dependency inject" the template into the resource:

cookbooks/test/recipes/default.rb:

foo "whatever" do
  template_cookbook cookbook_name
  template_source "bar.erb"
end

cookbooks/test/templates/bar.erb:

THIS IS THE OVERRIDDEN TEMPLATE

The cookbook_file resource has a cookbook property that should work identically.

You can this pattern "in the wild" in the sous-chef tomcat cookbook where the properties are defined here and later used in the template resource it renders here and here

Upvotes: 5

Related Questions