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.
- 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
|