flintlock
flintlock is a simple application deployer inspired by Heroku's buildpacks.
At its core, it's a simple scripting API which allows developers/ops the ability
to create re-usable application deployments. In flintlock, these deployments
are called "modules".
Installation
The latest release of flintlock will be published to rubygems.org. To install,
just run:
$ gem install flintlockIf you're running on a RHEL/CentOS 6 machine (or derivative), you might be able to
make use of the flintlock RPM spec file located in the git repository
(flintlock.spec) to build RPM packages. Assuming all of the dependencies are
installed, this should just be a matter of running:
$ rpmbuild -ba flintlock.spec --define "scl ruby193"Tutorial
Let's deploy a sample redis module I've written. This tutorial assumes you
are running on a CentOS 6 machine with access to the EPEL package repository.
You'll also need git.
After installing flintlock, run the following:
flintlock deploy git://github.com/jcmcken/flintlock-redis.git /some/empty/directoryIn this case, the deploy command will recognize that you want to deploy from git.
It will clone the remote repository, stage it, and then begin deploying the necessary
files and directories to /some/empty/directory. Let's see what happens:
$ flintlock deploy git://github.com/jcmcken/flintlock-redis.git /some/empty/directory
run fetching module
run detecting compatibility
info deploying jcmcken/redis (0.0.1) to '/some/empty/directory'
create creating deploy directory
run installing and configuring dependencies
create staging application files
run launching the application
run altering application runtime environment
info complete!
$Assuming the module was written well enough, these messages should indicate that our
redis server is running. Let's verify:
$ ps -ef | grep redis
jcmcken 24846 1 0 17:41 ? 00:00:00 /usr/sbin/redis-server /some/empty/directory/etc/redis.conf
jcmcken 24865 19343 0 17:41 pts/1 00:00:00 grep redisLet's take a look at the deploy directory, /some/empty/directory:
$ tree /some/empty/directory
/some/empty/directory
|-- bin
| `-- redis
|-- data
|-- etc
| `-- redis.conf
|-- log
| |-- redis.log
| |-- stderr.log
| `-- stdout.log
`-- run
`-- redis.pidYou'll notice that everything for this redis server is self-contained within our deploy
directory. This is a central tenet of flintlock:
An application deployment is always self-contained within a single directory
How well an application adheres to this philosophy depends on the application. For instance,
some applications may not have configurable /tmp directories. For transient data, this
is usually acceptable. But all of the important files should really be located together.
Supported Formats
Currently flintlock can install modules from a number of sources:
- From a local directory
- From a local tarball (
tarortar.gz) - Over
gitsupported protocols (git://..) - Over
svnsupported protocols (svn://...) -
tarortar.gzoverhttp/https
Attempting to install any other way will throw an error message similar to the following:
run fetching module
error don't know how to download 'https://github.com'!Writing a Module
Introduction
flintlock modules are simply a bunch of scripts which follow a certain convention.
At its heart, a module has the following minimal layout:
sample-app-1
|-- bin
| |-- defaults
| |-- detect
| |-- modify
| |-- prepare
| |-- stage
| |-- start
| `-- stop
`-- metadata.json
Running flintlock new in an empty directory of your choosing will automatically
generate this structure.
The top-level directory (in this case, sample-app-1) can be called anything.
The files under bin are executable scripts (using any language you care to
use). More on these later.
The metadata.json file contains metadata about the module. This metadata looks as follows:
{
"author": "jcmcken",
"name": "sample-app-1",
"version": "0.0.1"
}All three keys (author, name, version) are required, but can be any value
(as long as they're not the empty string). These metadata are merely used to namespace
the module.
flintlock developers can choose to include more files in their modules if needed.
Stages
flintlock has different "stages" of execution that occur in a specific order every time
you run a deployment.
These stages correspond directly to the scripts under bin/.
The most important stages, and their purpose, are as follows. (The stages occur in the order listed below)
-
detect: Detect whether the module is compatible with the current host. -
prepare: Install or compile any required dependencies. This script takes no arguments. -
stage: Stage the application directories and files. This script takes a single argument, which is the directory where your app will be deployed. This directory need not exist, but if it does, it must be empty. -
start: Start the application. This script takes the same argument passed tostage. -
modify: Once the application is started, perform some runtime modifications. For instance, if you've just started a MySQL server, you may want to remove the default tables or add a password to the database superuser. This script takes the same argument passed tostageandstart.
The API between these scripts and flintlock is as follows:
- If the script exits with a return code of
0,flintlockwill think that the script succeeded. - If the script exits with a return code of
1,flintlockwill think that the script has failed. - Any other return code, and
flintlockwill think that some sort of internal error has occurred. In other words, something outside of the script's control failed.
When flintlock encounters a non-zero exit code, it will halt execution and display an
error.
Configuration Defaults
A flintlock module may also choose to utilize the bin/defaults script to set
configuration defaults.
By default, flintlock will source this script prior to executing any of the other
stages.
A user can choose to override these defaults at the command line. For example, if your
defaults script looks like:
PORT=80The user can override this at the command line by running:
PORT=8080 flintlock deploy <module> <deploy_dir>flintlock will transparently override the default PORT with the env var passed at the
command line.
Examples
Some example flintlock modules can be found @ the following locations: