deploying Python code with Puppet

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.


The quick-and-dirty way is to use exec:

exec { 'install abcd':
  path    => ['/bin', '/usr/bin'],
  cwd     => '/usr/local',
  command => 'git clone http:/.../abcd',
  creates => '/usr/local/abcd',
}

It's also not difficult to create your own git resource, based on that:

define git ($package, $source) {
  exec {...}
}

However, I think that the clean way is to package all software you are using into packages (deb or yum or whatever your operating system uses), and upload it to the Puppet master. Then, when a server is being installed, it will find everything it needs on the Puppet master, rather than needing to connect to various git repositories (and pip repositories, and mercurial repositories, since if you start doing this trick for git, you'll do it for pip also). Then, installing will be way more reliable (one of the git/pip/hg connections could be temporarily down, or it might have moved), and will use less bandwidth, especially if you are installing your software on many servers. If you don't have time to spare to create packages, creating .tar.gz packages is an intermediate solution. Of course this also takes time, I know; I also use the quick-and-dirty way when I'm in a hurry.