lib/vagabond/vagabond.rb in vagabond-0.2.8 vs lib/vagabond/vagabond.rb in vagabond-0.2.10

- old
+ new

@@ -1,9 +1,10 @@ +#encoding: utf-8 require 'thor' require 'chef/knife/core/ui' require 'vagabond/uploader' -require File.join(File.dirname(__FILE__), 'cookbooks/lxc/libraries/lxc.rb') +require 'elecksee/lxc' %w(constants errors vagabondfile internal_configuration helpers).each do |dep| require "vagabond/#{dep}" end @@ -15,65 +16,66 @@ require "vagabond/actions/#{File.basename(action).sub('.rb', '')}" end module Vagabond class Vagabond < Thor + + DISABLE_HOST_SOLO_ON = %w(status init) include Thor::Actions include Helpers Actions.constants.each do |const| klass = Actions.const_get(const) include klass if klass.is_a?(Module) end - attr_reader :name - attr_reader :vagabondfile - attr_reader :internal_config - attr_reader :ui - attr_reader :options - attr_accessor :mappings_key attr_accessor :lxc attr_accessor :config attr_accessor :action CLI_OPTIONS = lambda do - class_option(:debug, - :type => :boolean, - :default => false - ) + class_option(:debug, + :type => :boolean, + :default => false + ) - class_option(:force_solo, - :aliases => '--force-configure', - :type => :boolean, - :default => false, - :desc => 'Force configuration of system' - ) + class_option(:force_solo, + :aliases => '--force-configure', + :type => :boolean, + :default => false, + :desc => 'Force configuration of system' + ) - class_option(:color, - :type => :boolean, - :default => true, - :desc => 'Enable/disable colorized output' - ) + class_option(:color, + :type => :boolean, + :default => true, + :desc => 'Enable/disable colorized output' + ) - class_option(:vagabond_file, - :aliases => '-f', - :type => :string, - :desc => 'Provide path to Vagabondfile' - ) - - class_option(:local_server, - :type => :boolean, - :default => true, - :desc => 'Enable/disable local Chef server usage if available' - ) + class_option(:vagabond_file, + :aliases => '-f', + :type => :string, + :desc => 'Provide path to Vagabondfile' + ) + + class_option(:local_server, + :type => :boolean, + :default => true, + :desc => 'Enable/disable local Chef server usage if available' + ) + + class_option(:callbacks, + :type => :boolean, + :default => true, + :desc => 'Enable/disable action callbacks' + ) end CLI_OPTIONS.call - # action:: Action to perform # name:: Name of vagabond # config:: Hash configuration # # Creates an instance @@ -99,47 +101,60 @@ self.send("_#{meth}_options").each do |opts| method_option(*opts) end end define_method meth do |*args| - setup(meth, *args) - execute + @original_args = args.dup + unless(args.include?(:no_setup)) + setup(meth, *args) + end + result = execute + callbacks(meth) + chain! + result end end end COMMANDS.call protected + def attributes + if(config[:attributes]) + if(config[:attributes].is_a?(Hash)) + JSON.dump(config[:attributes]) + else + config[:attributes].to_s + end + end + end + def version setup_ui ui.info "#{ui.color('Vagabond:', :yellow, :bold)} - Advocating idleness and work-shyness" ui.info " #{ui.color('Version:', :blue)} - #{VERSION.version} (#{VERSION.codename})" exit end def execute - self.send("_#{@action}") + self.send("_#{action}") end def setup(action, name=nil, *args) @action = action @name = name - @options = options.dup - if(args.last.is_a?(Hash)) - _ui = args.last.delete(:ui) - @options.merge!(args.last) - end - @leftover_args = args - setup_ui(_ui) - load_configurations - if(respond_to?(check = "#{action}_validate?".to_sym)) - validate! if send(check) + hash_args = args.detect{|x|x.is_a?(Hash)} + if(hash_args) + args.delete(hash_args) + _ui = hash_args.delete(:ui) + base_setup(_ui) + config.merge!(hash_args) else - validate! + base_setup end + @leftover_args = args end def name_required! unless(name) ui.fatal "Node name is required!" @@ -148,60 +163,32 @@ end def provision_solo(dir) ui.info "#{ui.color('Vagabond:', :bold)} Provisioning node: #{ui.color(name, :magenta)}" lxc.container_ip(20) # force wait for container to appear and do so quietly - direct_container_command( + cmd = direct_container_command( "chef-solo -c #{File.join(dir, 'solo.rb')} -j #{File.join(dir, 'dna.json')}", :live_stream => STDOUT ) + raise VagabondError::NodeProvisionFailed.new("Failed to provision: #{name}") unless cmd end - def load_configurations - @vagabondfile = Vagabondfile.new(options[:vagabond_file], :allow_missing) - options[:sudo] = sudo - # TODO: provide action call back for full or partial solo disable - if((@action.to_s == 'status' && lxc_installed?) || @action.to_s == 'init') - options[:disable_solo] = true - end - Chef::Log.init('/dev/null') unless options[:debug] - Lxc.use_sudo = @vagabondfile[:sudo].nil? ? true : @vagabondfile[:sudo] - @internal_config = InternalConfiguration.new(@vagabondfile, ui, options) - options[:disable_solo] = false if @action.to_s == 'init' - @config = @vagabondfile[:boxes][name] - @lxc = Lxc.new(@internal_config[mappings_key][name] || '____nonreal____') - if(options[:local_server] && lxc_installed?) - if(@vagabondfile[:local_chef_server] && @vagabondfile[:local_chef_server][:enabled]) - srv_name = @internal_config[:mappings][:server] - srv = Lxc.new(srv_name) if srv_name - if(srv_name && srv.running?) - proto = @vagabondfile[:local_chef_server][:zero] ? 'http' : 'https' - options[:knife_opts] = " --server-url #{proto}://#{srv.container_ip(10, true)}" - else - unless(@action.to_sym == :status || name.to_s =='server') - ui.warn 'Local chef server is not currently running!' unless @action.to_sym == :status - end - end - end - end - end - def validate! if(name.to_s == 'server') ui.fatal "RESERVED node name supplied: #{ui.color(name, :red)}" - ui.info ui.color(" -> Try: vagabond server #{@action}", :cyan) + ui.info ui.color(" -> Try: vagabond server #{action}", :cyan) raise VagabondError::ReservedName.new(name) end if(name && config.nil? && !options[:disable_name_validate]) ui.fatal "Invalid node name supplied: #{ui.color(name, :red)}" ui.info ui.color(" -> Available: #{vagabondfile[:nodes].keys.sort.join(', ')}", :cyan) raise VagabondError::InvalidName.new(name) end end def check_existing! - if(@lxc.exists?) + if(lxc.exists?) ui.error "LXC: #{name} already exists!" true end end @@ -211,22 +198,19 @@ def vagabond_dir File.join(base_dir, '.vagabond') end - def lxc_installed? - system('which lxc-info > /dev/null') - end - def wait_for_completion(type=nil) + @threads ||= [] if(type) - Array(@threads[:type]).map(&:join) + Array(@threads[type]).collect{|hsh| hsh[:thread]}.map(&:join) else - @threads.values.map do |threads| - threads.each do |thread_set| - Array(thread_set).map(&:join) - end - end + @threads.values.flatten.collect{|hsh| hsh[:thread]}.map(&:join) end + end + + def tasks(type=nil) + type ? @threads[type] : @threads end end end