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.
- data/foreman_hooks.gemspec +2 -2
- data/lib/foreman_hooks.rb +85 -0
- data/lib/foreman_hooks/callback_hooks.rb +22 -0
- data/lib/foreman_hooks/engine.rb +0 -15
- data/lib/foreman_hooks/orchestration_hook.rb +2 -2
- data/lib/foreman_hooks/util.rb +0 -59
- metadata +3 -3
- data/lib/foreman_hooks/hooks_observer.rb +0 -28
data/foreman_hooks.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "foreman_hooks"
|
3
3
|
|
4
|
-
s.version = "0.3.
|
5
|
-
s.date = "2013-
|
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"
|
data/lib/foreman_hooks.rb
CHANGED
@@ -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
|
data/lib/foreman_hooks/engine.rb
CHANGED
@@ -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
|
data/lib/foreman_hooks/util.rb
CHANGED
@@ -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.
|
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-
|
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
|