deploying Python code with Puppet

I'm trying to implement a deployment system for my web application, based on Puppet.

The application consists of several services (a couple of web servers: Django- and Tornado-based and a worker based on Celery). They live in different git repositories, hosted on github.

I've used Chef for my previous projects. In case of Chef, deploying such thing would be easy: I'd just use git resource to checkout necessary code for this particular node, and set everything else up.

However, I don't understand how it's done in Puppet. I haven't found a git type in documentation. I've tried Googling it, but from what I found it seems that checking out and updating git code from Puppet is not a usual task.

Clearly, my assumed workflow is somewhat unusual for Puppet. I could try something else. What's the natural way to deploy such apps with Puppet?


Solution 1:

I'd use fabric to deploy Python code -- in fact, I do. But if all you want is the git stuff, here's an example from my puppet configurations using the vcsrepo module:

vcsrepo { '/var/www/gitorious':
    ensure   => present,
    owner    => 'git',
    source   => 'git://gitorious.org/gitorious/mainline.git',
    revision => 'v2.2.1',
    provider => git,
}   

Generally speaking, Puppet is not a good tool when you want things done in a tight time frame. Puppetlabs solution to these tasks is MCollective, which I have used and disliked.

Solution 2:

It's true that there is not native git resource type in Puppet, but I wouldn't call it an "unusual task".

There are a variety of solutions out there for implementing this yourself using define. We're using a git class that defines a git::repository resource type like this:

class git {
  define repository (
    $url,
    $workdir=undef,
    $branch=undef,
    $recursive=undef,
    $pull=true
  ) {
    if $workdir {
      $r_workdir = $workdir
    } else {
      $r_workdir = $name
    }

    if $branch {
      $branch_arg = "--branch $branch"
    }

    if $recursive {
      $recursive_arg = '--recursive'
    }

    exec { "clone-gitrepo-$name":
      creates => "$r_workdir",
      command => "/usr/bin/git clone $branch_arg $recursive_arg $url $r_workdir",
    }

    # This is here so other things can depend on
    # File[/path/to/working/directory].
    file { $r_workdir:
      ensure  => directory,
      require => Exec["clone-gitrepo-$name"],
    }

    if $pull {
      exec { "update-gitrepo-$name":
        require => Exec["clone-gitrepo-$name"],
        cwd     => "$r_workdir",
        command => '/usr/bin/git pull',
      }
    }
  }
}

We use it, for example, like this:

class openstack::controller::novnc {
  include git

  git::repository { '/opt/noVNC':
    url => 'git://github.com/cloudbuilders/noVNC.git',
  }
}

It performs a git pull operation every time Puppet runs, unless you set pull to false.

Note that I am not making any claims as to the correctness or robustness of this solution; it's what we're using and it works for us but there may be more feature-ful solutions out there.

You can find our code online here.