When deploying .tar.gz applications through Puppet, version management becomes crucial. Your current approach handles the initial deployment well, but lacks proper version transition handling. The key pain point emerges when upgrading from version 56 to 57, where the old version directory persists.
Here's an improved implementation that addresses directory cleanup during upgrades:
# modules/apps/manifests/init.pp
define apps::deploy (
Integer $version,
String $apps_name,
String $install_path = '/usr/local/apps/path'
) {
$tarball = "${version}-${apps_name}"
$tmp_path = "/tmp/${tarball}"
$version_file = "${install_path}/.current_version"
# Clean previous version if exists
exec { "clean_previous_version":
command => "rm -rf ${install_path}/*",
onlyif => "test -f ${version_file} && test $(cat ${version_file}) -ne ${version}",
before => Exec["apps_unzip"]
}
# Download new version
exec { "apps_wget":
command => "/usr/bin/wget http://web_server/${tarball} -O ${tmp_path}",
unless => "test -f ${tmp_path}",
require => Package["wget"]
}
# Extract and mark version
exec { "apps_unzip":
cwd => $install_path,
command => "/bin/tar xzf ${tmp_path} && echo ${version} > ${version_file}",
unless => "test -f ${version_file} && test $(cat ${version_file}) -eq ${version}",
require => [Package["tar"], Exec["apps_wget"]]
}
}
The solution introduces several improvements:
- Uses a hidden .current_version file to track installations
- Properly cleans previous installation before deploying new version
- Switches from unzip to tar for .tar.gz files (more appropriate)
- Adds proper dependency chaining between resources
Your node declaration would now look like:
node 'server1.domain.com' inherits basenode {
apps::deploy { 'my_application':
version => 57,
apps_name => "apps_tarball.tgz"
}
}
For more robust handling, consider the puppet/archive module:
class { 'archive':
path => "/tmp/${version}-${apps_name}",
source => "http://web_server/${version}-${apps_name}",
extract => true,
extract_path => "/usr/local/apps/path",
extract_command => 'tar xzf %s',
cleanup => true,
creates => "/usr/local/apps/path/.version-${version}"
}
While Puppet can handle application deployment, Capistrano might be better suited for:
- Complex multi-step deployment procedures
- Application-specific tasks (migrations, restarts)
- Rollback capabilities
A hybrid approach often works best - Puppet for infrastructure and dependencies, Capistrano for application deployment.
When deploying applications packaged in .tar.gz files using Puppet, version management becomes crucial. The primary pain point emerges when upgrading versions - how to properly clean up previous installations while maintaining idempotency in your Puppet manifests.
Your existing implementation shows a good start with wget and unzip operations, but lacks proper version cleanup. Here's what's working well:
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"] ],
}
To properly handle version upgrades, we need to:
file { "/usr/local/apps/path/apps-version-${old_version}":
ensure => absent,
backup => false,
require => Exec["apps_unzip"],
before => Exec["apps_unzip"],
}
Here's a comprehensive approach that handles both deployment and cleanup:
define apps::deploy (
$version,
$apps_name,
$install_path = '/usr/local/apps/path'
) {
$tarball = "${version}-${apps_name}"
$tmp_path = "/tmp/${tarball}"
# Download the tarball
exec { "download_${tarball}":
command => "/usr/bin/wget http://web_server/${tarball} -O ${tmp_path}",
unless => "/usr/bin/test -f ${tmp_path}",
require => Package['wget'],
}
# Clean previous version if exists
file { "${install_path}/apps-version-${version}":
ensure => absent,
backup => false,
onlyif => "test -d ${install_path}/apps-version-${version}",
}
# Extract new version
exec { "extract_${tarball}":
command => "/bin/tar -xzf ${tmp_path} -C ${install_path}",
creates => "${install_path}/apps-version-${version}",
require => [Package['tar'], Exec["download_${tarball}"]],
}
# Clean up temp file
file { $tmp_path:
ensure => absent,
require => Exec["extract_${tarball}"],
}
}
While Puppet excels at system configuration and package management, Capistrano might be better suited for:
- Application-specific deployment workflows
- Rolling back deployments
- Managing complex deployment sequences
When using Puppet for application deployment:
# Use defined types for reusable deployment logic
# Implement proper dependency chains
# Include verification steps for each operation
# Clean up temporary files and old versions