lib/screwcap/task.rb in screwcap-0.2 vs lib/screwcap/task.rb in screwcap-0.3

- old
+ new

@@ -1,68 +1,62 @@ class Task < Screwcap::Base + include MessageLogger + def initialize(opts = {}, &block) super self.__name = opts[:name] self.__options = opts self.__commands = [] - self.__command_sets = [] + self.__command_sets = opts[:command_sets] || [] self.__server_names = [] + self.__block = block if opts[:command_set] == true if opts[:server] and opts[:servers].nil? self.__server_names << opts[:server] else self.__server_names = opts[:servers] end - validate(opts[:deployment_servers]) + validate(opts[:deployment_servers]) unless opts[:validate] == false end # run a command. basically just pass it a string containing the command you want to run. def run arg, options = {} + if arg.class == Symbol - self.__commands << {:command => self.send(arg), :type => :remote} + self.__commands << options.merge({:command => self.send(arg), :type => :remote, :from => self.__name}) else - self.__commands << {:command => arg, :type => :remote} + self.__commands << options.merge({:command => arg, :type => :remote, :from => self.__name}) end end def scp options = {} self.__commands << options.merge({:type => :scp}) end # run a command. basically just pass it a string containing the command you want to run. def local arg, options = {} if arg.class == Symbol - self.__commands << {:command => self.send(arg), :type => :local} + self.__commands << options.merge({:command => self.send(arg), :type => :local, :from => self.__name}) else - self.__commands << {:command => arg, :type => :local} + self.__commands << options.merge({:command => arg, :type => :local, :from => self.__name}) end - end - - - def execute! - threads = [] - self.__servers.each do |_server| - _server.__addresses.each do |_address| - if self.__options[:parallel] == false - execute_on(_server, _address) - else - threads << Thread.new(_server, _address) { |server, address| execute_on(server, address) } - end + if failure_cmd = self.__commands.last[:onfailure] + unless self.__command_sets.find {|cs| cs.__name == failure_cmd } + raise ScrewCap::ConfigurationError, "Could not find failure command set named '#{failure_cmd}' for task '#{self.__name}'" end end - threads.each {|t| t.join } end protected def method_missing(m, *args) if m.to_s[0..1] == "__" or [:run].include?(m) or m.to_s.reverse[0..0] == "=" super(m, args.first) else - if cs = self.__command_sets.find {|cs| cs.name == m } + if cs = self.__command_sets.find {|cs| cs.__name == m } # eval what is in the block clone_table_for(cs) cs.__commands = [] cs.instance_eval(&cs.__block) self.__commands += cs.__commands @@ -74,11 +68,11 @@ private def clone_table_for(object) self.table.each do |k,v| - object.set(k, v) unless [:__command_sets, :name, :__commands, :__options].include?(k) + object.set(k, v) unless [:__block, :__tasks, :__name, :__command_sets, :__commands, :__options].include?(k) end end def validate(servers) raise Screwcap::ConfigurationError, "Could not find a server to run this task on. Please specify :server => :servername or :servers => [:server1, :server2] in the task_for directive." if self.__server_names.blank? @@ -87,52 +81,8 @@ raise Screwcap::ConfigurationError, "Could not find a server to run this task on. Please specify :server => :servername or :servers => [:server1, :server2] in the task_for directive." unless servers.map(&:name).include?(server_name) end # finally map the actual server objects via name self.__servers = self.__server_names.map {|name| servers.find {|s| s.name == name } } - end - - def execute_on(server, address) - begin - log blue("\n*** BEGIN executing task #{self.__name} on #{server.name} with address #{address}\n") unless self.__options[:silent] == true - - server.__with_connection_for(address) do |ssh| - error = false - self.__commands.each do |command| - next if error and self.__options[:stop_on_errors] - - if command[:type] == :remote - log green(" I: (#{address}): #{command[:command]}\n") - - ssh.exec! command[:command] do |ch,stream,data| - if stream == :stderr - error = true - errorlog red(" E: (#{address}): #{data}") - else - log green(" O: (#{address}): #{data}") - end - end # ssh.exec - elsif command[:type] == :local - ret = `#{command[:command]}` - if $?.to_i == 0 - log blue(" I: (local): #{command[:command]}\n") - log blue(" O: (local): #{ret}\n") - else - log blue(" I: (local): #{command[:command]}\n") - errorlog red(" O: (local): #{ret}\n") - end - elsif command[:type] == :scp - server.__upload_to!(address, command[:local], command[:remote]) - log green(" I: (#{address}): SCP #{command[:local]} to #{server.__user}@#{address}:#{command[:remote]}") - end - end # commands.each - end # net.ssh start - rescue Net::SSH::AuthenticationFailed => e - raise Net::SSH::AuthenticationFailed, "Authentication failed for server named #{server.name}. Please check your authentication credentials." - rescue Exception => e - errorlog red(" F: (#{address}): #{e}") - ensure - log blue("*** END executing task #{self.__name} on #{server.name} with address #{address}\n\n") unless self.__options[:silent] == true - end end end