What sucks, who sucks and you suck

Puppet to Ansible

I’ve just completed the move of the configuration management for my very
small home network from an obsolete Puppet 2.x setup to Ansible. Total
time = approximately half a day. Showstoppers - none.

There are only two nodes, a fileserver running OpenIndiana and a Fedora
desktop. I had some very limited Puppet manifests to install my preferred
packages, configure the automounter and apply some local fixes - the bare
minimum for recovery if I ever needed to recreate systems. This was based
on the Puppet 2.6 rulebase I used in my day job, with most of it hacked or
commented out to disable the irrelevant parts.

It was way overkill for what I needed, and the problem was that the Fedora
repository tracked the mainstream Puppet releases much more closely than
staid old EPEL at work, so my 2.6 rules were suddenly running under a 3.7
agent. This worked, but led to voluminous log entries such as:

puppet-agent[6818]: Using less secure serialization of reports and query parameters for compatibility
puppet-agent[6818]: with older puppet master. To remove this notice, please upgrade your master(s)
puppet-agent[6818]: to Puppet 3.3 or newer.
puppet-agent[6818]: The package type's allow_virtual parameter will be
changing its default value from false to true in a future release. If you
do not want to allow virtual packages, please explicitly set allow_virtual
to false.

The entries are harmless, although they tend to indicate that things are
going to break at some point in the future. And honestly, “less secure
serialization”? It doesn’t really answer the four key questions of a lazy
sysadmin: Yeah? And? So? What?

More importantly, I just didn’t fancy delving into an aging Puppet
codebase that had been thrown together to begin with, and refactoring to
some unknown degree to bring it up to 3.x standards. Puppet’s problem here
is that the language has changed across releases, and practices that were
previously recommended or common are now deprecated or even unsupported.
In particular, the scoping changes
looked likely to mean some extensive recoding, as I relied a lot on
inheritance previously. Or maybe not - it was working now. But would it
still work when Fedora 30 brought Puppet 7.0 with it?

So, as I was currently using Ansible more in my day job, I opted to
rewrite the whole thing in Ansible anyway. It’s a lighter weight tool,
it’s very quick to grasp and, so far, it hasn’t suffered the kind of
semantic upheavals that Puppet has gone through. As mentioned, it took
about half a day to convert the few Puppet classes I had into playbooks
and tasks. In fact, I was so confident that the Ansible tasks were doing
what I intended that I was able to extend more of them to cover my
fileserver (which under Puppet, only had a couple of simple permission
changes applied).

The Puppet code was in a module, and the Ansible task is in a role -
potay-to, potah-to. (However, Ansible’s with_fileglob loop doesn’t
currently allow you to exclude particular files. I can live with that.)
Beyond that, it was pretty much a one-to-one syntactic conversion of the
Puppet semantics to Ansible. (Plus of course, I lost all the legacy
code that I had never needed in the first place.)

As I only have two nodes, I opted to forego the idea of a control node and
just wrote local playbooks for each host (95% similar) that would be
checked out using ansible-pull in a cron job. This was actually the
element of Puppet I miss most in Ansible: the overall structure and
control for regular running of the manifests against hosts. Ansible is
much more aimed at one-off or adhoc tasks, and if you want to schedule it
regularly, you’re left to patch your own solution together. (Ansible
creator Michael DeHaan apparently
doesn’t like the concept of ‘convergence’.)
In this case, I want regular runs of the tasks because there are some …
um … recurring issues whose reversion I want to enforce. (Yeah, I really
should get to the bottom of those but meh, the cobbler’s children have no
shoes.) Using ansible-pull does mean installing Ansible on each node, but
as there are only two this is a negligible overhead.

By the way, installing Ansible on legacy OpenIndiana releases is a little
complicated:

Install gcc-illumos, python-setuptools and pyyaml from the repository.

Use easy_install to install PIP.

Use PIP to install Ansible. It will fail while building pycrypto, but
you can manually fix this in the build tree:# pip install --no-clean ansible
Change to the /tmp/pip-build-* temporary directory.
Edit /usr/lib/python2.6/config/Makefile, change KPIC to fPIC.
Edit pycrypto setup.py, change ‘/usr/include/’ to ‘/usr/include/gmp’.# env CC=/opt/gcc/4.4.4/bin/gcc python ./setup.py install

Then rerun the Ansible pip install.

Incidentally, I’d still happily use Puppet-latest-release for a greenfield
deployment of a large number of fairly similar systems. But I’d be more
likely to reach for Ansible if I was in a hurry, if the scope was somewhat
open-ended or if the requirements were more limited or random. (The latter
applies here.)