Skip to content

Instantly share code, notes, and snippets.

@heffergm
Created March 9, 2012 21:05
Show Gist options
  • Save heffergm/2008701 to your computer and use it in GitHub Desktop.
Save heffergm/2008701 to your computer and use it in GitHub Desktop.
begin
require 'railsless-deploy'
require 'capistrano/ext/multistage'
rescue LoadError
abort "No soup for you! =>Required gems: railsless-deploy, capistrano-ext"
end
## rvm =>uncommment and set appropriately if you're using rvm
#$:.unshift(File.expand_path('./lib', ENV['rvm_path']))
#require "rvm/capistrano"
#set :rvm_ruby_string, '1.9.2-p290-patched@puppet'
#set :rvm_type, :system
## /rvm
# opts
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
set :application, "your_app"
set :repository_name, "your_repository"
set :repository, "git@github.com:your/#{repository_name}.git"
set :scm, :git
set :user, "root"
set :branch, ENV['BRANCH'] || "master"
set :deploy_to, "/opt/#{repository_name}"
set :deploy_via, :remote_cache
set :use_sudo, false
set :keep_releases, 2
set :deploy_lockfile, "/tmp/deploy_lockfile.txt"
set :message, %x[git log -n1 --oneline]
set :tags, ENV['TAGS']
set :max_hosts, ENV['MAXHOSTS'] || 100
## Lock deploy
%w(deploy).each do |lock|
before(lock.to_sym, 'deploy:lock'.to_sym)
end
## update, cleanup, run puppet, unlock
after "deploy:update", "deploy:run_puppet", "deploy:cleanup", "deploy:unlock"
## Start deploying
namespace :deploy do
task :start do ; end
task :stop do ; end
# custom cleanup
task :cleanup, :except => { :no_release => true } do
count = fetch(:keep_releases, 2).to_i
cmd = "ls -xt #{releases_path}"
run cmd do |channel, stream, data|
local_releases = data.split.reverse
if count >= local_releases.length
logger.info "\e[0;31;1mNOTICE:\e[0m No old releases to clean up on #{channel[:server]}"
else
logger.info "\e[0;31;1mNOTICE:\e[0m Keeping #{count} of #{local_releases.length} deployed releases on #{channel[:server]}"
(local_releases - local_releases.last(count)).each { |release|
run "rm -rf #{File.join(releases_path, release)}", :hosts => [channel[:server]]
}
end
end
end
## Set max_hosts on update_code
task :update_code, :except => { :no_release => true }, :max_hosts => "#{max_hosts}" do
logger.info "\e[0;31;1mNOTICE:\e[0m Pulling repo from #{repository}: max_hosts => '#{max_hosts}'"
on_rollback { run "rm -rf #{release_path}; true" }
strategy.deploy!
finalize_update
end
## Create deploy lockfiles
task :lock, :roles => :app do
check_lock
logger.info "\e[0;31;1mNOTICE:\e[0m Creating deploy lockfile..."
msg = fetch(:lock_message, 'Cap generated lock message')
timestamp = Time.now.strftime("%m/%d/%Y %H:%M:%S %Z")
lock_message = "Deploys locked by #{ENV['USER']} at #{timestamp}: #{msg}"
put lock_message, "#{deploy_lockfile}", :mode => 0664
end
## Check for lockfiles
desc "Check if deploys are OK here or if someone has locked down deploys"
task :check_lock, :roles => :app do
run "cat #{deploy_lockfile};echo" do |ch, stream, data|
if data =~ /Deploys locked by/
logger.info "\e[0;31;1mABORTING:\e[0m #{data}"
abort 'Deploys are locked on this machine'
else
end
end
end
## Remove lockfiles
desc "Remove the deploy lock"
task :unlock, :roles => :app do
logger.info "\e[0;31;1mNOTICE:\e[0m Removing deploy lockfile..."
run "rm -f #{deploy_lockfile}; echo"
end
## Run puppet
task :run_puppet, :roles => :app do
if ENV['NOOP'] == nil
if ENV['TAGS'] == nil
logger.info "\e[0;31;1mATTENTION:\e[0m Applying full puppet manifest..."
run "puppet apply --factpath=#{current_path}/facter/lib --modulepath=#{current_path}/modules #{current_path}/manifests/site.pp"
else
logger.info "\e[0;31;1mATTENTION:\e[0m Applying puppet manifests with tags: #{ENV['TAGS']}"
run "puppet apply --factpath=#{current_path}/facter/lib --modulepath=#{current_path}/modules --tags #{tags} #{current_path}/manifests/site.pp"
end
else
if ENV['TAGS'] == nil
logger.info "\e[0;31;1mATTENTION:\e[0m Applying full puppet manifest with --noop set (no changes will be made)..."
run "puppet apply --noop --factpath=#{current_path}/facter/lib --modulepath=#{current_path}/modules #{current_path}/manifests/site.pp"
else
logger.info "\e[0;31;1mATTENTION:\e[0m Applying puppet manifests with tags: #{ENV['TAGS']}, --noop is set (no changes will be made)..."
run "puppet apply --noop --factpath=#{current_path}/facter/lib --modulepath=#{current_path}/modules --tags #{tags} #{current_path}/manifests/site.pp"
end
end
end
end
@heffergm
Copy link
Author

heffergm commented Mar 9, 2012

Deploy and apply puppet manifests via capistrano

  • this is a generalized gist of what I'm using to deploy puppet manifests

Why is it any good?

  • apply manifests based only on specific puppet tags via TAGS="tag1,tag2,tag3". So for example: HOSTFILTER=some.host.com TAGS="redis,monit" cap production deploy, will only apply puppet modules you've tagged with redis or monit, and only on some.host.com.
  • run puppet with noop to test changes: NOOP=t cap production deploy . This will apply all your manifests, tell you what would have changed, but not actually make the changes.
  • it avoids all the headaches that come with attempting to maintain a puppetmaster, scaling it, and trying to make changes without wreaking havoc on production systems (see NOOP ^)

Questions?

  • fire away

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment