Last week, we looked at an advanced spec helper, puppetlabs_spec_helper, and generated some tests with it. We also looked at the rake targets available with the helper and you may have noticed the build target: “Build puppet module package”. Prior to that, we created a new certs module that is code only, no data, for use in distribution of certificate files for web servers. It seems like a good opportunity to see how this works so we can upload a module to the forge.
Forge Modules
The Puppet Forge is a central repository for shared modules, written by Puppet Labs or by the community. It’s the puppet analog to perl’s CPAN, python’s pip, etc. – tell puppet you want a module and it fetches it from the forge. As the modules are shared, rather than specific to a user’s installation, be sure to use sound fundamentals to create a portable module. Your role and profile modules, which likely reference umpteen other modules and the files and templates they contain, are not good candidates for the forge, but a utility module like the certs module is a good candidate.
Publishing
Puppet Labs maintains a large document on the procedure to publish a module to the forge. While we can all read the directions, where’s the fun in that? Well, you should, but we’ll focus on the highlights for now. We’ll need a forge account, an updated metadata.json file, and an uploadable tarball to continue. Create your login and save the user/pass in your password vault. The username you specify should be the same as you use in the metadata’s ‘author’ key. If you already have an account, sign in now.
Next, review the metadata.json in the module. When using puppet module generate, the version is set t0 0.1.0, you may want to increase that now. The default license is Apache 2.0, this will work fine for most people. Make sure the source/issue_url/project_page values point to the correct location and your dependencies are defined. You may want to add an operatingsystem_support hash so users understand where the module has been tested – even on well maintained modules, this doesn’t mean a non-listed operating system will not work, but it ensures that users are not surprised if it fails. Here’s what the certs metadata looks like:
{ "name": "rnelson0-certs", "version": "0.5.0", "author": "rnelson0", "summary": "SSL Certificate File Management", "license": "Apache 2.0", "source": "https://github.com/rnelson0/certs", "issues_url": "https://github.com/rnelson0/certs/issues", "project_page": "https://github.com/rnelson0/certs", "operatingsystem_support": [ { "operatingsystem":"RedHat", "operatingsystemrelease":[ "6.5" ] } ], "dependencies": [ { "version_range": ">= 1.0.0", "name": "puppetlabs-stdlib" } ] }
There is at least one bug with puppet and broken/incomplete metadata so be sure to make sure the syntax is correct. Beware of semantic version numbers and the placement of commas. Unlike the Puppet DSL, trailing commas in a list are invalid. I am unaware of a programmatic method to determine valid metadata, but the fix at least looks like it will specify the metadata as the error’s source.
With everything in place, it’s time to build the module. Run rake build. If you receive some “cannot parse JSON” errors, go back to the metadata and very that every list item has a comma except the last and that all brackets and braces have a begin and end pair. Once the metadata is correct, you’ll see exactly noting on the command line, but an ls reveals some new files:
[rnelson0@build certs]$ rake build [rnelson0@build certs]$ ls manifests metadata.json pkg Rakefile README.md spec tests [rnelson0@build certs]$ ls pkg rnelson0-certs-0.5.0 rnelson0-certs-0.5.0.tar.gz
Hooray, our module is ready to upload! Every time you run rake build, it will create a new package or overwrite the existing one. If for any reason you need to remove the packages, use rake clean. Be aware that you cannot undo that action, so don’t clean out old versions that you haven’t uploaded to the forge yet! You do not want to track these files, as they’ll become part of your module and start to bloat the size. Add them to .gitignore:
[rnelson0@build certs]$ cat >> .gitignore pkg/
Don’t forget to commit, push, and merge your changes to your upstream now!
Unfortunately, there is no CLI interface for the forge or a way to PUT your package via a URI*. Download the package from your build server, then upload it to the forge.
That’s it. Your module is now available for everyone to download!
Summary
Today’s exercise was pretty simple, but powerful: take an existing module, update some metadata, and publish it to the forge. Your module is now available for everyone to download. You can also move your module from the git repo section of your Puppetfile to the forge section, and so can other people. Take some time to promote your module via social media and then the fun stuff begins – Pull Requests. You’re going to have to take care of this thing you just created. For a small utility module like rnelson0-certs, that’s not going to require much. Large modules, like puppetlabs-apache, will require a lot more effort. I think it’s worth it, though!