Managing Jenkins with Puppet, part 1: Basic installation
It seems every other organization is using Jenkins these days. Jenkins is a continuous integration and continuous delivery server that can be used to automate building, testing, and delivering or deploying software.
Many organizations also use Puppet for their configuration management needs. Puppet is, if not the de facto configuration management solution, at least one of the most mature and field tested ones. It consists of several server components, agents, a declarative programming language, amongst others. Puppet can be used to install, set up and manage large number of all kinds of resources.
Modifying XML files with Puppet's Augeas resource
This article is based on an earlier article written in Finnish.
Here I describe how to make changes to an XML file with Augeas - a useful approach when managing the whole file as a template is out of the question. The configuration file used as an example, web.xml, belong to Pwm, and we intend to set the webapp context parameter.
As discussed before it is important to get an idea of how Augeas sees the file before attempting to modify it with Puppet. First we tell which Augeas lens to use (here: Xml) and which file(s) to associate with the Xml lens. This can be done with in one step:
Using Augeas to manage resources in Puppet
This translated from the original Finnish article that is available here.
The Augeas resource in Puppet allows one to manage parts of a complex configuration file instead of managing the whole file using a template or a static file. For trivial cases stdlib’s file_line resource may be sufficient. While use of templates or static files is in general more reliable and easier than use of Augeas, the latter is quite useful in many cases. As using Puppet Augeas resource directly is quite challenging, a useful practice is to first make the changes manually with “augtool” and only then convert the results into Puppet Augeas resources. We use PostgreSQL’s pg_hba.conf file here as an example.
Allowing changes to a Puppet-managed resource outside of Puppet
When a resource is managed by Puppet it is typically managed fully, or not at all. Exceptions to this rule, such as the “replace” parameter in the File resource, are rare. However, sometimes you end up having to change the properties of a resource outside of Puppet without making Puppet overwrite those changes on the next run. A good example is a set of firewall rules managed with puppetlabs-firewall - you generally want to manage the whole ruleset with Puppet so that you can be sure of the state of the ruleset. For example, if you have libvirt installed, a bunch of virbr0-related rules may appear without your consent. On RedHat-based distros you may also see several rules getting removed by puppetlabs-firewall. Or a fellow sysadmin may have added some random iptables rules for debugging purposes. These are good reasons to have
Getting the interface that matches an IP in Puppet
I was recently in a situation where I needed to figure out which interface name matched a particular, static IPv4 address. On a single or a handful of nodes this could have been hardcoded in Hiera, for example, but there were dozens of nodes. The way I solved this was by creating a custom fact that uses the IPv4 address and loops through the interfaces list to find the matching interface name:
Why modules in Puppetfile should be sorted
This is probably one of the shortest blog postings in the history of this blog. But as this topic does not seem to be covered in more generic articles about avoiding Git merge conflicts (e.g. this, this and this), here it goes.
Adding modules to the Puppetfile is a quite common task. When you or your team has multiple feature branches at the same time many of those branches may add new Puppet modules to the Puppetfile. This is fine, unless the new modules are added to the bottom of the Puppetfile: Git will get confused because it sees that multiple commits have changed the exact same place in the Puppetfile.
Pidgin IRC with ZNC and Freenode SASL external auth
I use Pidgin as my instant messaging client because it is open source and because it supports almost all IM protocols directly or through plugins. In my case I need support for IRC, XMPP, Facebook, Slack and SIPE (Office 365). Apparently it would be possible to use Pidgin for Signal as well, but as official Signal client is open source and works quite well I’m fine with running it standalone. As I use Linux, I can rarely hope for a native client for the proprietary IM services. Plus even if there was one, I would not want to run 4-5 messaging applications when I can have one (or two). Or to have the same amount of IM web applications open just to get messages.
Puppet rspec testing: understanding describe and context
In the Puppet module rspec testing with PDK blog post I covered the procedure of creating and running puppet-rspec tests with PDK. This blog post will go more in-depth to that topic, in particular describe and context which you see in all puppet-rspec tests.
When looking at the puppet-rspec test syntax the first time it looks very “rubyesque”. Somebody used to staring at Python code, for example, could call the syntax “odd” or “1337”. Fortunately reading the Ruby rspec documentation helps understand what is going on under the hood and thus making the spec files look less magical. In my case rspec documentation helped understand how contexts work. In the previous blog post a context was created for every supported operating system listed in metadata, and rspec tests were run for each of them by using facts from facterdb.
Testing Puppet feature branches in Foreman
With default settings Foreman does not allow Puppet Agents to specify their own environment when connecting to the Puppetserver. This makes it impossible to use r10k and feature branch workflow like you can with a normal Puppetserver. This behavior can fortunately be reverted easily by modifying Foreman configuration file, /etc/foreman/settings.yaml:
# Allow testing feature branches on nodes
:enc_environment: false
After modifying settings restart the webserver, e.g.
Migrating from Fabric 1 to Fabric 2
Fabric is a Python library for executing shell commands remotely over SSH in serial or parallel mode. I used Fabric 1 for years and it was - and still is - an excellent tool. While Fabric’s use-cases overlap somewhat with those of Ansible, the difference is that Fabric is not state-based. In other words, in Fabric you don’t tell that “file a should have contents n and mode m”. Instead, you just run commands on the target host which hopefully result in the end state you’re looking for. Or maybe you’re not even interested in end-state per se, but just need to run some commands. Both approaches have their use-cases. Fabric and Ansible are quite powerful as orchestration tools: they allow running task a on server x, then task b on server y. For enforcing infrastructure to be in a certain state we prefer Puppet and Terraform over Ansible.