lib/guignol/commands/base.rb in guignol-0.1.2.1 vs lib/guignol/commands/base.rb in guignol-0.3.0
- old
+ new
@@ -1,88 +1,75 @@
-# Copyright (c) 2012, HouseTrip SA.
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation are those
-# of the authors and should not be interpreted as representing official policies,
-# either expressed or implied, of the authors.
-
-
+require 'thor'
require 'pathname'
require 'parallel'
-require 'guignol/instance'
-require 'guignol/array/collect_key'
+require 'guignol'
+require 'guignol/configuration'
+require 'guignol/models/instance'
+require 'core_ext/array/collect_key'
module Guignol::Commands
class Base
- def initialize(*argv)
- @all_configs = load_config_files
- check_config_consistency
- @configs = argv.map { |pattern|
- @all_configs.select { |config|
- config[:name] =~ /#{pattern}/
- }
- }.flatten.uniq
+ def initialize(patterns, options = {})
+ @configs = select_configs(patterns)
+ @options = options
end
+ # Run the block for each server in +configs+ (in parallel).
def run
- before_run or return if respond_to?(:before_run)
+ before_run(@configs) or return
+ results = {}
- Parallel.each(@configs) do |config|
- run_on_server(config)
+ Parallel.each(@configs, parallel_options) do |name,config|
+ instance = Guignol::Models::Instance.new(name, config)
+ results[name] = run_on_server(instance, @options)
end
+
+ after_run(results)
end
- protected
- def confirm(message)
- $stdout.print "#{message}? [y/N] "
- $stdout.flush
- answer = $stdin.gets
- return answer.strip =~ /y/i
+ protected
+
+ # Override in subclasses
+ def before_run(configs) ; true ; end
+
+ # Override in subclasses
+ def after_run(data) ; true ; end
+
+
+ def shell
+ Guignol::Shell.shared_shell
end
- private
- # Read & return the first available config.
- def load_config_files
- [
- Pathname.new(ENV['GUIGNOL_YML'] || '/var/nonexistent'),
- Pathname.new('guignol.yml'),
- Pathname.new('config/guignol.yml'),
- Pathname.new(ENV['HOME']).join('.guignol.yml')
- ].each do |pathname|
- next unless pathname.exist?
- return YAML.load(pathname.read)
+ def synchronize
+ (@mutex ||= Mutex.new).synchronize do
+ yield
end
- return {}
end
- def check_config_consistency
- errors = []
- errors << "Instance config lacks :name" unless @all_configs.collect_key(:name).all?
- errors << "Instance config lacks :uuid" unless @all_configs.collect_key(:uuid).all?
- errors << "Volume config lacks :uuid" unless @all_configs.collect_key(:volumes).collect_key(:uuid)
- raise errors.join(', ') if errors.any?
+
+ private
+
+
+ def parallel_options
+ if RUBY_VERSION >= '1.9.3'
+ # 1.9.3 has bugs with Excon / SSL connections
+ { :in_threads => 0 }
+ else
+ { :in_threads => @configs.size }
+ end
end
+
+ # Put all the servers matching one of the +names+ in +configs+.
+ def select_configs(patterns)
+ patterns = patterns.map { |pattern|
+ pattern.kind_of?(String) ? Regexp.new(pattern) : pattern
+ }
+ Guignol.configuration.delete_if { |name,config|
+ patterns.none? { |pattern| name.to_s =~ pattern }
+ }
+ end
+
end
end