# How to deploy applications (in .tar.gz) with Puppet?

I'm a beginner with Puppet and I would like to know if I'm on the right way to deploy applications with Puppet.

The applciations are in a tar.gz file which contains a file with the version number. So, I do this to deploy (I go on the server and do a client restart to pick up the new tarball):

nodes.pp

node 'server1.domain.com' inherits basenode {
apps { apps:
version => 56,
apps_name => "apps_tarball.tgz",
}

init.pp (modules)

exec {"apps_wget":
command => "/usr/bin/wget http://web_server/${version}-${apps_name} -O /tmp/${container_zip_name}", unless => "test -f /tmp/${version}-${apps_name}", require => [ Package["wget"] ], } exec {"apps_unzip": cwd => "/usr/local/apps/path", command => "/usr/bin/unzip /tmp/${version}-${apps_name}", unless => "test -f /usr/local/apps/path/apps-version-${version}",
require => [ Package["unzip"], Exec["container_wget"] ],
}


But, when I want to upgrade, I don't know to say Puppet to delete the old directory? For example, If I want to upgrade version 56 to 57: I must delete the 56's version directory.

I heard about Capristrano and it seems to be better to use Puppet for managinig packages, config files and using Capristrano to deploy apps, isn't it?

Thanks.

-
I use the module forge.puppetlabs.com to manage downloading/decompressing/placing things which are only available as tarballs. It works great. –  Jon Johnson Feb 24 '14 at 18:02

I would like to know if I'm on the right way to deploy applications with Puppet.

No, you are not.

You should use the package management available on your operating system. If your software is in tar.gz format, you should re-package it locally as .deb, .rpm or whatever.

If the software is something developed locally, you should use whatever build/deploy tools are available for it.

-
In a perfect world, admins will take the time to create packages from tarballs. In the real world, my experience has shown this does not happen. Our clients install many applications, sometimes very large applications, from tarballs and have no intention of changing this. –  EmmEff Jan 14 at 18:34
@EmmEff That's not a difference between perfect world and real world. That's a difference between "We are stuck to old ways and not ready for automatic configuration management" places and places where configuration management does work. I have seen both -- and even seen the latter turn into the former with a change of admins. –  Daniel C. Sobral Jan 23 at 3:54

You might want to try using fpm to make RPMs or DEBs of your tarballs; it's really simple to use, and you don't have to understand anything about the package formats you don't want to.

To answer your original question, the right way to deploy applications with Puppet is to make Puppet do as little work as possible; any complicated exec resources that download and extract tarballs are bound to be very, very brittle, and making Puppet just yum install a package is much healthier long-run.

-
I knew what I was doing was so very wrong. But rpm building has always scared me away. fpm is my salvation. Thank you Handyman5. f-yeah. –  8None1 Jan 7 '14 at 4:50

I would try very hard to bundle up the app as an RPM or .deb package and build a yum or apt repository to hold the packages. The packaging up of a tarball or zip that you're just opening up into a directory is pretty easy (but should be a separate question). The packaging available that way tracks versions nicely and handles all sorts of things that just opening up a tarball won't handle well.

If I really really couldn't build a proper package I would do something like this:

### nodes.pp:

node 'server1.domain.com' inherits basenode {
apps { apps:
version    => 56,
oldversion => 55,
apps_name  => "apps_tarball.tgz",
}


### init.pp (modules):

file {
[ "/usr/local/apps/path/apps-version-${oldversion}", "/tmp/${oldversion}-${apps_name}" ]: recurse => true, ensure => absent; } exec { "apps_wget_${apps_name}":
command   => "/usr/bin/wget http://web_server/${version}-${apps_name} -O /tmp/${container_zip_name}", logoutput => on_failure, creates => "/tmp/${version}-${apps_name}", require => [ Package["wget"] ]; "apps_unzip_${apps_name}":
cwd     => "/usr/local/apps/path",
command => "/usr/bin/unzip /tmp/${version}-${apps_name}",
creates => "/usr/local/apps/path/apps-version-${version}", require => [ Package["unzip"], Exec["container_wget"], Exec["apps_wget_${apps_name}] ];
}


Another alternative is to simply use a recursive puppet resource like:

file {
"/usr/local/apps/path/":
source => "puppet:///modules/modulename/apps/path",
ensure => directory,
replace => true,
purge   => true,
recurse => true;
}


(where you've already untarred things correctly on the puppet master. Probably also require whatever package is running the service and notify whatever service it's running out of).

-
file { "/usr/local/apps/path/apps-version-\${old-version}":
ensure => absent
}


As an aside, doing everything as execs is kinda ugly, and can be hard to troubleshoot when things start breaking; if you can, maybe keep extracted versions of the app files on the puppet server, and use a recursive file resource to retrieve?

-