foreman_hooks 0.3.12 → 0.3.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +92 -7
- data/examples/{hook_functions.sh → bash/hook_functions.sh} +0 -0
- data/examples/{log.sh → bash/log.sh} +0 -0
- data/examples/python/functions.py +37 -0
- data/examples/python/host/managed/create/10-logger.py +52 -0
- data/extra/foreman-debug.sh +6 -0
- data/lib/foreman_hooks.rb +2 -15
- data/lib/foreman_hooks/as_dependencies_hook.rb +14 -0
- data/lib/foreman_hooks/callback_hooks.rb +5 -1
- data/lib/foreman_hooks/engine.rb +11 -1
- data/lib/foreman_hooks/orchestration_hook.rb +9 -7
- data/lib/foreman_hooks/util.rb +29 -2
- data/lib/tasks/hooks.rake +20 -2
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ada8bb38440801209fabcb38b2bea702e6364f0e9cdd0bb8e074060b3c46450a
|
4
|
+
data.tar.gz: ca37f997197dde8d000ce21d4ebd0bb938803cb7a3ff46dd2a8ee335634e396a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9da94d17eff07e19d3f02014a007f01aa5d33e113417eae10f3fcfb01edb7bb90a6d9e6f5f59ac7a8547b26b4aa1b875c7f02b4cac98c426dd44aaa47519f7dc
|
7
|
+
data.tar.gz: b97ee982a4ac00618bad1a832e48c69981bdbbafaaa806b97f1d891fcbfbb644ee04377696a77fa146eaf3935c41e0b0054eba3dae321352e951b93ae8de475a
|
data/README.md
CHANGED
@@ -17,7 +17,8 @@ Please see the Foreman wiki for appropriate instructions:
|
|
17
17
|
The gem name is "foreman_hooks".
|
18
18
|
|
19
19
|
RPM users can install the "tfm-rubygem-foreman_hooks" or
|
20
|
-
"rubygem-foreman_hooks" packages.
|
20
|
+
"rubygem-foreman_hooks" packages. Debian/Ubuntu users can install the
|
21
|
+
"ruby-foreman-hooks" package.
|
21
22
|
|
22
23
|
# Usage
|
23
24
|
|
@@ -31,7 +32,11 @@ Examples:
|
|
31
32
|
~foreman/config/hooks/host/managed/create/50_register_system.sh
|
32
33
|
~foreman/config/hooks/host/managed/destroy/15_cleanup_database.sh
|
33
34
|
~foreman/config/hooks/smart_proxy/after_create/01_email_operations.sh
|
34
|
-
~foreman/config/hooks/audited/
|
35
|
+
~foreman/config/hooks/audited/audit/after_create/01_syslog.sh
|
36
|
+
|
37
|
+
After adding or removing hooks, restart the Foreman server to update the list
|
38
|
+
of known hooks (usually `apache2` or `httpd` when using Passenger, or
|
39
|
+
`touch ~foreman/tmp/restart.txt`).
|
35
40
|
|
36
41
|
## Objects / Models
|
37
42
|
|
@@ -54,6 +59,11 @@ and to get events for a listed object (e.g. `host/managed`):
|
|
54
59
|
|
55
60
|
## Orchestration events
|
56
61
|
|
62
|
+
_Only supported on these objects:_
|
63
|
+
|
64
|
+
* _host/managed_
|
65
|
+
* _nic/\*_
|
66
|
+
|
57
67
|
Foreman supports orchestration tasks for hosts and NICs (each network
|
58
68
|
interface) which happen when the object is created, updated and destroyed.
|
59
69
|
These tasks are shown to the user in the UI and if they fail, will
|
@@ -61,18 +71,38 @@ automatically trigger a rollback of the action. A rollback is performed as
|
|
61
71
|
an opposite action (e.g. for DHCP record creation a rollback action is
|
62
72
|
destroy).
|
63
73
|
|
64
|
-
|
74
|
+
The following hooks are executed during `around_save` Rails callback:
|
65
75
|
|
66
76
|
* `create`
|
67
77
|
* `update`
|
78
|
+
|
79
|
+
The following hooks are executed during `on_destroy` Rails callback:
|
80
|
+
|
68
81
|
* `destroy`
|
69
82
|
|
70
|
-
|
71
|
-
|
72
|
-
|
83
|
+
The following hooks are executed during `after_commit` Rails callback:
|
84
|
+
|
85
|
+
* `postcreate`
|
86
|
+
* `postupdate`
|
87
|
+
|
88
|
+
The major difference between `create` and `postcreate` (or update respectively) is how late the hook is called during save operation. In the former case when a hook fails it starts rollback and operation can be still cancelled. In the latter case object was already saved and there is no way of cancelling the operation, but all referenced data should be properly loaded. The advice is to use the latter hooks as they will likely contain all the required data (e.g. nested parameters).
|
89
|
+
|
90
|
+
Orchestration hooks can be given a priority by prefixing the filename with the
|
91
|
+
priority number, therefore it is possible to order them before or after
|
92
|
+
built-in orchestration steps (before DNS records are created for example).
|
93
|
+
Existing common priority levels are:
|
94
|
+
|
95
|
+
* _2_: Set up compute instance (create VM)
|
96
|
+
* _10_: Create DNS record
|
97
|
+
* _10_: Create DHCP reservation
|
98
|
+
* _20_: Deploy TFTP configs
|
99
|
+
* _50_: Create realm entry
|
100
|
+
* _1000_: Power up compute instance
|
73
101
|
|
74
102
|
## Rails events
|
75
103
|
|
104
|
+
_Supported on all object types._
|
105
|
+
|
76
106
|
For hooks on anything apart from hosts or NICs (which support orchestration,
|
77
107
|
as above) then the standard Rails events will be needed. These are the most
|
78
108
|
interesting events provided:
|
@@ -111,6 +141,12 @@ may want to ensure stdin is closed to prevent pipe buffer from filling.
|
|
111
141
|
| ~foreman/config/hooks/host/managed/create/50_register_system.sh \
|
112
142
|
create foo.example.com
|
113
143
|
|
144
|
+
Some arguments are available as environment variables:
|
145
|
+
|
146
|
+
Variable | Description
|
147
|
+
-------- | -----------
|
148
|
+
FOREMAN_HOOKS_USER | Username of Foreman user
|
149
|
+
|
114
150
|
Every hook within the event directory is executed in alphabetical order. For
|
115
151
|
orchestration hooks, an integer prefix in the hook filename will be used as
|
116
152
|
the priority value, so influences where it's done in relation to DNS, DHCP, VM
|
@@ -132,6 +168,54 @@ to rollback its action - in this case the first argument will change as
|
|
132
168
|
appropriate, so must be obeyed by the script (e.g. a "create" hook will be
|
133
169
|
called with "destroy" if it has to be rolled back later).
|
134
170
|
|
171
|
+
## Logging
|
172
|
+
|
173
|
+
Entries are logged at application startup and during execution of hooks, but
|
174
|
+
most will be at 'debug' level and may use the 'sql' logger. Enable this in
|
175
|
+
Foreman's `/etc/foreman/settings.yaml`:
|
176
|
+
|
177
|
+
```yaml
|
178
|
+
:logging:
|
179
|
+
:level: debug
|
180
|
+
:loggers:
|
181
|
+
:sql:
|
182
|
+
:enabled: true
|
183
|
+
```
|
184
|
+
|
185
|
+
See [Foreman manual: Debugging](https://theforeman.org/manuals/latest/index.html#7.2Debugging)
|
186
|
+
for full details.
|
187
|
+
|
188
|
+
Enabling debugging and searching the Foreman log file (`/var/log/foreman/production.log`)
|
189
|
+
for the word "hook" will find all relevant log entries.
|
190
|
+
|
191
|
+
### Hook discovery and setup
|
192
|
+
|
193
|
+
Expect to see these entries when the server starts:
|
194
|
+
|
195
|
+
* `Found hook to Host::Managed#create, filename 01_example` - for each
|
196
|
+
executable hook script in the correct location
|
197
|
+
* `Finished discovering 3 hooks for Host::Managed#create` - for each unique
|
198
|
+
event with hook scripts
|
199
|
+
* `Extending Host::Managed with foreman_hooks orchestration hooking support` -
|
200
|
+
if any orchestration (create/update/destroy) hooks exist for that object
|
201
|
+
* `Extending Host::Managed with foreman_hooks Rails hooking support` - if any
|
202
|
+
Rails events hooks exist for that object
|
203
|
+
* `Created hook method after_create on Host::Managed` - for each type of Rails
|
204
|
+
event that has hooks
|
205
|
+
|
206
|
+
### Running hooks
|
207
|
+
|
208
|
+
Expect to see these entries logged when a hooked action occurs:
|
209
|
+
|
210
|
+
* `Observed after_create hook on test.example.com` when a registered Rails
|
211
|
+
event occurs, hook will then execute immediately
|
212
|
+
* `Queuing 3 hooks for Host::Managed#create` when an orchestration action is
|
213
|
+
being set up (hook will be executed later during orchestration)
|
214
|
+
* `Queuing hook 01_example for Host::Managed#create at priority 01` for each
|
215
|
+
hook registered when setting up an orchestration action
|
216
|
+
* `Running hook: /example/config/hooks/host/managed/create/01_example create test.example.com`
|
217
|
+
as the hook (orchestration or Rails event) is executed
|
218
|
+
|
135
219
|
## Transactions
|
136
220
|
|
137
221
|
Most hooks are triggered during database transaction. This can cause
|
@@ -154,6 +238,7 @@ tools when writing scripts.
|
|
154
238
|
|
155
239
|
# More resources
|
156
240
|
|
241
|
+
* [foreman\_hooks issue tracker](https://github.com/theforeman/foreman_hooks/issues)
|
157
242
|
* [Extending Foreman quickly with hook scripts](http://m0dlx.com/blog/Extending_Foreman_quickly_with_hook_scripts.html)
|
158
243
|
* [AWS VPC Buildout With Foreman Hooks for RDNS Creation](http://www.brian2.net/posts/foreman_hooks_aws_vpc/)
|
159
244
|
* [Foreman <-> FreeIPA Integration Guide](https://bitbin.de/blog/2013/11/foreman-freeipa-integration-guide/)
|
@@ -161,7 +246,7 @@ tools when writing scripts.
|
|
161
246
|
|
162
247
|
# Copyright
|
163
248
|
|
164
|
-
Copyright (c) 2012-
|
249
|
+
Copyright (c) 2012-2017 Dominic Cleal
|
165
250
|
|
166
251
|
This program is free software: you can redistribute it and/or modify
|
167
252
|
it under the terms of the GNU General Public License as published by
|
File without changes
|
File without changes
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
#######
|
3
|
+
# To allow this module to be imported by other triggers
|
4
|
+
# execute the commands below:
|
5
|
+
# $ mkdir -p /usr/share/foreman-community/hooks
|
6
|
+
# $ touch /usr/share/foreman-community/hooks/__init__.py
|
7
|
+
# $ cp functions.py /usr/share/foreman-community/hooks/
|
8
|
+
########
|
9
|
+
import json
|
10
|
+
import sys
|
11
|
+
import tempfile
|
12
|
+
|
13
|
+
HOOK_TEMP_DIR = "/usr/share/foreman/tmp"
|
14
|
+
|
15
|
+
# HOOK_EVENT = update, create, before_destroy etc.
|
16
|
+
# HOOK_OBJECT = to_s representation of the object, e.g. host's fqdn
|
17
|
+
HOOK_EVENT, HOOK_OBJECT = (sys.argv[1], sys.argv[2])
|
18
|
+
|
19
|
+
|
20
|
+
def get_json_hook():
|
21
|
+
'''
|
22
|
+
Create JSON object to be imported by hook/trigger
|
23
|
+
Saves the data received via stdin to file.
|
24
|
+
It does not require to save to a file, but it may be useful
|
25
|
+
to troubleshooting.
|
26
|
+
'''
|
27
|
+
|
28
|
+
with tempfile.NamedTemporaryFile(
|
29
|
+
dir=HOOK_TEMP_DIR,
|
30
|
+
# set to False for troubleshooting
|
31
|
+
delete=True,
|
32
|
+
prefix="foreman_hooks.") as hook:
|
33
|
+
|
34
|
+
json_hook = sys.stdin.read()
|
35
|
+
hook.file.write(json_hook)
|
36
|
+
hook.file.flush()
|
37
|
+
return json.loads(json_hook)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
import sys
|
3
|
+
import tempfile
|
4
|
+
import subprocess
|
5
|
+
|
6
|
+
sys.path.append('/usr/share/foreman-community/hooks')
|
7
|
+
|
8
|
+
from functions import \
|
9
|
+
(HOOK_EVENT, HOOK_OBJECT, HOOK_TEMP_DIR, get_json_hook)
|
10
|
+
|
11
|
+
PREFIX = "created_by_hook-{}".format(sys.argv[0].split('/')[-1])
|
12
|
+
|
13
|
+
HOOK_JSON = get_json_hook()
|
14
|
+
|
15
|
+
cmd = ['logger']
|
16
|
+
|
17
|
+
# read the information received
|
18
|
+
if HOOK_JSON.get('host'):
|
19
|
+
hostname = HOOK_JSON.get('host').get('name', None)
|
20
|
+
if hostname:
|
21
|
+
cmd.append('System:{0}'.format(hostname))
|
22
|
+
|
23
|
+
mac_address = HOOK_JSON.get('host').get('mac', None)
|
24
|
+
if mac_address:
|
25
|
+
cmd.append('MAC:{0}'.format(mac_address))
|
26
|
+
|
27
|
+
operating_system = HOOK_JSON.get('host').get('operatingsystem_name', None)
|
28
|
+
if operating_system:
|
29
|
+
cmd.append('OS:{0}'.format(operating_system))
|
30
|
+
|
31
|
+
# execute logger command
|
32
|
+
subprocess.call(cmd)
|
33
|
+
|
34
|
+
# for troubleshooting purposes, you can save the received data to a file
|
35
|
+
# to parse the information to be used on the trigger.
|
36
|
+
# To accomplish it, set the variable dumpdata to True
|
37
|
+
dumpdata = False
|
38
|
+
if dumpdata:
|
39
|
+
with tempfile.NamedTemporaryFile(dir=HOOK_TEMP_DIR,
|
40
|
+
delete=False,
|
41
|
+
prefix=PREFIX) as fd:
|
42
|
+
fd.file.write("HOOK_OBJECT: %s\n" % HOOK_OBJECT)
|
43
|
+
fd.file.write("HOOK_EVENT: %s\n" % HOOK_EVENT)
|
44
|
+
fd.file.write("HOOK_JSON: %s\n" % HOOK_JSON)
|
45
|
+
|
46
|
+
# local variables
|
47
|
+
fd.file.write("hostname: %s\n" % hostname)
|
48
|
+
fd.file.write("mac_address: %s\n" % mac_address)
|
49
|
+
fd.file.write("os: %s\n" % operating_system)
|
50
|
+
fd.file.flush()
|
51
|
+
|
52
|
+
sys.exit(0)
|
data/lib/foreman_hooks.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module ForemanHooks
|
2
2
|
require 'foreman_hooks/engine'
|
3
3
|
require 'foreman_hooks/util'
|
4
|
+
require 'foreman_hooks/as_dependencies_hook'
|
4
5
|
require 'foreman_hooks/callback_hooks'
|
5
6
|
require 'foreman_hooks/orchestration_hook'
|
6
7
|
|
@@ -67,7 +68,7 @@ module ForemanHooks
|
|
67
68
|
end
|
68
69
|
|
69
70
|
def attach_hook(klass, events)
|
70
|
-
if events.keys.detect { |event| ['create', 'update', 'destroy'].include? event }
|
71
|
+
if events.keys.detect { |event| ['create', 'update', 'destroy', 'postcreate', 'postupdate'].include? event }
|
71
72
|
unless klass.ancestors.include?(ForemanHooks::OrchestrationHook)
|
72
73
|
logger.debug "Extending #{klass} with foreman_hooks orchestration hooking support"
|
73
74
|
klass.send(:include, ForemanHooks::OrchestrationHook)
|
@@ -83,17 +84,3 @@ module ForemanHooks
|
|
83
84
|
def logger; Rails.logger; end
|
84
85
|
end
|
85
86
|
end
|
86
|
-
|
87
|
-
module ActiveSupport::Dependencies
|
88
|
-
class << self
|
89
|
-
def load_missing_constant_with_hooks(from_mod, constant_name)
|
90
|
-
ret = load_missing_constant_without_hooks(from_mod, constant_name)
|
91
|
-
ForemanHooks.hooks.each do |klass,events|
|
92
|
-
ForemanHooks.attach_hook(ret, events) if ret.name == klass
|
93
|
-
end
|
94
|
-
ret
|
95
|
-
end
|
96
|
-
|
97
|
-
alias_method_chain :load_missing_constant, :hooks
|
98
|
-
end
|
99
|
-
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ForemanHooks
|
2
|
+
module ASDependenciesHook
|
3
|
+
def load_missing_constant(from_mod, constant_name)
|
4
|
+
super(from_mod, constant_name).tap do |ret|
|
5
|
+
return ret unless ret.try(:name)
|
6
|
+
ForemanHooks.hooks.each do |klass,events|
|
7
|
+
ForemanHooks.attach_hook(ret, events) if ret.name == klass
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
ActiveSupport::Dependencies.singleton_class.send(:prepend, ASDependenciesHook)
|
14
|
+
end
|
@@ -10,7 +10,11 @@ module ForemanHooks::CallbackHooks
|
|
10
10
|
next unless name
|
11
11
|
|
12
12
|
Rails.logger.debug("Created hook method #{event} on #{self}")
|
13
|
-
|
13
|
+
if "#{event}" == "before_destroy"
|
14
|
+
set_callback name.to_sym, filter.to_sym, "#{event}_hooks".to_sym, prepend: true
|
15
|
+
else
|
16
|
+
set_callback name.to_sym, filter.to_sym, "#{event}_hooks".to_sym
|
17
|
+
end
|
14
18
|
define_method("#{event}_hooks") do
|
15
19
|
Rails.logger.debug "Observed #{event} hook on #{self}"
|
16
20
|
return unless hooks = ForemanHooks.find_hooks(self.class, event)
|
data/lib/foreman_hooks/engine.rb
CHANGED
@@ -2,8 +2,18 @@ require 'foreman_hooks'
|
|
2
2
|
|
3
3
|
module ForemanHooks
|
4
4
|
class Engine < ::Rails::Engine
|
5
|
+
engine_name 'foreman_hooks'
|
6
|
+
|
5
7
|
config.to_prepare do
|
6
|
-
ForemanHooks.hooks.each
|
8
|
+
ForemanHooks.hooks.each do |klass,events|
|
9
|
+
begin
|
10
|
+
klass_const = klass.constantize
|
11
|
+
rescue NameError => e
|
12
|
+
ForemanHooks.logger.error "foreman_hooks: unknown hook object #{klass}, check against `foreman-rake hooks:objects`"
|
13
|
+
next
|
14
|
+
end
|
15
|
+
ForemanHooks.attach_hook(klass_const, events)
|
16
|
+
end
|
7
17
|
end
|
8
18
|
|
9
19
|
initializer 'foreman_hooks.register_plugin', :before => :finisher_hook do |app|
|
@@ -12,6 +12,7 @@ module ForemanHooks::OrchestrationHook
|
|
12
12
|
def queue_hooks_validate
|
13
13
|
return unless errors.empty?
|
14
14
|
queue_hooks(new_record? ? 'create' : 'update')
|
15
|
+
queue_hooks(new_record? ? 'postcreate' : 'postupdate')
|
15
16
|
end
|
16
17
|
|
17
18
|
def queue_hooks_destroy
|
@@ -22,20 +23,21 @@ module ForemanHooks::OrchestrationHook
|
|
22
23
|
def queue_hooks(event)
|
23
24
|
logger.debug "Observed #{event} hook on #{self}"
|
24
25
|
unless is_a? Orchestration
|
25
|
-
logger.
|
26
|
+
logger.error "#{self.class.to_s} doesn't support orchestration, can't run orchestration hooks: use Rails events instead"
|
27
|
+
return
|
26
28
|
end
|
27
29
|
|
28
30
|
return unless hooks = ForemanHooks.find_hooks(self.class, event)
|
29
|
-
logger.debug "
|
31
|
+
logger.debug "Queuing #{hooks.size} hooks for #{self.class.to_s}##{event}"
|
30
32
|
|
31
33
|
counter = 0
|
32
34
|
hooks.each do |filename|
|
33
35
|
basename = File.basename(filename)
|
34
36
|
priority = basename =~ /^(\d+)/ ? $1 : 10000 + (counter += 1)
|
35
|
-
logger.debug "Queuing hook #{
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
logger.debug "Queuing hook #{filename} for #{self.class.to_s}##{event} at priority #{priority}"
|
38
|
+
queue_to_use = (event =~ /^post/) ? post_queue : queue
|
39
|
+
queue_to_use.create(:name => "Hook: #{filename}", :priority => priority.to_i,
|
40
|
+
:action => [HookRunner.new(filename, self, event.to_s), event.to_s == 'destroy' ? :hook_execute_del : :hook_execute_set])
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
@@ -53,7 +55,7 @@ module ForemanHooks::OrchestrationHook
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def hook_execute_set
|
56
|
-
@obj.exec_hook(@filename, @event
|
58
|
+
@obj.exec_hook(@filename, @event, *args)
|
57
59
|
end
|
58
60
|
|
59
61
|
def hook_execute_del
|
data/lib/foreman_hooks/util.rb
CHANGED
@@ -9,18 +9,23 @@ module ForemanHooks::Util
|
|
9
9
|
'host'
|
10
10
|
when "Host::Discovered"
|
11
11
|
'discovered_host'
|
12
|
-
when "Audited::Adapters::ActiveRecord::Audit"
|
12
|
+
when "Audited::Adapters::ActiveRecord::Audit", "Audited::Audit"
|
13
13
|
'audit'
|
14
14
|
else
|
15
15
|
self.class.name.downcase
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
def rabl_path
|
20
|
+
"api/v2/#{render_hook_type.tableize}/show"
|
21
|
+
end
|
22
|
+
|
19
23
|
def render_hook_json
|
20
24
|
# APIv2 has some pretty good templates. We could extend them later in special cases.
|
21
25
|
# Wrap them in a root node for pre-1.4 compatibility
|
22
26
|
view_path = ActionController::Base.view_paths.collect(&:to_path)
|
23
|
-
json = Rabl.render(self,
|
27
|
+
json = Rabl.render(self, rabl_path,
|
28
|
+
view_path: view_path, format: :json, scope: RablScope.new)
|
24
29
|
%Q|{"#{render_hook_type}":#{json}}|
|
25
30
|
rescue => e
|
26
31
|
logger.warn "Unable to render #{self} (#{self.class}) using RABL: #{e.message}"
|
@@ -29,6 +34,11 @@ module ForemanHooks::Util
|
|
29
34
|
end
|
30
35
|
|
31
36
|
def exec_hook(*args)
|
37
|
+
unless File.executable?(args.first)
|
38
|
+
logger.warn("Hook #{args.first} no longer exists or isn't executable, so skipping execution of the hook. The server should be restarted after adding or removing hooks.")
|
39
|
+
return true
|
40
|
+
end
|
41
|
+
|
32
42
|
logger.debug "Running hook: #{args.join(' ')}"
|
33
43
|
success, output = if defined? Bundler && Bundler.responds_to(:with_clean_env)
|
34
44
|
Bundler.with_clean_env { exec_hook_int(render_hook_json, *args) }
|
@@ -41,6 +51,10 @@ module ForemanHooks::Util
|
|
41
51
|
end
|
42
52
|
|
43
53
|
def exec_hook_int(stdin_data, *args)
|
54
|
+
# Set environment vars available in hook scripts
|
55
|
+
# Name of active Foreman user:
|
56
|
+
ENV['FOREMAN_HOOKS_USER'] = User.current.login
|
57
|
+
|
44
58
|
args.map!(&:to_s)
|
45
59
|
output, status = if Open3.respond_to? :capture2e
|
46
60
|
Open3.capture2e(*args.push(:stdin_data => stdin_data))
|
@@ -60,4 +74,17 @@ module ForemanHooks::Util
|
|
60
74
|
logger.debug "Hook output: #{output}" if output && !output.empty?
|
61
75
|
[status.success?, output]
|
62
76
|
end
|
77
|
+
|
78
|
+
class RablScope
|
79
|
+
def initialize
|
80
|
+
# Used by api/v2/hosts/main.json.yaml to include parameter lists
|
81
|
+
@all_parameters = true
|
82
|
+
@parameters = true
|
83
|
+
end
|
84
|
+
|
85
|
+
def params
|
86
|
+
# Used by app/views/api/v2/common/show_hidden.json.rabl to show hidden parameter values (#17653)
|
87
|
+
{ 'show_hidden' => true, 'show_hidden_parameters' => true }
|
88
|
+
end
|
89
|
+
end
|
63
90
|
end
|
data/lib/tasks/hooks.rake
CHANGED
@@ -1,7 +1,15 @@
|
|
1
1
|
namespace :hooks do
|
2
2
|
desc 'Print a list of object names that can be hooked'
|
3
3
|
task :objects => :environment do
|
4
|
-
|
4
|
+
Rails.application.config.eager_load_namespaces.each(&:eager_load!)
|
5
|
+
|
6
|
+
# Gather the models
|
7
|
+
models = ActiveRecord::Base.descendants.collect(&:name).collect(&:underscore)
|
8
|
+
|
9
|
+
# filter out known models not hookable
|
10
|
+
models.reject! {|e| e.start_with?('habtm')}
|
11
|
+
|
12
|
+
puts models.sort
|
5
13
|
end
|
6
14
|
|
7
15
|
desc 'Print a list of event names for a given object, e.g. hooks:events[host/managed]'
|
@@ -12,8 +20,18 @@ namespace :hooks do
|
|
12
20
|
fail("Unknown model #{args[:object]}, run hooks:objects to get a list (#{e.message})")
|
13
21
|
end
|
14
22
|
|
23
|
+
# 1. List default ActiveRecord callbacks
|
15
24
|
events = ActiveRecord::Callbacks::CALLBACKS.map(&:to_s).reject { |e| e.start_with?('around_') }
|
16
|
-
|
25
|
+
|
26
|
+
# 2. List Foreman orchestration callbacks
|
27
|
+
events.concat(['create', 'destroy', 'update', 'postcreate', 'postupdate']) if model.included_modules.include?(Orchestration)
|
28
|
+
|
29
|
+
# 3. List custom define_callbacks/define_model_callbacks
|
30
|
+
callbacks = model.methods.map { |m| $1 if m =~ /\A_([a-z]\w+)_callbacks\z/ }.compact
|
31
|
+
# ignore callbacks that are in the AR default list
|
32
|
+
callbacks.delete_if { |c| events.any? { |e| e.end_with?("_#{c}") } }
|
33
|
+
callbacks.each { |c| events.push("before_#{c}", "after_#{c}") }
|
34
|
+
|
17
35
|
puts events.sort
|
18
36
|
end
|
19
37
|
end
|
metadata
CHANGED
@@ -1,18 +1,18 @@
|
|
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.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominic Cleal
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Plugin engine for Foreman that enables running custom hook scripts on
|
14
14
|
Foreman events
|
15
|
-
email:
|
15
|
+
email: dominic@cleal.org
|
16
16
|
executables: []
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files:
|
@@ -24,9 +24,13 @@ files:
|
|
24
24
|
- README.md
|
25
25
|
- Rakefile
|
26
26
|
- TODO
|
27
|
-
- examples/hook_functions.sh
|
28
|
-
- examples/log.sh
|
27
|
+
- examples/bash/hook_functions.sh
|
28
|
+
- examples/bash/log.sh
|
29
|
+
- examples/python/functions.py
|
30
|
+
- examples/python/host/managed/create/10-logger.py
|
31
|
+
- extra/foreman-debug.sh
|
29
32
|
- lib/foreman_hooks.rb
|
33
|
+
- lib/foreman_hooks/as_dependencies_hook.rb
|
30
34
|
- lib/foreman_hooks/callback_hooks.rb
|
31
35
|
- lib/foreman_hooks/engine.rb
|
32
36
|
- lib/foreman_hooks/orchestration_hook.rb
|
@@ -34,9 +38,9 @@ files:
|
|
34
38
|
- lib/tasks/hooks.rake
|
35
39
|
- test/test_helper.rb
|
36
40
|
- test/unit/host_observer_test.rb
|
37
|
-
homepage:
|
41
|
+
homepage: https://github.com/theforeman/foreman_hooks
|
38
42
|
licenses:
|
39
|
-
- GPL-3
|
43
|
+
- GPL-3.0
|
40
44
|
metadata: {}
|
41
45
|
post_install_message:
|
42
46
|
rdoc_options: []
|
@@ -44,17 +48,16 @@ require_paths:
|
|
44
48
|
- lib
|
45
49
|
required_ruby_version: !ruby/object:Gem::Requirement
|
46
50
|
requirements:
|
47
|
-
- -
|
51
|
+
- - ">="
|
48
52
|
- !ruby/object:Gem::Version
|
49
53
|
version: '0'
|
50
54
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
55
|
requirements:
|
52
|
-
- -
|
56
|
+
- - ">="
|
53
57
|
- !ruby/object:Gem::Version
|
54
58
|
version: '0'
|
55
59
|
requirements: []
|
56
|
-
|
57
|
-
rubygems_version: 2.0.6
|
60
|
+
rubygems_version: 3.1.2
|
58
61
|
signing_key:
|
59
62
|
specification_version: 4
|
60
63
|
summary: Run custom hook scripts on Foreman events
|