Skip to content

Instantly share code, notes, and snippets.

@jfryman
Last active November 14, 2017 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jfryman/14e5134ad0a2cc982f554b6811080573 to your computer and use it in GitHub Desktop.
Save jfryman/14e5134ad0a2cc982f554b6811080573 to your computer and use it in GitHub Desktop.
Puppet Env Magic
$stdout.sync = true
namespace :environments do
desc "Update one or more branches "
task :update, :branch do |_, args|
branch = args[:branch] || 'all'
log "Pruning origin"
git(:remote, :prune, :origin)
repo_dir = ENV['ROOT_DIR'] || '/opt/puppet'
envs_dir = ENV['PUPPET_ENV_DIR'] || "#{ROOT_DIR}/environments"
log "Loading list of branches"
all_branches = git(:branch, '-a').split(/\W*\n\W*/)
branches = all_branches.map {|r| remote_branch_name(r) }.compact
# Unless specified, only deploy the requested branch
branch.eql?('all') ? deploy = branches : deploy = branch
Rake::Task['environments:cleanup'].invoke(envs_dir, branches)
Rake::Task['environments:setup'].invoke(envs_dir, repo_dir, deploy)
Rake::Task['environments:symlink'].invoke(envs_dir)
end
desc "Clean up old branches from upstream"
task :cleanup, :dir, :branches do |_, args|
dir, branches = args[:dir], args[:branches]
log "Cleaning up deleted branches from #{Dir.pwd}"
Dir.chdir(dir) do
current_envs = Dir['*']
current_envs.each do |env|
next if env == 'current_working_directory'
next if branches.include? env
next if branches.any?{ |branch| branch.gsub(/\W/,'_') == env }
puts "Removing environment #{env}"
FileUtils.rm_rf env
end
end
end
desc "Deploy a branch"
task :setup, :env_dir, :repo_dir, :branches do |_, args|
environments_dir, repo_dir, branches = args[:env_dir], args[:repo_dir], args[:branches]
Array(branches).each do |branch|
log "Setting up branch #{branch} from #{Dir.pwd}"
env_checkout = "#{environments_dir}/#{branch.gsub(/\W/,'_')}"
Dir.chdir(repo_dir) do
log "Updating git root from #{Dir.pwd}"
git(:fetch, '--all')
log "Running gc on git root."
git(:gc, '--auto')
end
log "Cloning initial branch environment #{branch}"
git(:clone, '--mirror', repo_dir, "#{env_checkout}.tmp/.git")
Dir.chdir("#{env_checkout}.tmp") do
log "Turning bare mirror into regular repository"
git(:config, '--bool', 'core.bare', 'false')
log "Resetting branch environment to origin/#{branch}"
git(:reset, '--hard', "origin/#{branch}")
local_branch_sha = git('show', '-s', '--pretty=format:%H', 'HEAD').strip
log "Environment #{branch} is currently on #{local_branch_sha}"
end
log "Deploying new branch environment #{branch}"
FileUtils.mv env_checkout, "#{env_checkout}.old" if File.directory? env_checkout
FileUtils.mv "#{env_checkout}.tmp", env_checkout
FileUtils.rm_rf "#{env_checkout}.old" if File.directory? "#{env_checkout}.old"
end
end
task :symlink, :environments_dir do |_, args|
environments_dir = args[:environments_dir]
unless Dir.exists?("#{environments_dir}/production") do
log "Creating production symlinks"
Dir.chdir(environments_dir) do
ln_nfs 'master', 'production'
end
end
end
end
end
def git(command, *args)
arguments = args.map {|a| a.to_s }.join(' ')
output = `git #{command} #{arguments} 2>&1`
log output
output
end
def remote_branch_name(full_branch_name)
full_branch_name[%r{remotes/origin/([\w\-\/]*)$}, 1]
end
def librarian(dir)
Dir.chdir(dir)
puts `bundle exec librarian-puppet install`
end
def ln_nfs(source, dest)
if File.exists?(dest) ||
(File.symlink?(dest) && File.readlink(dest) != source)
File.unlink dest
end
File.symlink source, dest
end
def log(message)
timestr = Time.now.strftime("%H:%M:%S")
puts "[#{timestr}] #{message}"
end
#!/usr/bin/env sh
set -e
if [ $(id -u) -ne 0 ]; then
echo "Please run with root privileges"
exit 1
fi
DIR=$( dirname "$(readlink -f "$0")" )
. $DIR/shared-functions
cd $PROJECT_ROOT
echo "Configuring system..."
if [ -n "$DEBUG" ]; then
echo "Enabling Debug..."
PUPPET_GRAPH_ARGS="--graph --graphdir $PROJECT_ROOT/graphs/$NODE"
PUPPET_DEBUG_ARGS="--debug --verbose $PUPPET_GRAPH_ARGS"
LIBRARIAN_DEBUG_AGRS="--verbose"
GIT_DEBUG_ARGS="--verbose"
RSYNC_DEBUG_ARGS="-v"
## Make graph directory for output and debug
if [ ! -d $PROJECT_ROOT/graphs/${NODE} ]; then
mkdir -p $PROJECT_ROOT/graphs/${NODE}
fi
fi
# Disable color output from different tools
if [ -n "$NOCOLOR" ]; then
PUPPET_COLOR_ARGS="--color=false"
fi
# Do not attempt to upload from upstream git
if [ -z "$DISABLE_GIT" ]; then
git pull origin -q $GIT_DEBUG_ARGS
fi
## Run any pre-flight commands
$PROJECT_ROOT/script/preflight-os
# Set the environment. This should be done *after* librarian-puppet
## has done its thing to determine if it is needed to switch back
## to production if the branch has been deleted.
##
## `puppet_environment` is set in Class[puppet::masterless]
CURRENT_ENV=`$PROJECT_ROOT/bin/facter puppet_environment`
PUPPET_ENV=""
if [ -z "$ENV" ]; then
if [ -n "$CURRENT_ENV" ]; then
PUPPET_ENV=$CURRENT_ENV
else
PUPPET_ENV='production'
fi
else
PUPPET_ENV=$ENV
fi
# Setup Puppet environments
mkdir -p $PROJECT_ROOT/environments
if [ "$PUPPET_ENV" = "current_working_directory" ]; then
# Make sure the current working directory is an environment too!
# This is sort of a hack to support environments while developing
# on the currently active branch in Vagrant or other environments
echo "Setting up 'current_working_directory'..."
## Install Puppet libs
librarian-puppet install >> $LOG_FILE 2>&1
## Setup an environment for this project
rsync $RSYNC_DEBUG_ARGS -arh --delete --exclude "environments" \
--exclude "vendor" --exclude "artifacts" --exclude "graphs" \
--exclude "packer" --exclude "script" --exclude ".git" \
$PROJECT_ROOT/ $PROJECT_ROOT/environments/current_working_directory/
else
echo "Setting up Puppet environments..."
rake environments:update[$PUPPET_ENV] >> $LOG_FILE 2>&1
fi
## Attempt to detect if the environment even exists... if not,
## roll back to the production environment.
### Make sure our environment conforms to Puppet environment naming
PUPPET_ENV=$(echo $PUPPET_ENV | sed 's/[-\/.]/_/g')
if [ ! -d $PROJECT_ROOT/environments/$PUPPET_ENV ]; then
echo "The environment $PUPPET_ENV does not exist... falling back to production"
PUPPET_ENV='production'
fi
## Run Puppet
puppet apply $PUPPET_DEBUG_ARGS --environment $PUPPET_ENV \
--config $PROJECT_ROOT/puppet.conf $PUPPET_COLOR_ARGS \
$PROJECT_ROOT/environments/$PUPPET_ENV/manifests $@ 2>&1 \
| tee -a $LOG_FILE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment