diff options
author | Anton Aksola <anton.aksola@nebula.fi> | 2015-08-28 11:05:18 +0300 |
---|---|---|
committer | Anton Aksola <anton.aksola@nebula.fi> | 2015-08-28 11:05:18 +0300 |
commit | 0906e02a8538b698ed8bd7c72e6a09d3e809b67a (patch) | |
tree | d494ee43f71d41034efa98f5b5ab59ab5500207a /lib/oxidized/hook.rb | |
parent | 18cf96b36e54cb52c678e4e6395e595b6f9b4159 (diff) |
Initial implementation of the hook feature
The current implementation is modular and allows users to define hooks
in several ways:
* Use one of the built-in hook types (currently only 'exec')
* Define their own Hook classes inside ~/.config/oxidized/hook
Exec hook type runs a user defined command with or without shell. It
populates a bunch of environment variables with metadata. The command
can either be run as synchronous or asynchronous. The default is
synchronous.
Diffstat (limited to 'lib/oxidized/hook.rb')
-rw-r--r-- | lib/oxidized/hook.rb | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/lib/oxidized/hook.rb b/lib/oxidized/hook.rb new file mode 100644 index 0000000..2763c4f --- /dev/null +++ b/lib/oxidized/hook.rb @@ -0,0 +1,88 @@ +module Oxidized +class HookManager + class << self + def from_config cfg + mgr = new + cfg.hooks.each do |name,h_cfg| + h_cfg.events.each do |event| + mgr.register event.to_sym, name, h_cfg.type, h_cfg + end + end + mgr + end + end + + # HookContext is passed to each hook. It can contain anything related to the + # event in question. At least it contains the event name + class HookContext < OpenStruct; end + + # RegisteredHook is a container for a Hook instance + class RegisteredHook < Struct.new(:name, :hook); end + + Events = [ + :node_success, + :node_fail, + :post_store, + ] + attr_reader :registered_hooks + + def initialize + @registered_hooks = Hash.new {|h,k| h[k] = []} + end + + def register event, name, hook_type, cfg + unless Events.include? event + raise ArgumentError, + "unknown event #{event}, available: #{Events.join ','}" + end + + Oxidized.mgr.add_hook hook_type + begin + hook = Oxidized.mgr.hook.fetch(hook_type).new + rescue KeyError + raise KeyError, "cannot find hook #{hook_type.inspect}" + end + + hook.cfg = cfg + + @registered_hooks[event] << RegisteredHook.new(name, hook) + Log.debug "Hook #{name.inspect} registered #{hook.class} for event #{event.inspect}" + end + + def handle event, **ctx_params + ctx = HookContext.new ctx_params + ctx.event = event + + @registered_hooks[event].each do |r_hook| + begin + r_hook.hook.run_hook ctx + rescue => e + Log.error "Hook #{r_hook.name} (#{r_hook.hook}) failed " + + "(#{e.inspect}) for event #{event.inspect}" + end + end + end +end + +# Hook abstract base class +class Hook + attr_accessor :cfg + + def initialize + end + + def cfg=(cfg) + @cfg = cfg + validate_cfg! if self.respond_to? :validate_cfg! + end + + def run_hook ctx + raise NotImplementedError + end + + def log(msg, level=:info) + Log.send(level, "#{self.class.name}: #{msg}") + end + +end +end |