When working with Puppet and Puppet modules in particular you quickly notice that there are several ways to manage module dependencies. Today I learned about a new way introduced in Puppet Bolt 3.x, so I thought I'd compile a list that celebrates this diversity:
- metadata.json: used primarily to dependency metadata to Puppet Forge. Some tools like librarian-puppet and puppet-litmus use / can use this file to download dependency modules. The downside is that you can't define the location of the modules, so you're limited to Forge modules.
- Puppetfile: this is used by r10k and librarian-puppet to fetch modules. It supports downloading modules from Forge and Git. It is often used with Puppet control repositories, but is quite useful when using puppet apply as well (example here).
- .fixtures.yml: used by puppetlabs-spec-helper to download module dependencies that rspec-puppet needs to run the tests. In some more advanced modules (like puppet-module-keycloak) you may see several fixture files: one for with well-defined module versions and one for "whatever module are latest". The latter allows spotting regressions with new modules quickly.
- bolt-project.yaml: this is the new kid on the block. The old "bolt puppetfile install" command that could reuse an existing Puppetfile (e.g. in a control repository) was removed in Bolt 3.0. The new way requires defining module dependencies in bolt-project.yaml. Once you run "bolt module install" Bolt will create a Puppetfile based on contents of bolt-project.yaml. What the purpose of this change is I do not know. A side-effect is that you may need to move your Bolt project to a subdirectory inside your control repository or you could wipe out you main Puppetfile. That said, Bolt tries to avoid overwriting changes in the Puppetfile, so Bolt cold potentially co-exist with a control repo Puppetfile if you're careful.
So there are many ways to define Puppet module dependencies. Do we need that many? Probably not, but that's what we have. I hope that the changes to Bolt were made for a (good) reason, because I don't see the need for yet another way to define module dependencies in Puppet.