Intro

So, a little bit of research and I came across squashfs, which seems like a pretty cool way to distribute applications. Imagine building an image that you can mount and run the application on knowing that it would not be altered after the fact. Sounds good to me!

Getting started

Assuming that you have dreadnot up and running, and that you are on ubuntu we have a few prerequisites to install.

sudo apt-get update
sudo apt-get -yq install squashfs-tools

That will get you the tools you need to create the images.

Try it manually

If you want to create an image manually, run:

mksquashfs ~/ /tmp/my_home.squashed

After it is finished, you will have a mountable backup of your home directory. If you want to see what is inside, try:

sudo mount /tmp/my_home.squashed /mnt -t squashfs -o loop
cd /mnt
ls -lah

Behold! Your home directory!

Make it work in dreadnot

One button creation of the image? Okay, no problem!

Create and wire-up a build file similar to:

var exec = require('child_process').exec;

var async = require('async');
var mkdirp = require('mkdirp');
var misc = require('util/misc');
var sprintf = require('util/sprintf');
var git = require('util/git');


exports.get_deployedRevision = function(args, callback) {
  git.revParse(this.config.tapkick_dir, 'HEAD', function(err, stdout) {
    callback(null, stdout.replace(/^\s+|\s+$/g, ''));
  });
};


exports.task_deploy = function(stack, baton, args, callback) {
  var opts = { cwd: stack.config.tapkick_dir, env: process.env };

  async.series([
    function mksquashfs(callback) {
      misc.taskSpawn(baton, args, ['mksquashfs', '/tmp/' + args.revision, '/opt/dreadnot/out/' + args.revision + '.sqfs'], opts, callback);
    }
  ], callback);
};

exports.task_preDeploy = function(stack, baton, args, callback) {
  var opts = { cwd: stack.config.tapkick_dir, env: process.env };

  async.series([
    function fetch(callback) {
      misc.taskSpawn(baton, args, ['git', 'fetch'], opts, callback);
    },

    function checkout(callback) {
      misc.taskSpawn(baton, args, ['git', 'checkout', args.revision], opts, callback);
    },

    function mkdir(callback) {
      mkdirp('/tmp/' + args.revision, callback);
    },

    function createArchive(callback) {
      misc.taskSpawn(baton, args, ['git', 'archive', 'master', '-o', '/tmp/' + args.revision + '.tar'], opts, callback);
    },

    function extractArchive(callback) {
      misc.taskSpawn(baton, args, ['tar', '-xvf', '/tmp/' + args.revision + '.tar', '-C', '/tmp/' + args.revision ], opts, callback);
    },

    function npmInstall(callback) {
      misc.taskSpawn(baton, args, ['npm', 'install' ], opts, callback);
    }
  ], callback);
};

exports.task_postDeploy = function(stack, baton, args, callback) {
  var opts = { cwd: stack.config.tapkick_dir, env: process.env };
  async.series([], callback);
};

exports.targets = {
  'deploy': [
    'task_preDeploy',
    'task_deploy',
    'task_postDeploy',
  ]
};

This will archive all the files out the git repository, to an npm install to make sure all the dependecies are there and then create the file system and copy it to a semi-central location.

There are quite a few things that can optimize this script, but I’ll leave that up as an exercise for the reader.



Published

13 April 2012

Category

devops

Tags