aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile30
-rw-r--r--Gemfile.lock24
-rwxr-xr-xbin/leap3
-rw-r--r--leap_cli.gemspec8
-rw-r--r--lib/leap_cli.rb6
-rw-r--r--lib/leap_cli/version.rb4
-rw-r--r--vendor/supply_drop/.gitignore4
-rw-r--r--vendor/supply_drop/.rvmrc1
-rw-r--r--vendor/supply_drop/.travis.yml4
-rw-r--r--vendor/supply_drop/Gemfile6
-rw-r--r--vendor/supply_drop/Gemfile.lock47
-rw-r--r--vendor/supply_drop/README.md128
-rw-r--r--vendor/supply_drop/Rakefile24
-rw-r--r--vendor/supply_drop/lib/supply_drop.rb12
-rw-r--r--vendor/supply_drop/lib/supply_drop/async_enumerable.rb19
-rw-r--r--vendor/supply_drop/lib/supply_drop/plugin.rb94
-rw-r--r--vendor/supply_drop/lib/supply_drop/rsync.rb45
-rw-r--r--vendor/supply_drop/lib/supply_drop/syntax_checker.rb21
-rw-r--r--vendor/supply_drop/lib/supply_drop/tasks.rb96
-rw-r--r--vendor/supply_drop/lib/supply_drop/thread_pool.rb39
-rw-r--r--vendor/supply_drop/lib/supply_drop/util.rb23
-rw-r--r--vendor/supply_drop/lib/supply_drop/writer/batched.rb22
-rw-r--r--vendor/supply_drop/lib/supply_drop/writer/file.rb23
-rw-r--r--vendor/supply_drop/lib/supply_drop/writer/streaming.rb16
-rw-r--r--vendor/supply_drop/supply_drop.gemspec13
-rw-r--r--vendor/supply_drop/test/async_test.rb67
-rw-r--r--vendor/supply_drop/test/files/manifests/invalid.pp1
-rw-r--r--vendor/supply_drop/test/files/manifests/valid.pp9
-rw-r--r--vendor/supply_drop/test/files/templates/invalid.erb1
-rw-r--r--vendor/supply_drop/test/files/templates/valid.erb1
-rw-r--r--vendor/supply_drop/test/rsync_test.rb57
-rw-r--r--vendor/supply_drop/test/syntax_checker_test.rb23
32 files changed, 860 insertions, 11 deletions
diff --git a/Gemfile b/Gemfile
index e45e65f..7ee6bbf 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,2 +1,32 @@
source :rubygems
gemspec
+
+#
+# Specify support gems used that we might also develop locally.
+#
+# Available options:
+#
+# :dev_path - the development path of the gem. this path is used if running in 'development mode'.
+#
+# :vendor_path - where this gem is vendored. this path is used if it exists and we are running in 'production mode'
+#
+development_gems = {
+ 'supply_drop' => {:dev_path => '../gems/supply_drop', :vendor_path => 'vendor/supply_drop'}
+}
+
+#
+# A little bit of code to magically pick the correct gem
+#
+
+mode = :production
+
+gem_root = File.dirname(__FILE__)
+path_key = mode == :development ? :dev_path : :vendor_path
+development_gems.each do |gem_name, options|
+ path = File.expand_path(options[path_key], gem_root)
+ if File.directory?(path)
+ gem gem_name, :path => path
+ else
+ gem gem_name
+ end
+end \ No newline at end of file
diff --git a/Gemfile.lock b/Gemfile.lock
index 5e98ec9..43d5d15 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -2,19 +2,40 @@ PATH
remote: .
specs:
leap_cli (0.0.1)
+ capistrano
gli (~> 2.3)
gpgme
highline
json_pure
+ net-ssh
terminal-table
+PATH
+ remote: vendor/supply_drop
+ specs:
+ supply_drop (0.12.0)
+ capistrano (>= 2.5.21)
+
GEM
remote: http://rubygems.org/
specs:
- gli (2.4.0)
+ capistrano (2.13.4)
+ highline
+ net-scp (>= 1.0.0)
+ net-sftp (>= 2.0.0)
+ net-ssh (>= 2.0.14)
+ net-ssh-gateway (>= 1.1.0)
+ gli (2.4.1)
gpgme (2.0.1)
highline (1.6.15)
json_pure (1.7.5)
+ net-scp (1.0.4)
+ net-ssh (>= 1.99.1)
+ net-sftp (2.0.5)
+ net-ssh (>= 2.0.9)
+ net-ssh (2.6.1)
+ net-ssh-gateway (1.1.0)
+ net-ssh (>= 1.99.1)
rake (0.9.2.2)
terminal-table (1.4.5)
@@ -24,3 +45,4 @@ PLATFORMS
DEPENDENCIES
leap_cli!
rake
+ supply_drop!
diff --git a/bin/leap b/bin/leap
index 171bbb0..0f55e5b 100755
--- a/bin/leap
+++ b/bin/leap
@@ -18,6 +18,7 @@ rescue LoadError
$LOAD_PATH.unshift lib_dir unless $LOAD_PATH.include?(lib_dir)
require 'rubygems'
require 'leap_cli'
+ require 'bundler/setup' # force evaluation of "Gemfile"
end
require 'gli'
@@ -37,8 +38,6 @@ module LeapCli::Commands
extend Forwardable
extend Terminal::Table::TableHelper
- ENV['GLI_DEBUG'] = "true"
-
#
# delegate highline methods to make them available to sub-commands
#
diff --git a/leap_cli.gemspec b/leap_cli.gemspec
index 9bc5232..8b9c9c5 100644
--- a/leap_cli.gemspec
+++ b/leap_cli.gemspec
@@ -44,8 +44,12 @@ spec = Gem::Specification.new do |s|
s.add_runtime_dependency('terminal-table')
s.add_runtime_dependency('highline')
- # other gems
- s.add_runtime_dependency('net-ssh') # used for setting up ssh keys (but also required by other gems we use)
+ # network gems
+ s.add_runtime_dependency('net-ssh')
+ s.add_runtime_dependency('capistrano')
+ #s.add_runtime_dependency('supply_drop')
+
+ # misc gems
s.add_runtime_dependency('json_pure') # we use this json library for output so we can keep the keys sorted.
s.add_runtime_dependency('gpgme') # not essential, but used for some minor stuff in adding sysadmins
diff --git a/lib/leap_cli.rb b/lib/leap_cli.rb
index 0b3a59f..e258cf3 100644
--- a/lib/leap_cli.rb
+++ b/lib/leap_cli.rb
@@ -1,10 +1,6 @@
module LeapCli; end
-unless defined?(LeapCli::VERSION)
- # ^^ I am not sure why this is needed.
- require 'leap_cli/version.rb'
-end
-
+require 'leap_cli/version.rb'
require 'core_ext/hash'
require 'core_ext/boolean'
require 'core_ext/nil'
diff --git a/lib/leap_cli/version.rb b/lib/leap_cli/version.rb
index c272647..5900ee5 100644
--- a/lib/leap_cli/version.rb
+++ b/lib/leap_cli/version.rb
@@ -1,3 +1,5 @@
module LeapCli
- VERSION = '0.0.1'
+ unless defined?(LeapCli::VERSION)
+ VERSION = '0.0.1'
+ end
end
diff --git a/vendor/supply_drop/.gitignore b/vendor/supply_drop/.gitignore
new file mode 100644
index 0000000..c2c6428
--- /dev/null
+++ b/vendor/supply_drop/.gitignore
@@ -0,0 +1,4 @@
+**/*/.vagrant
+*.gem
+*.swp
+**/*/puppet_output.txt
diff --git a/vendor/supply_drop/.rvmrc b/vendor/supply_drop/.rvmrc
new file mode 100644
index 0000000..b0542b7
--- /dev/null
+++ b/vendor/supply_drop/.rvmrc
@@ -0,0 +1 @@
+rvm 1.8.7-p249@supply_drop --create
diff --git a/vendor/supply_drop/.travis.yml b/vendor/supply_drop/.travis.yml
new file mode 100644
index 0000000..7751578
--- /dev/null
+++ b/vendor/supply_drop/.travis.yml
@@ -0,0 +1,4 @@
+language: ruby
+rvm:
+ - 1.8.7
+ - 1.9.2
diff --git a/vendor/supply_drop/Gemfile b/vendor/supply_drop/Gemfile
new file mode 100644
index 0000000..b4e0f50
--- /dev/null
+++ b/vendor/supply_drop/Gemfile
@@ -0,0 +1,6 @@
+source :rubygems
+
+gem 'capistrano', '2.11.2'
+gem 'vagrant', '0.9.7'
+gem 'rake', '0.8.7'
+gem 'puppet', '2.7.1'
diff --git a/vendor/supply_drop/Gemfile.lock b/vendor/supply_drop/Gemfile.lock
new file mode 100644
index 0000000..c85ee2c
--- /dev/null
+++ b/vendor/supply_drop/Gemfile.lock
@@ -0,0 +1,47 @@
+GEM
+ remote: http://rubygems.org/
+ specs:
+ archive-tar-minitar (0.5.2)
+ capistrano (2.11.2)
+ highline
+ net-scp (>= 1.0.0)
+ net-sftp (>= 2.0.0)
+ net-ssh (>= 2.0.14)
+ net-ssh-gateway (>= 1.1.0)
+ childprocess (0.3.1)
+ ffi (~> 1.0.6)
+ erubis (2.7.0)
+ facter (1.6.5)
+ ffi (1.0.11)
+ highline (1.6.11)
+ i18n (0.6.0)
+ json (1.5.4)
+ log4r (1.1.10)
+ net-scp (1.0.4)
+ net-ssh (>= 1.99.1)
+ net-sftp (2.0.5)
+ net-ssh (>= 2.0.9)
+ net-ssh (2.2.2)
+ net-ssh-gateway (1.1.0)
+ net-ssh (>= 1.99.1)
+ puppet (2.7.1)
+ facter (>= 1.5.1)
+ rake (0.8.7)
+ vagrant (0.9.7)
+ archive-tar-minitar (= 0.5.2)
+ childprocess (~> 0.3.1)
+ erubis (~> 2.7.0)
+ i18n (~> 0.6.0)
+ json (~> 1.5.1)
+ log4r (~> 1.1.9)
+ net-scp (~> 1.0.4)
+ net-ssh (~> 2.2.2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ capistrano (= 2.11.2)
+ puppet (= 2.7.1)
+ rake (= 0.8.7)
+ vagrant (= 0.9.7)
diff --git a/vendor/supply_drop/README.md b/vendor/supply_drop/README.md
new file mode 100644
index 0000000..91e86b6
--- /dev/null
+++ b/vendor/supply_drop/README.md
@@ -0,0 +1,128 @@
+# supply_drop
+
+supply_drop is a capistrano plugin to facitiate provisioning servers with puppet, without using the puppet server. It works by simply rsyncing your puppet configuration files to your servers and running puppet apply. It strives to allow you to write idiomatic puppet scripts while being as lightweight as possible.
+
+[![Build Status](https://secure.travis-ci.org/pitluga/supply_drop.png)](http://travis-ci.org/pitluga/supply_drop)
+
+### Installation
+
+ gem install supply_drop
+
+or with Bundler
+
+ gem 'supply_drop'
+
+then at the top of your deploy.rb
+
+ require 'rubygems'
+ require 'supply_drop'
+
+### Tasks
+
+ cap puppet:bootstrap:ubuntu
+ cap puppet:bootstrap:osx
+ cap puppet:bootstrap:redhat
+
+This does a simple apt-get install of puppet on the target servers.
+
+ cap puppet:noop
+
+This will show you a list of the pending changes to be applied server-by-server.
+
+ cap puppet:apply
+
+Applies the pending changes to all the servers.
+
+ cap puppet:syntax_check
+
+Locally syntax checks all the puppet files and erb templates. Requires you to have puppet installed locally.
+
+ cap puppet:remove_lock
+
+Remove any stale lock files created by supply_drop when locking is used and something went wrong.
+
+
+You can specify that one of your servers should not be puppeted by setting the :nopuppet flag to true, like so. It will then be skipped by all the above commands.
+
+ role :weird_thing, '33.33.33.33', :nopuppet => true
+
+### Variables
+
+There are several variables that can be overriden to change how supply_drop works:
+
+ set :puppet_source, '.'
+
+defines the base directory containing your puppet configs that will be rsynced to the servers.
+
+ set :puppet_destination, '/tmp/supply_drop'
+
+defines where on the server the puppet configuration files are synced to.
+
+ set :puppet_command, 'puppet apply'
+
+allows you to override the puppet command that is run if puppet is not on the path.
+
+ set :puppet_lib, "#{puppet_destination}/modules"
+
+the value of the PUPPETLIB environment variable, the location of your puppet modules.
+
+ set :puppet_parameters, 'puppet.pp'
+
+the parameters that are passed to the puppet call.
+
+ set :puppet_excludes, %w(.git .svn)
+
+these are patterns that are passed as rsync --exclude flags when pushing your puppet configs to the box.
+
+ set :puppet_parallel_rsync, true
+
+determines whether the rsync commands for multiple servers are run in parallel threads or serially
+
+ set :puppet_parallel_rsync_pool_size, 10
+
+sets the maximum number of rsync commands that are run concurrently
+
+ set :puppet_syntax_check, false
+
+when true, will syntax check your puppet files and erb templates before rsyncing them to your servers. This is an
+experimental feature and is quite slow at the moment.
+
+ set :puppet_stream_output, false
+
+will write the incremental output from the hosts to the screen instead of waiting until complete and printing by host.
+
+ set :puppet_write_to_file, nil
+
+a file to additionally write puppet output to, useful for large noops with small scrollbacks.
+
+ set :puppet_runner, nil
+
+allows you to specify the user to execute the puppet command as. Like running sudo -u puppet args from the command line.
+
+ set :puppet_lock_file, '/tmp/puppet.lock'
+
+sets a lockfile on each remote host to prevent multiple users from puppeting the same node simultaneously. Set to nil to disable locking. You can alternately temporarily disable locking by setting the NO_PUPPET_LOCKING environment variable to any value.
+
+### Handling Legacy Puppet
+
+Puppet deprecated the implicit invocation of apply [in the 2.6.x series](https://github.com/puppetlabs/puppet/commit/a23cfd869f90ae4456dded6e5a1c82719b128f01).
+
+The default behavior of supply_drop includes `apply` keyword in its commands, but if you need compatibility with older versions of puppet, set the `puppet_command` variable to omit it.
+
+You'll need to do this if you see errors like this:
+
+ Could not parse for environment production: Could not find file /home/.../supply_drop/apply.pp
+
+### How to contribute
+
+If you write anything complicated, write a test for it. Test that your changes work using vagrant. Send a pull request. Easy peezy.
+
+### Contributors
+
+* Paul Hinze [phinze](https://github.com/phinze "github")
+* Paul Gross [pgr0ss](https://github.com/pgr0ss "github")
+* Drew Olson [drewolson](https://github.com/drewolson "github")
+* Dave Pirotte [dpirotte](https://github.com/dpirotte "github")
+* Mike Pilat [mikepilat](https://github.com/mikepilat "github")
+* Dan Manges [dan-manges](https://github.com/dan-manges "github") (one soda's worth)
+* Brian Cosgrove [cosgroveb](https://github.com/cosgroveb "github")
diff --git a/vendor/supply_drop/Rakefile b/vendor/supply_drop/Rakefile
new file mode 100644
index 0000000..666b6a4
--- /dev/null
+++ b/vendor/supply_drop/Rakefile
@@ -0,0 +1,24 @@
+require 'rake/testtask'
+
+Rake::TestTask.new do |t|
+ t.test_files = FileList['test/*_test.rb']
+end
+
+task :default => :test
+
+desc "clean"
+task :clean do
+ rm_f Dir.glob("*.gem")
+end
+
+namespace :gem do
+ desc "build the gem"
+ task :build => :clean do
+ sh "gem build supply_drop.gemspec"
+ end
+
+ desc "push the gem"
+ task :push => :build do
+ sh "gem push #{Dir.glob("*.gem").first}"
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop.rb b/vendor/supply_drop/lib/supply_drop.rb
new file mode 100644
index 0000000..9c2c050
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop.rb
@@ -0,0 +1,12 @@
+require 'supply_drop/rsync'
+require 'supply_drop/async_enumerable'
+require 'supply_drop/plugin'
+require 'supply_drop/syntax_checker'
+require 'supply_drop/thread_pool'
+require 'supply_drop/util'
+require 'supply_drop/writer/batched'
+require 'supply_drop/writer/file'
+require 'supply_drop/writer/streaming'
+require 'supply_drop/tasks'
+
+Capistrano.plugin :supply_drop, SupplyDrop::Plugin
diff --git a/vendor/supply_drop/lib/supply_drop/async_enumerable.rb b/vendor/supply_drop/lib/supply_drop/async_enumerable.rb
new file mode 100644
index 0000000..1d5a116
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/async_enumerable.rb
@@ -0,0 +1,19 @@
+module SupplyDrop
+ module AsyncEnumerable
+ def each(&block)
+ pool = SupplyDrop::ThreadPool.new(SupplyDrop::Util.thread_pool_size)
+ super do |item|
+ pool.schedule(item, &block)
+ end
+ pool.shutdown
+ end
+
+ def map(&block)
+ pool = SupplyDrop::ThreadPool.new(SupplyDrop::Util.thread_pool_size)
+ super do |item|
+ pool.schedule(item, &block)
+ end
+ pool.shutdown
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/plugin.rb b/vendor/supply_drop/lib/supply_drop/plugin.rb
new file mode 100644
index 0000000..348b22b
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/plugin.rb
@@ -0,0 +1,94 @@
+module SupplyDrop
+ module Plugin
+
+ def rsync
+ SupplyDrop::Util.thread_pool_size = puppet_parallel_rsync_pool_size
+ servers = SupplyDrop::Util.optionally_async(find_servers_for_task(current_task), puppet_parallel_rsync)
+ failed_servers = servers.map do |server|
+ rsync_cmd = SupplyDrop::Rsync.command(
+ puppet_source,
+ SupplyDrop::Rsync.remote_address(server.user || fetch(:user, ENV['USER']), server.host, puppet_destination),
+ :delete => true,
+ :excludes => puppet_excludes,
+ :ssh => ssh_options.merge(server.options[:ssh_options]||{})
+ )
+ logger.debug rsync_cmd
+ server.host unless system rsync_cmd
+ end.compact
+
+ raise "rsync failed on #{failed_servers.join(',')}" if failed_servers.any?
+ end
+
+ def prepare
+ run "mkdir -p #{puppet_destination}"
+ run "#{sudo} chown -R $USER: #{puppet_destination}"
+ end
+
+ def noop
+ puppet(:noop)
+ end
+
+ def apply
+ puppet(:apply)
+ end
+
+ def lock
+ if should_lock?
+ run <<-GETLOCK
+if [ ! -f #{puppet_lock_file} ]; then
+ touch #{puppet_lock_file};
+else
+ stat -c "#{red_text("Puppet in progress, #{puppet_lock_file} owned by %U since %x")}" #{puppet_lock_file} >&2;
+ exit 1;
+fi
+ GETLOCK
+ end
+ end
+
+ def unlock
+ run "#{sudo} rm -f #{puppet_lock_file}; true" if should_lock?
+ end
+
+ private
+
+ def should_lock?
+ puppet_lock_file && !ENV['NO_PUPPET_LOCK']
+ end
+
+ def puppet(command = :noop)
+ #puppet_cmd = "cd #{puppet_destination} && #{sudo_cmd} #{puppet_command} --modulepath=#{puppet_lib} #{puppet_parameters}"
+ puppet_cmd = "cd #{puppet_destination} && #{sudo_cmd} #{puppet_command} #{puppet_parameters}"
+ flag = command == :noop ? '--noop' : ''
+
+ writer = if puppet_stream_output
+ SupplyDrop::Writer::Streaming.new(logger)
+ else
+ SupplyDrop::Writer::Batched.new(logger)
+ end
+
+ writer = SupplyDrop::Writer::File.new(writer, puppet_write_to_file) unless puppet_write_to_file.nil?
+
+ begin
+ run "#{puppet_cmd} #{flag}" do |channel, stream, data|
+ writer.collect_output(channel[:host], data)
+ end
+ logger.debug "Puppet #{command} complete."
+ ensure
+ writer.all_output_collected
+ end
+ end
+
+ def red_text(text)
+ "\033[0;31m#{text}\033[0m"
+ end
+
+ def sudo_cmd
+ if fetch(:use_sudo, true)
+ sudo(:as => puppet_runner)
+ else
+ logger.info "NOTICE: puppet_runner configuration invalid when use_sudo is false, ignoring..." unless puppet_runner.nil?
+ ''
+ end
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/rsync.rb b/vendor/supply_drop/lib/supply_drop/rsync.rb
new file mode 100644
index 0000000..7356653
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/rsync.rb
@@ -0,0 +1,45 @@
+module SupplyDrop
+ class Rsync
+ class << self
+ def command(from, to, options={})
+ flags = ['-az']
+ flags << '--delete' if options[:delete]
+ flags << excludes(options[:excludes]) if options.has_key?(:excludes)
+ flags << ssh_options(options[:ssh]) if options.has_key?(:ssh)
+
+ "rsync #{flags.compact.join(' ')} #{from} #{to}"
+ end
+
+ def remote_address(user, host, path)
+ user_with_host = [user, host].compact.join('@')
+ [user_with_host, path].join(':')
+ end
+
+ def excludes(patterns)
+ [patterns].flatten.map { |p| "--exclude=#{p}" }
+ end
+
+ def ssh_options(options)
+ mapped_options = options.map do |key, value|
+ next unless value
+
+ #
+ # for a list of the options normally support by Net::SSH (and thus Capistrano), see
+ # http://net-ssh.github.com/net-ssh/classes/Net/SSH.html#method-c-start
+ #
+ case key
+ when :keys then [value].flatten.select { |k| File.exist?(k) }.map { |k| "-i #{k}" }
+ when :config then "-F #{value}"
+ when :port then "-p #{value}"
+ when :user_known_hosts_file then "-o 'UserKnownHostsFile=#{value}'"
+ when :host_key_alias then "-o 'HostKeyAlias=#{value}'"
+ when :paranoid then "-o 'StrictHostKeyChecking=yes'"
+ when :host_name then "-o 'HostName=#{value}'"
+ end
+ end.compact
+
+ %[-e "ssh #{mapped_options.join(' ')}"] unless mapped_options.empty?
+ end
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/syntax_checker.rb b/vendor/supply_drop/lib/supply_drop/syntax_checker.rb
new file mode 100644
index 0000000..fe9cda4
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/syntax_checker.rb
@@ -0,0 +1,21 @@
+module SupplyDrop
+ class SyntaxChecker
+ def initialize(path)
+ @path = path
+ end
+
+ def validate_puppet_files
+ Dir.glob("#{@path}/**/*.pp").map do |puppet_file|
+ output = `puppet parser validate #{puppet_file}`
+ $?.to_i == 0 ? nil : [puppet_file, output]
+ end.compact
+ end
+
+ def validate_templates
+ Dir.glob("#{@path}/**/*.erb").map do |template_file|
+ output = `erb -x -T '-' #{template_file} | ruby -c 2>&1`
+ $?.to_i == 0 ? nil : [template_file, output]
+ end.compact
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/tasks.rb b/vendor/supply_drop/lib/supply_drop/tasks.rb
new file mode 100644
index 0000000..e73b280
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/tasks.rb
@@ -0,0 +1,96 @@
+Capistrano::Configuration.instance.load do
+ namespace :puppet do
+ set :puppet_source, '.'
+ set :puppet_destination, '/tmp/supply_drop'
+ set :puppet_command, 'puppet apply'
+ set :puppet_lib, lambda { "#{puppet_destination}/modules" }
+ set :puppet_parameters, lambda { puppet_verbose ? '--debug --trace puppet.pp' : 'puppet.pp' }
+ set :puppet_verbose, false
+ set :puppet_excludes, %w(.git .svn)
+ set :puppet_stream_output, false
+ set :puppet_parallel_rsync, true
+ set :puppet_parallel_rsync_pool_size, 10
+ set :puppet_syntax_check, false
+ set :puppet_write_to_file, nil
+ set :puppet_runner, nil
+ set :puppet_lock_file, '/tmp/puppet.lock'
+
+ namespace :bootstrap do
+ desc "installs puppet via rubygems on an osx host"
+ task :osx do
+ if fetch(:use_sudo, true)
+ run "#{sudo} gem install puppet --no-ri --no-rdoc"
+ else
+ run "gem install puppet --no-ri --no-rdoc"
+ end
+ end
+
+ desc "installs puppet via apt on an ubuntu host"
+ task :ubuntu do
+ run "mkdir -p #{puppet_destination}"
+ run "#{sudo} apt-get update"
+ run "#{sudo} apt-get install -y puppet rsync"
+ end
+
+ desc "installs puppet via yum on a centos/red hat host"
+ task :redhat do
+ run "mkdir -p #{puppet_destination}"
+ run "#{sudo} yum -y install puppet rsync"
+ end
+ end
+
+ desc "checks the syntax of all *.pp and *.erb files"
+ task :syntax_check do
+ checker = SupplyDrop::SyntaxChecker.new(puppet_source)
+ logger.info "Sytax Checking..."
+ errors = false
+ checker.validate_puppet_files.each do |file, error|
+ logger.important "Puppet error: #{file}"
+ logger.important error
+ errors = true
+ end
+ checker.validate_templates.each do |file, error|
+ logger.important "Template error: #{file}"
+ logger.important error
+ errors = true
+ end
+ raise "syntax errors" if errors
+ end
+
+ desc "pushes the current puppet configuration to the server"
+ task :update_code, :except => { :nopuppet => true } do
+ syntax_check if puppet_syntax_check
+ supply_drop.rsync
+ end
+
+ desc "runs puppet with --noop flag to show changes"
+ task :noop, :except => { :nopuppet => true } do
+ transaction do
+ on_rollback { supply_drop.unlock }
+ supply_drop.prepare
+ supply_drop.lock
+ update_code
+ supply_drop.noop
+ supply_drop.unlock
+ end
+ end
+
+ desc "applies the current puppet config to the server"
+ task :apply, :except => { :nopuppet => true } do
+ transaction do
+ on_rollback { supply_drop.unlock }
+ supply_drop.prepare
+ supply_drop.lock
+ update_code
+ supply_drop.apply
+ supply_drop.unlock
+ end
+ end
+
+ desc "clears the puppet lockfile on the server."
+ task :remove_lock, :except => { :nopuppet => true} do
+ supply_drop.lock
+ end
+ end
+end
+
diff --git a/vendor/supply_drop/lib/supply_drop/thread_pool.rb b/vendor/supply_drop/lib/supply_drop/thread_pool.rb
new file mode 100644
index 0000000..082cf4a
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/thread_pool.rb
@@ -0,0 +1,39 @@
+require 'thread'
+
+module SupplyDrop
+ class ThreadPool
+ def initialize(size)
+ @size = size
+ @jobs = Queue.new
+ @retvals = []
+
+ @pool = Array.new(@size) do |i|
+ Thread.new do
+ Thread.current[:id] = i
+
+ catch(:exit) do
+ loop do
+ job, args = @jobs.pop
+ @retvals << job.call(*args)
+ end
+ end
+ end
+ end
+ end
+
+
+ def schedule(*args, &block)
+ @jobs << [block, args]
+ end
+
+
+ def shutdown
+ @size.times do
+ schedule { throw :exit }
+ end
+
+ @pool.map(&:join)
+ @retvals
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/util.rb b/vendor/supply_drop/lib/supply_drop/util.rb
new file mode 100644
index 0000000..5f4f9f4
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/util.rb
@@ -0,0 +1,23 @@
+module SupplyDrop
+ module Util
+ DEFAULT_THREAD_POOL_SIZE = 10
+
+ def self.thread_pool_size
+ @thread_pool_size ||= DEFAULT_THREAD_POOL_SIZE
+ end
+
+ def self.thread_pool_size=(size)
+ @thread_pool_size = size
+ end
+
+ def self.optionally_async(collection, async)
+ if async
+ async_collection = collection.clone
+ async_collection.extend SupplyDrop::AsyncEnumerable
+ async_collection
+ else
+ collection
+ end
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/writer/batched.rb b/vendor/supply_drop/lib/supply_drop/writer/batched.rb
new file mode 100644
index 0000000..e5fc826
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/writer/batched.rb
@@ -0,0 +1,22 @@
+module SupplyDrop
+ module Writer
+ class Batched
+ def initialize(logger)
+ @outputs = {}
+ @logger = logger
+ end
+
+ def collect_output(host, data)
+ @outputs[host] ||= ""
+ @outputs[host] << data
+ end
+
+ def all_output_collected
+ @outputs.keys.sort.each do |host|
+ @logger.info "Puppet output for #{host}"
+ @logger.debug @outputs[host], host
+ end
+ end
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/writer/file.rb b/vendor/supply_drop/lib/supply_drop/writer/file.rb
new file mode 100644
index 0000000..61454d8
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/writer/file.rb
@@ -0,0 +1,23 @@
+module SupplyDrop
+ module Writer
+ class File
+ def initialize(writer, file)
+ @wrapped_writer = writer
+ @logger = Capistrano::Logger.new(:output => file)
+ @logger.level = Capistrano::Logger::TRACE
+ @file_writer = Batched.new(@logger)
+ end
+
+ def collect_output(host, data)
+ @wrapped_writer.collect_output(host, data)
+ @file_writer.collect_output(host, data)
+ end
+
+ def all_output_collected
+ @wrapped_writer.all_output_collected
+ @file_writer.all_output_collected
+ @logger.close
+ end
+ end
+ end
+end
diff --git a/vendor/supply_drop/lib/supply_drop/writer/streaming.rb b/vendor/supply_drop/lib/supply_drop/writer/streaming.rb
new file mode 100644
index 0000000..e180ec8
--- /dev/null
+++ b/vendor/supply_drop/lib/supply_drop/writer/streaming.rb
@@ -0,0 +1,16 @@
+module SupplyDrop
+ module Writer
+ class Streaming
+ def initialize(logger)
+ @logger = logger
+ end
+
+ def collect_output(host, data)
+ @logger.debug data, host
+ end
+
+ def all_output_collected
+ end
+ end
+ end
+end
diff --git a/vendor/supply_drop/supply_drop.gemspec b/vendor/supply_drop/supply_drop.gemspec
new file mode 100644
index 0000000..34c7e34
--- /dev/null
+++ b/vendor/supply_drop/supply_drop.gemspec
@@ -0,0 +1,13 @@
+require 'rake'
+
+Gem::Specification.new do |s|
+ s.name = "supply_drop"
+ s.summary = "Masterless puppet with capistrano"
+ s.description = "See http://github.com/pitluga/supply_drop"
+ s.version = "0.12.0"
+ s.authors = ["Tony Pitluga", "Paul Hinze"]
+ s.email = ["tony.pitluga@gmail.com", "paul.t.hinze@gmail.com"]
+ s.homepage = "http://github.com/pitluga/supply_drop"
+ s.files = FileList["README.md", "Rakefile", "lib/**/*.rb"]
+ s.add_dependency('capistrano', '>= 2.5.21')
+end
diff --git a/vendor/supply_drop/test/async_test.rb b/vendor/supply_drop/test/async_test.rb
new file mode 100644
index 0000000..0b9bc3a
--- /dev/null
+++ b/vendor/supply_drop/test/async_test.rb
@@ -0,0 +1,67 @@
+require 'test/unit'
+require File.expand_path('../../lib/supply_drop/util', __FILE__)
+require File.expand_path('../../lib/supply_drop/async_enumerable', __FILE__)
+require File.expand_path('../../lib/supply_drop/thread_pool', __FILE__)
+
+class AsyncTest < Test::Unit::TestCase
+ def teardown
+ SupplyDrop::Util.thread_pool_size = SupplyDrop::Util::DEFAULT_THREAD_POOL_SIZE
+ end
+
+ def test_can_enumerate_asynchronously
+ collection = (1..10).to_a
+ elapsed = timed do
+ SupplyDrop::Util.optionally_async(collection, true).each do |item|
+ sleep 0.1
+ end
+ end
+ assert elapsed < 1
+ end
+
+ def test_can_enumerate_asynchronously_with_map
+ collection = (1..10).to_a
+ returned_values = nil
+ elapsed = timed do
+ returned_values = SupplyDrop::Util.optionally_async(collection, true).map do |item|
+ sleep 0.1
+ :somevalue
+ end
+ end
+ assert returned_values == Array.new(10, :somevalue)
+ assert elapsed < 1
+ end
+
+ def test_can_enumerate_normally_and_does_not_leak_after_extending
+ collection = (1..10).to_a
+ elapsed = timed do
+ SupplyDrop::Util.optionally_async(collection, true).each do |item|
+ sleep 0.1
+ end
+ end
+ assert elapsed < 1
+
+ elapsed = timed do
+ SupplyDrop::Util.optionally_async(collection, false).each do |item|
+ sleep 0.1
+ end
+ end
+ assert elapsed >= 1
+ end
+
+ def test_can_configure_thread_pool_size
+ collection = (1..10).to_a
+ SupplyDrop::Util.thread_pool_size = 1
+ elapsed = timed do
+ returned_values = SupplyDrop::Util.optionally_async(collection, true).map do |item|
+ sleep 0.1
+ end
+ end
+ assert elapsed >= 1
+ end
+
+ def timed
+ start = Time.now
+ yield
+ Time.now - start
+ end
+end
diff --git a/vendor/supply_drop/test/files/manifests/invalid.pp b/vendor/supply_drop/test/files/manifests/invalid.pp
new file mode 100644
index 0000000..5ca851c
--- /dev/null
+++ b/vendor/supply_drop/test/files/manifests/invalid.pp
@@ -0,0 +1 @@
+class example {
diff --git a/vendor/supply_drop/test/files/manifests/valid.pp b/vendor/supply_drop/test/files/manifests/valid.pp
new file mode 100644
index 0000000..d8e6486
--- /dev/null
+++ b/vendor/supply_drop/test/files/manifests/valid.pp
@@ -0,0 +1,9 @@
+class valid {
+ file { "/etc/hosts":
+ ensure => present,
+ content => "127.0.0.1 localhost",
+ owner => root,
+ group => root,
+ mode => "0644"
+ }
+}
diff --git a/vendor/supply_drop/test/files/templates/invalid.erb b/vendor/supply_drop/test/files/templates/invalid.erb
new file mode 100644
index 0000000..615887c
--- /dev/null
+++ b/vendor/supply_drop/test/files/templates/invalid.erb
@@ -0,0 +1 @@
+this is a <%= if true %> template
diff --git a/vendor/supply_drop/test/files/templates/valid.erb b/vendor/supply_drop/test/files/templates/valid.erb
new file mode 100644
index 0000000..722efea
--- /dev/null
+++ b/vendor/supply_drop/test/files/templates/valid.erb
@@ -0,0 +1 @@
+this is a <%= "good" %> template
diff --git a/vendor/supply_drop/test/rsync_test.rb b/vendor/supply_drop/test/rsync_test.rb
new file mode 100644
index 0000000..b51a6b3
--- /dev/null
+++ b/vendor/supply_drop/test/rsync_test.rb
@@ -0,0 +1,57 @@
+require 'test/unit'
+require File.expand_path('../../lib/supply_drop/rsync', __FILE__)
+
+class RsyncTest < Test::Unit::TestCase
+
+ def test_build_simple_command
+ command = SupplyDrop::Rsync.command('bar', 'foo')
+ assert_equal 'rsync -az bar foo', command
+ end
+
+ def test_allows_passing_delete
+ command = SupplyDrop::Rsync.command('bar', 'foo', :delete => true)
+ assert_equal 'rsync -az --delete bar foo', command
+ end
+
+ def test_allows_specifying_an_exclude
+ command = SupplyDrop::Rsync.command('bar', 'foo', :excludes => '.git')
+ assert_equal 'rsync -az --exclude=.git bar foo', command
+ end
+
+ def test_ssh_options_keys_only_lists_existing_files
+ command = SupplyDrop::Rsync.command('.', 'foo', :ssh => { :keys => [__FILE__, "#{__FILE__}dadijofs"] })
+ assert_match /-i #{__FILE__}/, command
+ end
+
+ def test_ssh_options_ignores_keys_if_nil
+ command = SupplyDrop::Rsync.command('.', 'foo', :ssh => { :keys => nil })
+ assert_equal 'rsync -az . foo', command
+ command = SupplyDrop::Rsync.command('bar', 'foo')
+ assert_equal 'rsync -az bar foo', command
+ end
+
+ def test_ssh_options_config_adds_flag
+ command = SupplyDrop::Rsync.command('.', 'foo', :ssh => { :config => __FILE__ })
+ assert_equal %Q[rsync -az -e "ssh -F #{__FILE__}" . foo], command
+ end
+
+ def test_ssh_options_port_adds_port
+ command = SupplyDrop::Rsync.command('.', 'foo', :ssh => { :port => '30022' })
+ assert_equal %Q[rsync -az -e "ssh -p 30022" . foo], command
+ end
+
+ def test_ssh_options_ignores_config_if_nil_or_false
+ command = SupplyDrop::Rsync.command('.', 'foo', :ssh => { :config => nil })
+ assert_equal 'rsync -az . foo', command
+ command = SupplyDrop::Rsync.command('.', 'foo', :ssh => { :config => false })
+ assert_equal 'rsync -az . foo', command
+ end
+
+ def test_remote_address_concatinates_things_correctly
+ assert_equal "user@box.local:/tmp", SupplyDrop::Rsync.remote_address('user', 'box.local', '/tmp')
+ end
+
+ def test_remote_address_drops_at_when_user_is_nil
+ assert_equal 'box.local:/tmp', SupplyDrop::Rsync.remote_address(nil, 'box.local', '/tmp')
+ end
+end
diff --git a/vendor/supply_drop/test/syntax_checker_test.rb b/vendor/supply_drop/test/syntax_checker_test.rb
new file mode 100644
index 0000000..15f6e73
--- /dev/null
+++ b/vendor/supply_drop/test/syntax_checker_test.rb
@@ -0,0 +1,23 @@
+require 'test/unit'
+require File.expand_path('../../lib/supply_drop/syntax_checker', __FILE__)
+
+class SyntaxCheckerTest < Test::Unit::TestCase
+
+ def test_syntax_checks_puppet_files
+ checker = SupplyDrop::SyntaxChecker.new(File.expand_path('../files', __FILE__))
+ errors = checker.validate_puppet_files
+ assert_equal 1, errors.count
+ file, error = errors.first
+ assert_match %r[manifests/invalid.pp$], file
+ assert_match %r[expected '\}'], error
+ end
+
+ def test_synatx_checks_erb_files
+ checker = SupplyDrop::SyntaxChecker.new(File.expand_path('../files', __FILE__))
+ errors = checker.validate_templates
+ assert_equal 1, errors.count
+ file, error = errors.first
+ assert_match %r[templates/invalid.erb$], file
+ assert_match %r[syntax error], error
+ end
+end