From d385da49ef6c17c64cf8be66002f5744c1ee38f7 Mon Sep 17 00:00:00 2001 From: elijah Date: Tue, 23 Oct 2012 03:50:52 -0700 Subject: patched supply_drop gem and vendored it --- Gemfile | 30 +++++ Gemfile.lock | 24 +++- bin/leap | 3 +- leap_cli.gemspec | 8 +- lib/leap_cli.rb | 6 +- lib/leap_cli/version.rb | 4 +- vendor/supply_drop/.gitignore | 4 + vendor/supply_drop/.rvmrc | 1 + vendor/supply_drop/.travis.yml | 4 + vendor/supply_drop/Gemfile | 6 + vendor/supply_drop/Gemfile.lock | 47 ++++++++ vendor/supply_drop/README.md | 128 +++++++++++++++++++++ vendor/supply_drop/Rakefile | 24 ++++ vendor/supply_drop/lib/supply_drop.rb | 12 ++ .../lib/supply_drop/async_enumerable.rb | 19 +++ vendor/supply_drop/lib/supply_drop/plugin.rb | 94 +++++++++++++++ vendor/supply_drop/lib/supply_drop/rsync.rb | 45 ++++++++ .../supply_drop/lib/supply_drop/syntax_checker.rb | 21 ++++ vendor/supply_drop/lib/supply_drop/tasks.rb | 96 ++++++++++++++++ vendor/supply_drop/lib/supply_drop/thread_pool.rb | 39 +++++++ vendor/supply_drop/lib/supply_drop/util.rb | 23 ++++ .../supply_drop/lib/supply_drop/writer/batched.rb | 22 ++++ vendor/supply_drop/lib/supply_drop/writer/file.rb | 23 ++++ .../lib/supply_drop/writer/streaming.rb | 16 +++ vendor/supply_drop/supply_drop.gemspec | 13 +++ vendor/supply_drop/test/async_test.rb | 67 +++++++++++ vendor/supply_drop/test/files/manifests/invalid.pp | 1 + vendor/supply_drop/test/files/manifests/valid.pp | 9 ++ .../supply_drop/test/files/templates/invalid.erb | 1 + vendor/supply_drop/test/files/templates/valid.erb | 1 + vendor/supply_drop/test/rsync_test.rb | 57 +++++++++ vendor/supply_drop/test/syntax_checker_test.rb | 23 ++++ 32 files changed, 860 insertions(+), 11 deletions(-) create mode 100644 vendor/supply_drop/.gitignore create mode 100644 vendor/supply_drop/.rvmrc create mode 100644 vendor/supply_drop/.travis.yml create mode 100644 vendor/supply_drop/Gemfile create mode 100644 vendor/supply_drop/Gemfile.lock create mode 100644 vendor/supply_drop/README.md create mode 100644 vendor/supply_drop/Rakefile create mode 100644 vendor/supply_drop/lib/supply_drop.rb create mode 100644 vendor/supply_drop/lib/supply_drop/async_enumerable.rb create mode 100644 vendor/supply_drop/lib/supply_drop/plugin.rb create mode 100644 vendor/supply_drop/lib/supply_drop/rsync.rb create mode 100644 vendor/supply_drop/lib/supply_drop/syntax_checker.rb create mode 100644 vendor/supply_drop/lib/supply_drop/tasks.rb create mode 100644 vendor/supply_drop/lib/supply_drop/thread_pool.rb create mode 100644 vendor/supply_drop/lib/supply_drop/util.rb create mode 100644 vendor/supply_drop/lib/supply_drop/writer/batched.rb create mode 100644 vendor/supply_drop/lib/supply_drop/writer/file.rb create mode 100644 vendor/supply_drop/lib/supply_drop/writer/streaming.rb create mode 100644 vendor/supply_drop/supply_drop.gemspec create mode 100644 vendor/supply_drop/test/async_test.rb create mode 100644 vendor/supply_drop/test/files/manifests/invalid.pp create mode 100644 vendor/supply_drop/test/files/manifests/valid.pp create mode 100644 vendor/supply_drop/test/files/templates/invalid.erb create mode 100644 vendor/supply_drop/test/files/templates/valid.erb create mode 100644 vendor/supply_drop/test/rsync_test.rb create mode 100644 vendor/supply_drop/test/syntax_checker_test.rb 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 -- cgit v1.2.3