Search code examples
chef-infratest-kitchenberkshelfberksfile

What is the purpose of .kitchen.yml file in the root of project generated by 'chef generate app'?


I have an old single repo of cookbooks intended for creating a complete development environment with Vagrant. I want to "refactor" it according to best practices. I want to split big cookbooks, make proper wrapper cookbooks of community cookbooks and add InSpec tests runnable by Testkitchen in order to check everything is installed as it supposed to be.

I decided to start from scratch and see what skeleton will be created by executing chef generate app some_name. This command produces the following set of files:

.
|-- .gitignore
|-- .kitchen.yml     <----------
|-- README.md
|-- cookbooks
|   `-- some_name
|       |-- Berksfile
|       |-- chefignore
|       |-- metadata.rb
|       |-- recipes
|       |   `-- default.rb
|       `-- spec
|           |-- spec_helper.rb
|           `-- unit
|               `-- recipes
|                   `-- default_spec.rb
`-- test
    `-- smoke
        `-- default
            `-- default_test.rb

I noticed .kitchen.yml created in the root. Since now it is recommended to create single VCS repo for every cookbook, it looked a bit weird to me to have .kitchen.yml in the root. But on the other hand, it can be a good idea to keep VM configuration for testing all of my cookbooks and its test suites in single root file.

Then I decided to check if I will be able to run tests of all project's cookbooks from the root .kitchen.yml. I made a simple wrapper cookbook for installing Java, with depends 'java' in cookbook's metadata.rb and prepared root .kitchen.yml.

The problem I faced running kitchen test from the root is that community cookbook java is not resolved on kitchen tests execution. I tried to add Barksfile into cookbook directory and it did not help (still unknown java dependency). Looks like Kitchen only works with Berksfile relative to .kitchen.yml. Then I tried adding Berksfile in the project root and of course, it did not work because it also searches for metadata.rb in the root directory.

So looks like it is not a good idea to have a single .kitchen.yml for all cookbooks in the project root. Why is it generated then? I also do not like that I will have to write almost the same .kitchen.yml inside of every cookbook's directory, but looks like I have no choice if want to resolve dependencies from metadata.rb.

Would be nice if you could also suggest me a good example repo implementing best practices of wrapper/role-cookbooks + testing. My project is simple enough: it just creates some users, prepares environment and installs lots of services mostly using wrapped community cookbooks. I want to keep it in single repo and test with Kitchen + InSpec


Solution

  • app is a hybrid of manyrepo and monorepo design, so in that structure you would keep all your local cookbooks in the single repo and pull in external stuff as needed. The idea of the root kitchen.yml is to have a place to do top-level tests for the app as a whole. Usually this means testing policies rather than cookbooks these days, see https://github.com/poise/yolover-example for examples of that.

    As for cookbook resolution issues, you do probably want a root Berksfile if not using policies, though it can be just:

    source 'https://supermarket.chef.io/'
    source chef_repo: '.'
    cookbook 'whatever'
    

    This app style was somewhat of an experiment and probably needs to be revised/updated a bit as it has aged.