Snooze Deployment Tool

Snooze is a deployment tool written in Java (although not pure Java) that can be used to deploy projects to multiple servers using SSH and Subversion.

A common case for this is to deploy website code to multiple webservers.

Download

Snooze 1.2snooze-1.2.zipDownload
Snooze 1.2 Sourcesnooze-1.2-src.zipDownload

Convensions

The assumption is made that a number of conventions are followed, which can be further extended with configuration on a per project basis.

This document describes the usage of release branches, this behaviour however can be disabled by setting the configuration option release-branches to false. By disabling release branches, tags are created directly from the development branch (trunk).

Authentication

Snooze makes the assumption that SSH keys are setup to allow password-less logins to the deployment servers and to subversion.

Subversion

Projects are maintained within subversion with the following layout.

Main development/<repository>/<project>/trunk
Development branches/<repository>/<project>/branches/<branch>
Release branches/<repository>/<project>/branches/releases/<version>
Release tags/<repository>/<project>/tags/<version>

Deployment locations

Projects are deployed to one or more servers with the following mirrored layout. For a webserver the active directory (or subdirectory within) would be configured to be the document root.

The active directory provides a default layout, however this can be changed with configuration to provide one or more deployment locations per project.

Live directory/<deployment root>/<project>/active
Switching directory/<deployment root>/<project>/spare

Deployment lifecycle

Deploying new features to production.

Deploying bug fixes to production.

Tasks

Snooze is comprised as a collection of tasks. The following core tasks are used to perform the above deployment lifecycle.

The help task "./bin/release help" or "./bin/release help <task>" can be run to view further details.

Configuration

Configuration is maintained within the file ./etc/conf.xml. An example configuration is shown below.

<?xml version="1.0" encoding="UTF-8" ?>
<release>

	<config>
		<!--
		The user to login with on the deployment servers, 
		SSH keys should be set up to allow password-less logins.
		-->
		<remote-user>www</remote-user>
		
		<!--
		Use releases branches.
		If true, versioned release branches are created from trunk and tags 
		from release branches. If false or omitted, tags are created from trunk.
		-->
		<release-branches>true</release-branches>
	</config>

	<!-- A list of server names against IP addresses or hostnames -->
	<servers>
		<server>
			<name>web-1</name>
			<host>1.2.3.4</host>
		</server>
		<server>
			<name>web-2</name>
			<host>2.3.4.5</host>
		</server>
		<server>
			<name>test-web-1</name>
			<host>1.1.1.1</host>
		</server>
	</servers>

	<!-- 
	A logical grouping of servers,
	it is acceptable for a server to exist in multiple groups
	-->
	<clusters>
		<cluster name="prod" layout="prod">
			<server>web-1</server>
			<server>web-2</server>
		</cluster>
		<cluster name="stage" layout="stage">
			<server>test-web-1</server>
		</cluster>
	</clusters>

	<!-- A list of svn repository names against base paths -->
	<repos>
		<repo>
			<name>websites</name>
			<base>svn+ssh://localhost/svn</base>
		</repo>
	</repos>

	<!-- A list of deployment path names against base paths -->
	<deploy-paths>
		<deploy-path>
			<name>varwww</name>
			<base>/var/www</base>
		</deploy-path>
	</deploy-paths>

	<!--
	A list of possible directories that can be deployed to under each project 
	deployment directory, this allows for multiple deployments per project. 
	Each layout is applied to a cluster using the cluster layout attribute and 
	if omitted, "active" is always used.
	-->
	<deploy-layouts>
		<layout name="prod">
			<dir>active</dir>
		</layout>
		<layout name="stage">
			<dir>slot1</dir>
			<dir>slot2</dir>
			<dir>slot3</dir>
		</layout>
	</deploy-layouts>

	<!--
	Project configuration, mapping to subversion repository, 
	deployment directory and environments to deployment servers
	-->
	<projects>

		<project>
			<!--
			The svn path is svn+ssh://localhost/svn/my-project
			The deployment directory is /var/www/my-project
			Deploying to the stage environment deploys to servers: test-web-1
			Deploying to the prod environment deploys to servers: web-1, web-2
			-->
			<name>my-project</name>
			<repo>websites</repo>
			<deploy>varwww</deploy>
			<envs>
				<env name="stage">stage</env>
				<env name="prod">prod</env>
			</envs>
		</project>

		<project>
			<!--
			The svn path is svn+ssh://localhost/svn/foo/your-project
			The deployment directory is /var/www/foo/your-project
			Deploying to the foo-stage environment deploys to servers: test-web-1
			Deploying to the foo-prod environment deploys to servers: web-1, web-2
			-->
			<name>your-project</name>
			<repo>websites</repo>
			<deploy>varwww</deploy>
			<repo-path>/foo/your-project</repo-path>
			<deploy-path>/foo/your-project</deploy-path>

			<envs>
				<env name="foo-stage">stage</env>
				<env name="foo-prod">prod</env>
			</envs>

			<!--
			A list of paths relative to the project in which svn:externals should 
			be fixed to the current revision when creating a release branch.
			-->
			<externals>
				<external>plugins</external>
			</externals>

			<!--
			Commands to run pre and post switch,
			Either absolute, or relative to the switching directory
			-->
			<pre-switch>bin/pre-switch</pre-switch>
			<post-switch>bin/post-switch</post-switch>

			<!--
			Commands to run pre and post deploy,
			Either absolute, or relative to the live directory
			-->
			<pre-deploy>bin/pre-deploy</pre-deploy>
			<post-deploy>bin/post-deploy</post-deploy>
		</project>

	</projects>

	<!--
	Additional remote commands, each command has the following attributes,

	buffer [true|false] (default false)
		Whether to buffer the commands output before displaying it to the
		terminal or flush per line.
	parallel [true|false] (default true)
		Whether to run the commands in parallel or sequentially
		across machines.
	-->
	<remote-commands>
		<command buffer="true" parallel="true">
			<name>uptime</name>
			<exec>/usr/bin/uptime</exec>
		</command>
		<command buffer="true" parallel="true">
			<name>ps</name>
			<exec>/bin/ps aux</exec>
		</command>
	</remote-commands>

</release>

Examples

Using the above configuration the following commands can be run to perform deployment tasks.

# Run Snooze interactively
./bin/release -i

# List projects snooze is aware of
> projects

# Create a release branch of the my-project project
# The version is auto incremented from the previous branch unless stated
> branch my-project

# Switch the switching directory for the my-project project on the testing
# environment to prepare for deployment of branch 1.0.0
> switch my-project stage branch 1.0.0

# Deploy the switching directory to the live directory on the testing environment
> deploy my-project stage

# Create a tag from the release branch
# The tag version is taken from the latest release branch version unless stated
> tag my-project

# Switch the switching directory for the my-project project on the production
# environment to prepare for deployment of tag 1.0.0
> switch my-project prod tag 1.0.0

# Deploy the switching directory to the live directory on the production environment
> deploy my-project prod

# Check uptime for all the servers for the my-project project
# on the production environment
> uptime my-project prod

# List projects snooze is aware of, running non-interactively
./bin/release projects

Open Source

Snooze makes use of the following open source libraries, any changes made will be listed here for download.

License

© Copyright 2010, 2012 Bedican Solutions

Redistribution and use of this software in source and binary forms, with or without modification, are permitted providing the following conditions are met:

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.