Overriding files/templates for kitchen runs

In my cookbook, some files and templates are generated by an external tool during build time. So these files do not exist in the cookbook’s “source code” when I work on this cookbook. But if I want to test my recipes I need these files, and the only way I found is putting dummy files inside the cookbook files/templates folders, which is not too great. I’d like to put these files in the test-related folders.

When doing a kitchen run, is there a way to specify a templates/files folder different from the one of the cookbook, as you can with attrbiutes and data bags?
Or is there another solution to my problem.

PS: I’m new to Chef, Inspec, Ruby, so don’t hesitate to point the obvious.

Could you provide an example of these auto generated template files? Are they .erb files? What do you mean by creating dummy files under templates/default ? Aren’t you using the auto generated template files? Sorry for the tons of questions… just trying to understand your usecase

My cookbook deploys jars/wars to a tomcat server. These files are stored in a maven repository and I do not want to store them in the cookbook (which is in version control).
So I have a project containing my cookbook, as source code, and a gradle build script that collects the files from the repository and builds a package containing the cookbook with the jars in the “files” folder. This full cookbook can then be deployed. But the “source” cookbook" still has its “files” folder empty.
I’d like to be able to test this “source” cookbook while I work on it, with dummy files in the tests folder and not in the files folder.
Typically I would like to have a templates_path or files_path in the kitchen config, just as there is a data_bags_path.

Or another solution to avoid mixing test data with dev data.

I think you can use an artifact repository (or just a webserver) for your ear/jar files and you need to point to this repo in your attribute files. Then you do not need to put these files into your cookbook’s file folder. You can use separate env json for dev and prod and both will have its own repo url, artifact version, etc.

For templates it is not clear for me how you prepare these files for chef.
Do you create some config/properties/xml files with some chef/ruby based sections? And after the gradle build you would like to fill these missing parts with chef based on its env.json or attributes?

This would imply the clients have access to this repo, as I guess you want me to use remote_file instead of cookbook_file.
And this is not the case. It’s a private repo.

As for the templates, I do not generate some right now. So nothing to solve yet. But what you describe is typically what I would do.

Not hundred percent sure how your flow looks like. For me it seems you would like to use chef to create an ‘installer’ for your application. (as you ship every release with your cookbook)

I do not know anything about your infrastructure but you may need to transfer all these cookbooks with your artifacts to every application server you would like to manage. That is why I mentioned a repo to store your artifacts (or any shared resource which is available) and ship cookbooks/artifacts separately.

Template files will work as you mentioned but I still have doubts with this approach. Isn’t it possible to use chef to manage all of these files? Can you share some lines of your generated files structure? Will the structure change on every build?

btw. your cookbooks have to follow every release changes on your application and you may have to code some enhancements on your recipes/templates on every structure/major change. Of course you can reduce this activity if you prepare these changes on java build side. Technically it will work but…

I think you have to check habitat as well. If I am not wrong and understand your usecase habitat will help you.

check it here: https://www.habitat.sh/

(habitat maybe a little bit overkill but you can put your app and automation into one package)

The easiest way to sideload anything for a kitchen run is to put it in the test/ folder. You can put cookbooks that only exists for the purposes of testing in there and then point your Berksfile at the cookbooks so they are available for the run and then add to the run_list. That cookbook or cookbooks can configure your test host as needed so that the core recipe(s) can then run after it. By way of example, the OpenLDAP cookbook (among many others) does this https://github.com/chef-cookbooks/openldap

We sell a software+hardware solution for building automation. We ship a server with the application to our customers.
We want to manage the update of this software on all the servers.
I thought Chef could be used this way (with the added benefit of the automatic initial provisioning).
So indeed, for every new version of the software, I planned to create a new version of the cookbook including the updated jars, and publish it on a public Chef server managing all the customers.
I didn’t think about creating a public repo on this server too, to provide the files with remote_file.
But anyway, I think it’s a bit of overkill just to fix my actual problem, which is to prevent polluting the cookbook files with dummy files while I test it.
Also it’s customary in testing frameworks to be able to provide a different set of resources for tests. And it’s already done for attributes and data bags.

I had seen this kind of approach but wasn’t too sure how it could fit my needs.
I will look into it, as it seems it’ll be my only hope for now.

Test-kitchen gives you a handful of ways to mock objects but it somewhat depends what is being mocked and what your goal is as to what interfaces make the most sense. Most of this falls under the more general term “shimming” as these cookbooks/data_bags/nodes/etc are purely for the purposes of testing and will not be uploaded to the chef-server. It’s not polluting the cookbook so much as leveraging test only cookbooks/objects so you don’t have to reinvent a wheel.

So I ended up creating a “wrapper” cookbook called myproject-test in the test folder, with a default recipe calling the cookbook to test and updating the cookbook_file resources to point to the test cookbook, which contains the files for the test that are referenced by myproject.
I guess that with this technique you can do pretty much anything since you can manipulate the resources to test.

test/cookbooks/myproject-test/recipe/default.rb:
include_recipe 'myproject::default’
edit_resource(:cookbook_file, ‘a_file’) do
cookbook 'myproject-test’
end

Berksfile:
cookbook ‘myproject-test’, path: ‘./test/cookbooks/myproject-test’, group: :test

kitchen.yml:

run_list:
- recipe[myproject-test::default]

That’s exactly the pattern we use for lots of resource/library only cookbooks so definitely a tried and true pattern. Glad this works for you!