foreman_hooks 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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