lib/taskr/actions.rb in taskr-0.2.1 vs lib/taskr/actions.rb in taskr-0.3.0

- old
+ new

@@ -11,11 +11,11 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Taskr. If not, see <http://www.gnu.org/licenses/>. -require 'openwfe/util/scheduler' +require 'rufus/scheduler' #require 'active_resource' require 'restr' @@ -37,17 +37,18 @@ end # The base class for all Actions. # Extend this to define your own custom Action. class Base - include OpenWFE::Schedulable + include Rufus::Schedulable class_inheritable_accessor :parameters class_inheritable_accessor :description attr_accessor :parameters attr_accessor :task + attr_accessor :task_action def initialize(parameters) self.parameters = HashWithIndifferentAccess.new(parameters) end @@ -70,44 +71,65 @@ task.update_attribute(:last_triggered, Time.now) task.update_attribute(:last_triggered_error, {:type => e.class.to_s, :message => details}) raise e end end + + def to_s + "#{self.class.name}(#{parameters.inspect})" + end end # Do not extend this class. It is used internally to schedule multiple # actions per task. # # If you want to define your own custom Action, extend Taskr::Actions::Base class Multi - include OpenWFE::Schedulable + include Rufus::Schedulable attr_accessor :actions attr_accessor :task def initialize self.actions = [] end def trigger(trigger_args = {}) begin - $LOG.info("Executing task #{self.name}") + $LOG.info("Executing task #{self.task.name}") actions.each do |a| a.execute + LogEntry.info(a, "Action #{a} executed.") end # TODO: maybe we should store last_triggered time on a per-action basis? task.update_attribute(:last_triggered, Time.now) + task.update_attribute(:last_triggered_error, nil) rescue => e $LOG.error(e) - $LOG.debug("#{e.stacktrace}") + $LOG.debug("#{e.backtrace}") task.update_attribute(:last_triggered, Time.now) - task.update_attribute(:last_triggered_error, e) + task.update_attribute(:last_triggered_error, {:type => e.class.to_s, :details => "#{e.message}"}) + # FIXME: Maybe actions should be responseible for logging their errors, otherwise we double-log the same error. + LogEntry.error(task, "Task #{task} raised an exception: \n#{e.class}: #{e.message}\n#{e.backtrace}") raise e end end end + class RotateTaskLog < Base + self.parameters = ['delete_old_log_entries_after_days'] + self.description = "Deletes old task log entries from this Taskr server's database." + + def execute + num = parameters['delete_old_log_entries_after_days'].to_i + + cond = ['timestamp < ?', Time.now - num.days] + LogEntry.delete_all(cond) + LogEntry.debug(task_action, "Deleted log entries with conditions: #{cond.inspect}") + end + end + class Shell < Base self.parameters = ['command', 'as_user'] self.description = "Execute a shell command (be careful!)" def execute @@ -116,32 +138,62 @@ cmd = parameters['command'] else user = nil end - if user - `sudo -u #{user} #{cmd}` - else - `#{cmd}` + unless user.blank? + cmd = "sudo -u #{user} #{cmd}" end + outio = StringIO.new + errio = StringIO.new + old_stdout, $stdout = $stdout, outio + old_stderr, $stderr = $stderr, errio + + out = `#{cmd}` + + err = errio.string + out = outio.string + LogEntry.debug(task_action, out) unless out.blank? + LogEntry.error(task_action, err) unless err.blank? + + $stdout = old_stdout + $stderr = old_stderr + unless $?.success? - raise "Shell command failed (#{$?}): #{cmd}" + msg = "Shell command #{cmd.inspect} failed (returned code #{$?}): #{out}" + LogEntry.error(task_action, msg) + raise msg end end end class Ruby < Base self.parameters = ['code'] self.description = "Execute some Ruby code." def execute + outio = StringIO.new + errio = StringIO.new + old_stdout, $stdout = $stdout, outio + old_stderr, $stderr = $stderr, errio + code = parameters['code'] - eval code + eval(code) + + err = errio.string + out = outio.string + LogEntry.debug(task_action, out) unless out.blank? + LogEntry.error(task_action, err) unless err.blank? + + $stdout = old_stdout + $stderr = old_stderr end end - + + +# This is too complicated... we use Restr instead. # class ActiveResource < Base # self.parameters = ['site', 'resource', 'action', 'parameters'] # self.description = "Perform a REST call on a remote service using ActiveResource." # # def execute @@ -205,12 +257,21 @@ auth = {} auth['username'] = parameters['username'] if parameters['username'] auth['password'] = parameters['password'] if parameters['password'] end - Restr.logger = $LOG - Restr.do(parameters['method'], parameters['url'], parameters['params'], auth) + if parameters['params'].kind_of? String + params2 = {} + parameters['params'].split('&').collect do |p| + key, value = p.split('=') + params2[key] = value + end + parameters['params'] = params2 + end + + Restr.logger = LogEntry.logger_for_action(task_action) + Restr.do(parameters['method'], parameters['url'], (parameters['params'] unless parameters['params'].blank?), auth) end end class Howlr < Rest self.parameters = ['url', 'from', 'recipients', 'subject', 'body', 'username', 'password', 'content_type'] @@ -244,10 +305,10 @@ :ruby_code => parameters['ruby_code']#, #:shell_command => parameters['shell_command'] } - Restr.logger = $LOG + Restr.logger = LogEntry.logger_for_action(task_action) Restr.post(parameters['url'], data) end end end end \ No newline at end of file