Deploying JIRA in the Enterprise – Part 2 – Packaging using the RPM Maven Plugin

Following on from my last post, this is Part 2, focusing on Packaging using the RPM Maven Plugin.

rpm-packaging

Firstly, why am I using RPM packages? There are many solutions for packaging and deploying applications using other tools. Every environment is going to be different and a decision will be based on the OS platform, standards and policies within your organisation, the infrastructure team, the knowledge and use of particular tools and processes. RPM is just one solution and it is your environment that will dictate the best choice.

The main driver for me has been the infrastructure environment. This is not just about using Red Hat Linux – it is also driven by what the Linux infrastructure teams are using or what they want you to use or are happy for you to use. In my case at my previous company, RPM’s were the standard for deploying applications on Linux infrastructure. We were encouraged to comply to the standard as best we could to ensure the Linux infrastructure team could better support our application. Once I had experience using this method, it was easier to reuse in other companies who were happy to support the method.

If you haven’t had any experience with RPM packages, there are plenty of resources online that will guide you through the basics. The Maximum RPM online book provides a good overview. Building RPM packages can seem daunting and many application teams at my previous company were using the RPM Maven Plugin to generate the RPM packages. It does simplify the configuration of the RPM build and integrate nicely into the release process if you are already using Maven.

Lets have a look at what the package will actually be doing:

  • Create the directory structure
  • Copy files to the directory structure
  • Set file and directory permissions
  • Add any symbolic links
  • Run any pre/post/clean/verify installation scripts.

The RPM Maven Plugin can do much more but I will just go over the general setup in this post and some small enhancements that I have added.

What are we going to put into the package? In our case, we package everything that we need to deploy the application except for the environment-specific configuration.  This includes:

  • The application package from Atlassian (standalone tar.gz version)
  • The edited files to the application package (email templates, additional libraries, configuration)
  • Plugin JAR files
  • Control scripts (cluster and init.d)
  • Optional dependencies like JDK and Apache (could also be managed via the dependency configuration)

These files and directories are placed in the build directory and stored in Subversion. You can use any other configuration management or source code management tool to store the files or directories as well. You could also use a file share or any other storage but it is better to have each package version controlled.

directory-structure

For those who are not familiar with Maven, the pom.xml (POM) file contains the configuration details to build a project and in our case the RPM package. Each of the above packaging details are specified in the POM file.

Firstly, we setup the standard POM variables and custom properties for use within the configuration definition.

...
<groupId>company.jira.packages</groupId>
<artifactId>company-jira-foo</artifactId>
<version>6.1.3</version>
<packaging>pom</packaging>
<name>company-jira-foo</name>
<url>http://www.company.com/company-jira-foo</url>
<properties>
<project.shortname>jira-foo</project.shortname>
</properties>
...

Next we need to add the start of the RPM Maven Plugin plugin configuration.

...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>rpm-maven-plugin</artifactId>
<version>2.1-alpha-1</version>
<executions>
<execution>
<goals>
<goal>rpm</goal>
</goals>
</execution>
</executions>
<configuration>
<version>${project.version}</version></pre>
<group>Application/System</group>
<copyright>COMPANY</copyright>
...

We have the RPM Maven Plugin initialised and we can first create the directory structure for the deployment. Here is an example of some directories that I create but note this is following a standard directory layout for the company where I work – it will vary depending on the standards that apply to your environment:

  • /apps/jira-foo
  • /apps/jira-foo/company-jira-foo (for the webapp)
  • /apps/jira-foo/scripts
  • /apps/jira-foo/logs
  • /apps/jira-foo/jira-home
  • /apps/jira-foo/plugins/installed-plugins

If the directory already exists then the package will not overwrite the directory. This is important, for example, the log files where you want to keep history in a production environment or jira-home where you want to keep your indexes, data and other files. We will cover cleaning the environment before installation in a later post.

We can then create the directories in the POM file.

...
<!-- Apps Root Directory -->
<mapping>
<directory>/apps/${project.shortname}</directory>
<filemode>755</filemode>
<username>apsadm</username>
<groupname>apsadm</groupname>
</mapping>
<!-- Web Application Directory -->
<mapping>
<directory>/apps/${project.shortname}/${project.artifactId}</directory>
<filemode>755</filemode>
<username>jirauser</username>
<groupname>jirauser</groupname>
</mapping>
...

We then define mapping the folders in the package to the structure we created.

  • edit-webapp -> /apps/jira-foo/company-jira-foo
  • webapp -> /apps/jira-foo/company-jira-foo
  • scripts -> /apps/jira-foo/scripts
  • plugins -> /apps/jira-foo/jira-home/plugins/installed-plugins

Note, that the edit-webapp is defined before the webapp but that mapping takes priority and overwrites the webapp mapping.

...
<!-- Mapping edit-webapp Files -->
<mapping>
<directory>/apps/${project.shortname}/${project.artifactId}</directory>
<directoryIncluded>false</directoryIncluded>
<recurseDirectories>true</recurseDirectories>
<filemode>755</filemode>
<username>jirauser</username>
<groupname>jirauser</groupname>
<sources>
<source>
<location>edit-webapp</location>
</source>
</sources>
</mapping>
<!-- Mapping webapp Files -->
<mapping>
<directory>/apps/${project.shortname}/${project.artifactId}</directory>
<directoryIncluded>false</directoryIncluded>
<recurseDirectories>true</recurseDirectories>
<filemode>755</filemode>
<username>jirauser</username>
<groupname>jirauser</groupname>
<sources>
<source>
<location>webapp</location>
</source>
</sources>
</mapping>
...

Finally, we add our symbolic links. One example is that we have a symbolic link called webapp to our webapp directory. This enables us to easily create scripts that work for all our applications and don’t need to be updated per application.

  • webapp -> /apps/jira-foo/company-jira-foo
...
<!-- Symbolic Links -->
<mapping>
<directory>/apps/${project.shortname}/live</directory>
<username>jirauser</username>
<groupname>jirauser</groupname>
<sources>
<softlinkSource>
<location>/apps/${project.shortname}/${project.artifactId}</location>
</softlinkSource>
</sources>
</mapping>
...

This is just the basic features of the RPM Maven Plugin to build your package. I have uploaded an example POM file here with all the features that I covered.

There are many features of the RPM Maven Plugin that you can use to customise your package. There are further details available here. Also I use other maven plugins such as the Build Number Maven Plugin to add build numbers to the end of the rpms and the Exec Maven Plugin to run some cleaning scripts on the build directory. The full process can be easily customised to meet your requirements.

Once you have your POM file setup and added your package contents to the build directory, you are ready to build your package. Ofcourse Maven is a prerequisite – I am not going to go into the details in this post. And another important prerequisite is the rpm-build package. It should be installed and configured so that the user executing the build has permission to execute the rpmbuild command (usually requires privileged/sudo access). There are usage details for the RPM Maven Plugin here but in general when the RPM is the primary artifact for the project such as in the example, you can use the command:

mvn package

In my current environment, the build takes around 5-10 minutes. It might take a little longer if you add additional dependencies or files in your package. You will notice that the plugin creates a target directory for all the build files. The rpm file itself will be placed in this directory structure if the build was successful – usually somewhere under target/rpm/company-jira-foo/RPMS/ .

There can be many things that can go wrong with the rpmbuild and/or with Maven. Again, I wont go into detail here but if you want to give this a try and come across some issues, please feel free to ask, I may have resolved a similar issue in the past.

For Part 3, I will go into the Configuration stored in Subversion and how to bring the whole process together with the Deployment Method using Bamboo.

the jira guy

Standard

One thought on “Deploying JIRA in the Enterprise – Part 2 – Packaging using the RPM Maven Plugin

Leave a comment