Ansible role for SonarQube upgrades

Published
by
Priit Liivak
in
Ansible, Development

You probably know and hopefully have used SonarQube. It’s a great tool that is actively evolving and improving. This is great if you are a developer using SonarQube. However, if you happen to administer SonarQube instance, the constant upgrades are quite a hassle since upgrade guide consists of 11 steps.

  1. Stop the old SonarQube server
  2. Download and unzip the new SonarQube distribution in a fresh directory, let’s say NEW_SONARQUBE_HOME
  3. Start it using the default H2 database and use the update centre to install the plugins you need
  4. Manually install any custom plugins
  5. Stop the new server
  6. Update the content of the sonar.properties and wrapper.conf files located in the NEW_SONARQUBE_HOME/conf directory with the content of the related files in the OLD_SONARQUBE_HOME/conf directory (web server URL, database settings, etc.). Do not copy-paste the old files
  7. If a custom JDBC driver is used, copy it into NEW_SONARQUBE_HOME/extensions/jdbc-driver/<dialect>
  8. Back up your database
  9. Remove the data/es directory
  10. Start the new web server
  11. Copy http://localhost:9000/setup (replace “localhost:9000” by your own URL) to browser and follow the setup instructions

This was way too much steps to execute manually. So I decided to automate it by writing an Ansible role for it.

Initial set-up

Before I started writing Ansible playbook, I needed to find a way to test my code. So I started off with Vagrant spinning up a virtual machine and provisioning it with simple script. This was needed to have similar environment to our actual SonarQube production instance. I was able to incrementally build my Ansible playbook and test it on this VM. Rather soon I learned that working with Vagrant is slowing me down since I needed to reset the environment more than initially expected. So I decided to consider Docker.

Docker for testing

I found the official SonarQube Docker image, but was unable to use that since our SonarQube instance is installed on CentOS and the official image used different base image. Also, I needed to customize the specific SonarQube version I wanted to start with. So I created our own Dockerfile with CentOS 6 base and Ansible installed.

This Docker image didn’t need to start SonarQube since I just wanted to verify that proper file changes are made and my Ansible playbook has no errors. One of the first steps of upgrade is shutting down the server anyway.

I mounted my playbook as volume to the container and ran Ansible within that container applying changes to that local environment.

#!/bin/bash

# Path of current script
TESTS_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" &amp;&amp; pwd )

# Command to test playbook with
TEST_COMMAND="cd /playbooks &amp;&amp; ansible-playbook $@ 
              -i 'localhost,' -c local 
              upgrade-sonar.yml"

# Run container mounting playbooks as volume
docker run -v "$TESTS_DIR/../playbooks/:/playbooks" 
              'sonar-upgrade-test' /bin/bash -c "${TEST_COMMAND}"

Running my playbook inside Docker decreased the feedback loop significantly so I decided that Docker was the way to go. You can take a look all my scripts in GitHub

Ansible Role

Moving forward step by step I reached a point where everything seemed to be working and I had a very useful Ansible role at my hands. It is not yet published to Ansible Galaxy, but you can find the source and documentation in GitHub under SonarQube upgrade Ansible role project.

Current Ansible role upgrades SonarQube by creating new installation next to current one. This provides means to rollback, if needed.

At the moment the role performs the following tasks:

  1. Ensures that specific non-root user exists for Sonar installation
  2. Creates sonar.sh in the directory where all installations reside
  3. Ensures that SonarQube service is present
  4. Stops SonarQube
  5. Downloads new version
  6. Backs up the database
  7. Downloads and installs plugins
  8. Applys custom configuration to new instance
  9. Ensures data/es is deleted
  10. Reconfigures SonarQube service to start new version
  11. Starts SonarQube

Manual steps

Still the process requires a couple manual steps.

Before running the upgrade playbook you should manually ensure that the plugins list that will be installed during upgrade is up to date. You could get the latest supported version numbers from administration view of SonarQube.

As recommended by SonarQube, this Ansible role does not just copy configuration from previous installation, but uses template with variables to create configuration for new instance. This means that before executing upgrade, a developer could compare the template and base configuration from new SonarQube download. Although this is a manual step, it’s easier compared to how it was done before, because the comparison can be done using IDE not just diff tool from command line.

Both of these steps need follow-up manual upgrade as well and I consider these upgrade preparation activities. I managed to simplify and decrease the upgrade process from initial 11 steps to the following 3:

  1. Set new version in playbook
  2. Run playbook for Sonar server
  3. Copy  http://localhost:9000/setup (replace “localhost:9000” by your own URL) to browser and follow the setup instructions

Improvements

Current configuration expects that SonarQube is configured to use MySQL.  Adding additional database engines seems to be an easy improvement.

Atlassian Crowd is configured to be an authentication provider. This could simply be omitted in template if appropriate variable values are missing.

There are more configuration files, just sonar.properties that should all be configured to be loaded from outside of the role.

So contributions are highly welcome and if SonarQube keeps up its release pace then we’ll probably add some ourselves.