Monday, August 29, 2011

Installing ant with puppet

Java and linux are not necessarily the best of bedfellows. Thats not exactly true as Java apps run great on linux, its more like Java packaging and linux packaging are not the best of bedfellows. Java apps and servers are not kept in the normal places that a linux person would like to see them in (and visa versa) and are generally not packaged as RPMs or debs or insert your favorite package manager here.
This is a hassle when trying to manage something through puppet. With puppet I would like to say install such and such package and be done with it; but because java stuff is not distributed as RPMs this means I had to roll my own. What follows is the strategy I took to manage ant and later applied to other java packages. One note before I go any further is I have started to look at the jpackage.org project. They didn't have a stable setup (at least as I read it but perhaps I am wrong) of ant 1.8, it was in their latest (6.0) repo which was labeled a work in progress. Your millage may vary.

The first thing I did was find a wonderful program called effing package manager. The fine people on the puppet IRC channel turned me on to this. This is a great little program for creating simple RPMs. It took me a bit to setup and install but follow the below instructions and it hopfully should work. This was done on a fresh cloud setup of CentOS 5.6 from Rackspace.

At a high level the setup is an extremely simplified and tailored RPM of ant. This RPM is published and then distributed through an internal yum server. Puppet is then used to install the package and create some symbolic links. The sym links are there so I could switch between the different ant versions as well but they are not really necessary. The final directory structure looks something like this (adding in an old version of ant for clarity).
/usr/ant/ant1.6.5
/usr/ant/apache-ant-1.8.2
/usr/ant/default --> sym linked to --> /usr/ant/apache-ant-1.8.2 (for example)
/usr/bin --> sym linked to --> /usr/ant/default/bin/ant

Step one, is to get a machine setup with effing package manager to create the simplified ant rpm.
yum install rpm-build make gcc ruby-devel
gem install fpm
Next download ant from apache and unpack it to /usr/ant/apache-ant-1.8.2, or wherever you want it to be. Note this is written for ant 1.8.2, but it should work for any version of ant just modify accordingly. This will be the directory that your created RPM will install it to.
Note I prefix ant with "my". Replace my if you want it named something else, the important thing is that it is distinguished from "ant" as this package does exist in some yum repos and you want to be able to be clear what you are installing.
mkdir /usr/ant
cd /usr/ant
wget http://www.apache.org/dist/ant/binaries/apache-ant-1.8.2-bin.tar.gz
gunzip apache-ant-1.8.2-bin.tar.gz
tar -xvf apache-ant-1.8.2-bin.tar
fpm -s dir -t rpm -n myant -v 1.8.2.1 -a noarch /usr/ant/apache-ant-1.8.2

Note, I used the ant version number plus an extra point release for the RPM version so that in case I need to change something in my packaging I can increment that last number.

Next setup a new puppet module for ant. The only thing in it is a manifests directory and an init.pp file containing:
class ant {
package {'myant-1.8.2': ensure => installed, alias => "ant"}

file { "/usr/ant/default":
ensure => link,
target => "/usr/ant/apache-ant-1.8.2/bin/ant",
require => Package['myant-1.8.2']
}

file { "/usr/bin/ant":
ensure => link,
target => "/usr/ant/default/bin/ant",
require => Package['myant-1.8.2']
}
}
Next you have to put your RPM up on a yum repo site somewhere. I have been using puppet to manage my yum repo as well so I can move it between environments, this has proven to be very handy. Finally add ant to your class or classes:
include ant
And that's all there is to it.