foreman_hooks 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,8 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "foreman_hooks"
3
3
 
4
- s.version = "0.3.1"
5
- s.date = "2013-04-07"
4
+ s.version = "0.3.2"
5
+ s.date = "2013-05-30"
6
6
 
7
7
  s.summary = "Run custom hook scripts on Foreman events"
8
8
  s.description = "Plugin engine for Foreman that enables running custom hook scripts on Foreman events"
@@ -1,3 +1,88 @@
1
1
  module ForemanHooks
2
2
  require 'foreman_hooks/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
3
+ require 'foreman_hooks/util'
4
+ require 'foreman_hooks/callback_hooks'
5
+ require 'foreman_hooks/orchestration_hook'
6
+
7
+ class << self
8
+ def hooks_root
9
+ File.join(Rails.application.root, 'config', 'hooks')
10
+ end
11
+
12
+ # Find all executable hook files under $hook_root/model_name/event_name/
13
+ def discover_hooks
14
+ hooks = {}
15
+ Dir.glob(File.join(hooks_root, '**', '*')) do |filename|
16
+ next if filename.end_with? '~'
17
+ next if filename.end_with? '.bak'
18
+ next if File.directory? filename
19
+ next unless File.executable? filename
20
+
21
+ relative = filename[hooks_root.size..-1]
22
+ next unless relative =~ %r{^/(.+)/([^/]+)/([^/]+)$}
23
+ klass = $1.camelize
24
+ event = $2
25
+ script_name = $3
26
+ hooks[klass] ||= {}
27
+ hooks[klass][event] ||= []
28
+ hooks[klass][event] << filename
29
+ logger.debug "Found hook to #{klass.to_s}##{event}, filename #{script_name}"
30
+ end
31
+ hooks
32
+ end
33
+
34
+ # {'ModelClass' => {'event_name' => ['/path/to/01.sh', '/path/to/02.sh']}}
35
+ def hooks
36
+ unless @hooks
37
+ @hooks = discover_hooks
38
+ @hooks.each do |klass,events|
39
+ events.each do |event,hooks|
40
+ logger.info "Finished registering #{hooks.size} hooks for #{klass}##{event}"
41
+ hooks.sort!
42
+ end
43
+ end
44
+ end
45
+ @hooks
46
+ end
47
+
48
+ # ['event1', 'event2']
49
+ def events(klass = nil)
50
+ filtered = if klass
51
+ klass = klass.name if klass.kind_of? Class
52
+ Hash[hooks.select { |k,e| k == klass }]
53
+ else
54
+ hooks
55
+ end
56
+ @events = filtered.values.map(&:keys).flatten.uniq.map(&:to_sym) unless @events
57
+ @events
58
+ end
59
+
60
+ def find_hooks(klass, event)
61
+ klass = klass.name if klass.kind_of? Class
62
+ return unless filtered = hooks[klass]
63
+ return unless filtered = filtered[event.to_s]
64
+ return if filtered.empty?
65
+ filtered
66
+ end
67
+
68
+ def logger; Rails.logger; end
69
+ end
70
+ end
71
+
72
+ module ActiveSupport::Dependencies
73
+ class << self
74
+ def load_missing_constant_with_hooks(from_mod, constant_name)
75
+ ret = load_missing_constant_without_hooks(from_mod, constant_name)
76
+ ForemanHooks.hooks.each do |klass,events|
77
+ next unless ret.name == klass
78
+ if events.keys.detect { |event| ['create', 'update', 'destroy'].include? event }
79
+ ret.send(:include, ForemanHooks::OrchestrationHook) unless ret.ancestors.include?(ForemanHooks::OrchestrationHook)
80
+ end
81
+ ret.send(:include, ForemanHooks::CallbackHooks) unless ret.ancestors.include?(ForemanHooks::CallbackHooks)
82
+ end
83
+ ret
84
+ end
85
+
86
+ alias_method_chain :load_missing_constant, :hooks
87
+ end
3
88
  end
@@ -0,0 +1,22 @@
1
+ require 'foreman_hooks/util'
2
+
3
+ module ForemanHooks::CallbackHooks
4
+ extend ActiveSupport::Concern
5
+ include ForemanHooks::Util
6
+
7
+ included do
8
+ ForemanHooks.events(self).each do |event|
9
+ filter, name = event.to_s.split('_', 2)
10
+ next unless name
11
+
12
+ set_callback name, "#{event}_hooks"
13
+ define_method("#{event}_hooks") do
14
+ Rails.logger.debug "Observed #{event} hook on #{self}"
15
+ return unless hooks = ForemanHooks.find_hooks(self.class, event)
16
+
17
+ Rails.logger.debug "Running #{hooks.size} hooks for #{self.class.to_s}##{event}"
18
+ hooks.each { |filename| exec_hook(filename, event.to_s, to_s) }
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,21 +1,6 @@
1
1
  require 'foreman_hooks'
2
- require 'foreman_hooks/hooks_observer'
3
- require 'foreman_hooks/orchestration_hook'
4
2
 
5
3
  module ForemanHooks
6
4
  class Engine < ::Rails::Engine
7
- config.to_prepare do
8
- # Register an observer to all classes with hooks present
9
- ForemanHooks::HooksObserver.observed_classes.each do |klass|
10
- klass.observers << ForemanHooks::HooksObserver
11
- klass.instantiate_observers
12
- end
13
-
14
- # Find any orchestration related hooks and register in those classes
15
- ForemanHooks::HooksObserver.hooks.each do |klass,events|
16
- orchestrate = events.keys.detect { |event| ['create', 'update', 'destroy'].include? event }
17
- klass.send(:include, ForemanHooks::OrchestrationHook) if orchestrate
18
- end
19
- end
20
5
  end
21
6
  end
@@ -25,7 +25,7 @@ module ForemanHooks::OrchestrationHook
25
25
  logger.warn "#{self.class.to_s} doesn't support orchestration, can't run orchestration hooks: use Rails events instead"
26
26
  end
27
27
 
28
- return unless hooks = find_hooks(self.class, event)
28
+ return unless hooks = ForemanHooks.find_hooks(self.class, event)
29
29
  logger.debug "Queueing #{hooks.size} hooks for #{self.class.to_s}##{event}"
30
30
 
31
31
  counter = 0
@@ -33,7 +33,7 @@ module ForemanHooks::OrchestrationHook
33
33
  basename = File.basename(filename)
34
34
  priority = basename =~ /^(\d+)/ ? $1 : 10000 + (counter += 1)
35
35
  logger.debug "Queuing hook #{basename} for #{self.class.to_s}##{event} at priority #{priority}"
36
- queue.create(:name => "Hook: #{basename}", :priority => priority,
36
+ queue.create(:name => "Hook: #{basename}", :priority => priority.to_i,
37
37
  :action => [HookRunner.new(filename, self, event.to_s),
38
38
  event.to_s == 'destroy' ? :hook_execute_del : :hook_execute_set])
39
39
  end
@@ -3,65 +3,6 @@ require 'open3'
3
3
  module ForemanHooks::Util
4
4
  extend ActiveSupport::Concern
5
5
 
6
- included do
7
- class_eval do
8
- def self.hooks_root
9
- File.join(Rails.application.root, 'config', 'hooks')
10
- end
11
-
12
- # Find all executable hook files under $hook_root/model_name/event_name/
13
- def self.discover_hooks
14
- hooks = {}
15
- Dir.glob(File.join(hooks_root, '**', '*')) do |filename|
16
- next if filename.end_with? '~'
17
- next if filename.end_with? '.bak'
18
- next if File.directory? filename
19
- next unless File.executable? filename
20
-
21
- relative = filename[hooks_root.size..-1]
22
- next unless relative =~ %r{^/(.+)/([^/]+)/([^/]+)$}
23
- klass = $1.camelize.constantize
24
- event = $2
25
- script_name = $3
26
- hooks[klass] ||= {}
27
- hooks[klass][event] ||= []
28
- hooks[klass][event] << filename
29
- logger.debug "Found hook to #{klass.to_s}##{event}, filename #{script_name}"
30
- end
31
- hooks
32
- end
33
-
34
- # {ModelClass => {'event_name' => ['/path/to/01.sh', '/path/to/02.sh']}}
35
- def self.hooks
36
- unless @hooks
37
- @hooks = discover_hooks
38
- @hooks.each do |klass,events|
39
- events.each do |event,hooks|
40
- logger.info "Finished registering #{hooks.size} hooks for #{klass.to_s}##{event}"
41
- hooks.sort!
42
- end
43
- end
44
- end
45
- @hooks
46
- end
47
-
48
- # ['event1', 'event2']
49
- def self.events
50
- @events = hooks.values.map(&:keys).flatten.uniq.map(&:to_sym) unless @events
51
- @events
52
- end
53
-
54
- def self.logger; Rails.logger; end
55
- end
56
- end
57
-
58
- def find_hooks(klass, event)
59
- return unless filtered = self.class.hooks[klass]
60
- return unless filtered = filtered[event.to_s]
61
- return if filtered.empty?
62
- filtered
63
- end
64
-
65
6
  def exec_hook(*args)
66
7
  logger.debug "Running hook: #{args.join(' ')}"
67
8
  success = if defined? Bundler && Bundler.responds_to(:with_clean_env)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: foreman_hooks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-07 00:00:00.000000000 Z
12
+ date: 2013-05-30 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Plugin engine for Foreman that enables running custom hook scripts on
15
15
  Foreman events
@@ -32,8 +32,8 @@ files:
32
32
  - examples/log.sh
33
33
  - foreman_hooks.gemspec
34
34
  - lib/foreman_hooks.rb
35
+ - lib/foreman_hooks/callback_hooks.rb
35
36
  - lib/foreman_hooks/engine.rb
36
- - lib/foreman_hooks/hooks_observer.rb
37
37
  - lib/foreman_hooks/orchestration_hook.rb
38
38
  - lib/foreman_hooks/util.rb
39
39
  - test/test_helper.rb
@@ -1,28 +0,0 @@
1
- require 'foreman_hooks/util'
2
-
3
- module ForemanHooks
4
- class HooksObserver < ActiveRecord::Observer
5
- include ForemanHooks::Util
6
-
7
- # Override ActiveRecord::Observer
8
- def self.observed_classes
9
- hooks.keys
10
- end
11
-
12
- def respond_to?(method)
13
- return true if super
14
- self.class.events.include? method
15
- end
16
-
17
- def method_missing(event, *args)
18
- obj = args.first
19
- logger.debug "Observed #{event} hook on #{obj}"
20
- return unless hooks = find_hooks(obj.class, event)
21
-
22
- logger.debug "Running #{hooks.size} hooks for #{obj.class.to_s}##{event}"
23
- hooks.each { |filename| exec_hook(filename, event.to_s, obj.to_s) }
24
- end
25
-
26
- def logger; Rails.logger; end
27
- end
28
- end