06 November 2009

Building puppet and facter RPMs for CentOS or RHEL

In the first part of his excellent Puppet tutorial, John Arundel suggests that, given the speed with which Puppet develops and changes, and to keep things simple, Puppet should be installed from source. While for one box, this may be true, I tend to the view that you should use the native package manager wherever possible. In the case of CentOS or Redhat (the most common platforms for Puppet users, our survey says) , this means building RPMs. This article shows you how to build reusable puppet and facter RPMs, to make your life easier when you graduate from managing puppet on one server, to controlling a whole datacentre.

Set up an rpmbuilding environment

There are two things to consider here. Firstly, it’s not considered good practice to build RPMs as root, and secondly, RPM by default will place built RPMs in /usr/src/redhat. For this reason, it’s a good idea to create a dedicated user, and an area for building packages.

# useradd -m rpmbuilder
# su - rpmbuilder
$ for dir in RPMS SRPMS SPECS SOURCES BUILD; do mkdir -p redhat/$dir; done
$ mkdir redhat/RPMS/noarch
$ mkdir redhat/RPMS/x86_64
$ for x in 3 4 5 6; do mkdir redhat/RPMS/i$x\86; done
$ echo "%_topdir /home/rpmbuilder/redhat" > .rpmmacros

Get the facter and puppet sources

$ cd redhat/SOURCES
$ wget http://reductivelabs.com/downloads/puppet/puppet-0.25.1.tar.gz
$ wget http://reductivelabs.com/downloads/facter/facter-1.5.7.tar.gz

Stage the spec files and any patches

The heart of the RPM building process is the spec (short for specification) file. This is a text file which provides instructions to the rpmbuild command on exactly how to build the package. This includes names, versions, compile options, dependency information and any other information you might like to know.

Both facter and puppet tarballs ship with spec files for building RPMs - we need to get them and put them in the SPECS directory.

$ tar xzvf puppet-0.25.1.tar.gz
$ tar xzvf facter-1.5.7.tar.gz

The spec files live under the conf/redhat directory. At the time of writing, you would type:

$ cp facter-1.5.7/conf/redhat/puppet.spec ../SPECS
$ cp puppet-0.25.1/conf/redhat/puppet.spec ../SPECS

It’s a principle of RPM development that we always use pristine sources. However, sometimes, usually for distrubution-specific reasons, we need to apply a patch to the pristine code. The spec file will contain details of whether this is needed.

Check if there are any patches required:

$ grep ^Patch ../SPECS/facter.spec
$ grep ^Patch ../SPECS/puppet.spec
Patch0:         rundir-perms.patch
$ find . -name rundir-perms.patch | grep redhat
./puppet-0.25.1/conf/redhat/rundir-perms.patch

The patch file needs to be placed in the SOURCES directory, alongside the pristine source tarball.

$ cp ./puppet-0.25.1/conf/redhat/rundir-perms.patch .

At the time of writing, the facter spec file is out of date - the version number is for an old version. You can verify this:

$ grep ^Version ../SPECS/facter.spec
Version: 1.5.5

We need to up this to 1.5.7:

$ sed -i '/^Version/s/\.5\.5/\.5\.7/' ../SPECS/facter.spec

Strictly speaking, we should also make an addition to the changelog. If you feel so inclined, open the file in an editor, and find the %changelog section, and add an entry a bit like this:

* Fri Nov 6 2009 Stephen Nelson-Smith <me@sekrit.com> - 1.5.7
- Update to 1.5.7 

Save the file, and we’re done.

Make sure we have the requirements

In order to build an RPM we need to be sure we have the prerequiste tools and libraries availale on our system. For something as small and simple as puppet and facter, this is trivial. If you start building bigger packages, with dependencies that in turn have dependencies, you’re probably going to find benefit from using Mock - the RPM building tool used by the CentOS project to maingtain the entire repository.

$ grep ^BuildRequires ../SPECS/facter.spec
BuildRequires: ruby >= 1.8.1
$ grep ^BuildRequires ../SPECS/puppet.spec
BuildRequires:  facter >= 1.5
BuildRequires:  ruby >= 1.8.1
$ rpm -q ruby
ruby-1.8.5-5.el5_1.1

OK, we’re going to have to build facter, then install it so we can build puppet.

Build facter

$ cd ../SPECS
$ rpmbuild -bb facter.spec

Look for the line that says something like:

Wrote: /home/rpmbuilder/redhat/RPMS/x86_64/facter-1.5.7-1.x86_64.rpm

Now, become root, and install facter:

# rpm -Uvh /home/rpmbuilder/redhat/RPMS/x86_64/facter-1.5.7-1.x86_64.rpm

Build puppet

# su - rpmbuilder
$ cd redhat/SPECS
$ rpmbuild -bb puppet.spec

You should see something like:

Wrote: /home/rpmbuilder/redhat/RPMS/x86_64/puppet-0.25.1-1.x86_64.rpm
Wrote: /home/rpmbuilder/redhat/RPMS/x86_64/puppet-server-0.25.1-1.x86_64.rpm

NB when you come to install these rpms, you also need augeas-libs and ruby-augeas. Both of these are available in EPEL. This is a new dependency since 0.25.x.

Congratulations, you’ve built facter and puppet rpms, which you can now distrubute across your envirionment.