chook 1.0.1.b2 → 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGES.md +56 -0
- data/README.md +363 -127
- data/bin/chook-server +31 -1
- data/data/chook.conf.example +183 -0
- data/data/com.pixar.chook-server.plist +20 -0
- data/data/sample_handlers/RestAPIOperation.rb +11 -11
- data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +3 -6
- data/data/sample_jsons/SmartGroupComputerMembershipChange.json +3 -1
- data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +3 -1
- data/lib/chook/configuration.rb +27 -8
- data/lib/chook/event.rb +6 -1
- data/lib/chook/event/handled_event.rb +36 -9
- data/lib/chook/event/handled_event/handlers.rb +260 -98
- data/lib/chook/event/handled_event_logger.rb +86 -0
- data/lib/chook/event_handling.rb +1 -0
- data/lib/chook/foundation.rb +3 -0
- data/lib/chook/procs.rb +17 -1
- data/lib/chook/server.rb +73 -72
- data/lib/chook/server/auth.rb +164 -0
- data/lib/chook/server/log.rb +215 -0
- data/lib/chook/server/public/css/chook.css +133 -0
- data/lib/chook/server/public/imgs/ChookLogoAlMcWhiggin.png +0 -0
- data/lib/chook/server/public/js/chook.js +126 -0
- data/lib/chook/server/public/js/logstream.js +101 -0
- data/lib/chook/server/routes.rb +28 -0
- data/lib/chook/server/routes/handle_by_name.rb +65 -0
- data/lib/chook/server/routes/handle_webhook_event.rb +27 -3
- data/lib/chook/server/routes/handlers.rb +52 -0
- data/lib/chook/server/routes/home.rb +48 -1
- data/lib/chook/server/routes/log.rb +105 -0
- data/lib/chook/server/routes/login_logout.rb +48 -0
- data/lib/chook/server/views/admin.haml +11 -0
- data/lib/chook/server/views/bak.haml +48 -0
- data/lib/chook/server/views/config.haml +15 -0
- data/lib/chook/server/views/handlers.haml +63 -0
- data/lib/chook/server/views/layout.haml +64 -0
- data/lib/chook/server/views/logstream.haml +33 -0
- data/lib/chook/server/views/sketch_admin +44 -0
- data/lib/chook/subject.rb +13 -2
- data/lib/chook/subject/dep_device.rb +81 -0
- data/lib/chook/subject/policy_finished.rb +43 -0
- data/lib/chook/subject/smart_group.rb +6 -0
- data/lib/chook/version.rb +1 -1
- metadata +79 -19
@@ -1,36 +1,45 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
1
|
+
# Copyright 2017 Pixar
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
4
|
+
# with the following modification; you may not use this file except in
|
5
|
+
# compliance with the Apache License and the following modification to it:
|
6
|
+
# Section 6. Trademarks. is deleted and replaced with:
|
7
|
+
#
|
8
|
+
# 6. Trademarks. This License does not grant permission to use the trade
|
9
|
+
# names, trademarks, service marks, or product names of the Licensor
|
10
|
+
# and its affiliates, except as required to comply with Section 4(c) of
|
11
|
+
# the License and to reproduce the content of the NOTICE file.
|
12
|
+
#
|
13
|
+
# You may obtain a copy of the Apache License at
|
14
|
+
#
|
15
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
16
|
+
#
|
17
|
+
# Unless required by applicable law or agreed to in writing, software
|
18
|
+
# distributed under the Apache License with the above modification is
|
19
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
20
|
+
# KIND, either express or implied. See the Apache License for the specific
|
21
|
+
# language governing permissions and limitations under the Apache License.
|
22
|
+
#
|
23
|
+
#
|
24
|
+
|
25
25
|
module Chook
|
26
26
|
|
27
|
-
# This method is used by the Ruby event-handler files.
|
27
|
+
# This method is used by the Ruby 'internal' event-handler files.
|
28
|
+
#
|
29
|
+
# those handlers are defined by passing a block to this method, like so:
|
30
|
+
#
|
31
|
+
# Chook.event_handler do |event|
|
32
|
+
# # so something with the event
|
33
|
+
# end
|
28
34
|
#
|
29
|
-
# Loading them
|
35
|
+
# Loading them will call this method and pass in a block
|
30
36
|
# with one parameter: a Chook::HandledEvent subclass instance.
|
31
37
|
#
|
32
|
-
# The block is then converted to a
|
33
|
-
#
|
38
|
+
# The block is then converted to a #handle method in an anonymous object.
|
39
|
+
# The object is stored for use by the event identified by the filename.
|
40
|
+
#
|
41
|
+
# By storing it as a method in an object, the handlers themselves
|
42
|
+
# can use #break or #return to exit (or even #next)
|
34
43
|
#
|
35
44
|
# NOTE: the files should be read with 'load' not 'require', so that they can
|
36
45
|
# be re-loaded as needed
|
@@ -44,7 +53,13 @@ module Chook
|
|
44
53
|
# @return [Proc] the block converted to a Proc
|
45
54
|
#
|
46
55
|
def self.event_handler(&block)
|
47
|
-
|
56
|
+
obj = Object.new
|
57
|
+
obj.define_singleton_method(:handle, &block)
|
58
|
+
# Loading the file created the object by calling this method
|
59
|
+
# but to access it after loading the file, we need to
|
60
|
+
# store it in here:
|
61
|
+
HandledEvent::Handlers.loaded_handler = obj
|
62
|
+
Chook.logger.debug "Code block for 'Chook.event_handler' loaded into \#handle method of runner-object #{obj.object_id}"
|
48
63
|
end
|
49
64
|
|
50
65
|
# the server class
|
@@ -53,56 +68,104 @@ module Chook
|
|
53
68
|
# The Handlers namespace module
|
54
69
|
module Handlers
|
55
70
|
|
56
|
-
#
|
57
|
-
|
71
|
+
# Don't load any handlers whose filenames start with this
|
72
|
+
DO_NOT_LOAD_PREFIX = 'Ignore-'.freeze
|
58
73
|
|
59
74
|
DEFAULT_HANDLER_DIR = '/Library/Application Support/Chook'.freeze
|
60
75
|
|
61
|
-
#
|
62
|
-
|
76
|
+
# Handlers that are only called by name using the route:
|
77
|
+
# post '/handler/:handler_name'
|
78
|
+
# are located in this subdirection of the handler directory
|
79
|
+
NAMED_HANDLER_SUBDIR = 'NamedHandlers'.freeze
|
63
80
|
|
64
|
-
#
|
65
|
-
|
66
|
-
@loaded_handler = nil
|
81
|
+
# internal handler files must match this regex somewhere
|
82
|
+
INTERNAL_HANDLER_BLOCK_START_RE = /Chook.event_handler( ?\{| do) *\|/
|
67
83
|
|
68
|
-
#
|
84
|
+
# self loaded_handler=
|
69
85
|
#
|
70
|
-
# @return [
|
86
|
+
# @return [Obj,nil] the most recent Proc loaded from a handler file.
|
71
87
|
# destined for storage in @handlers
|
72
88
|
#
|
73
89
|
def self.loaded_handler
|
74
90
|
@loaded_handler
|
75
91
|
end
|
76
92
|
|
77
|
-
#
|
93
|
+
# A holding place for internal handlers as they are loaded
|
94
|
+
# before being added to the @handlers Hash
|
95
|
+
# see Chook.event_handler(&block)
|
78
96
|
#
|
79
|
-
# @param a_proc [
|
97
|
+
# @param a_proc [Object] An object instance with a #handle method
|
80
98
|
#
|
81
|
-
def self.loaded_handler=(
|
82
|
-
@loaded_handler =
|
99
|
+
def self.loaded_handler=(anon_obj)
|
100
|
+
@loaded_handler = anon_obj
|
83
101
|
end
|
84
102
|
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
|
90
|
-
|
91
|
-
#
|
103
|
+
# Getter for @handlers
|
104
|
+
#
|
105
|
+
# @return [Hash{String => Array}] a mapping of Event Names as they
|
106
|
+
# come from the JSS to an Array of handlers for the event.
|
107
|
+
# The handlers are either Pathnames to executable external handlers
|
108
|
+
# or Objcts with a #handle method, for internal handlers
|
109
|
+
# (The objects also have a #handler_file attribute that is the Pathname)
|
92
110
|
#
|
93
|
-
# @return [Hash{String => Array}] a mapping of Event Names as the come from
|
94
|
-
# the JSS to an Array of handlers for the event. The handlers are either
|
95
|
-
# Proc objects to call from within ruby, or Pathnames to executable files
|
96
|
-
# which will take raw JSON on stdin.
|
97
111
|
def self.handlers
|
98
|
-
@handlers
|
112
|
+
@handlers ||= {}
|
99
113
|
end
|
100
114
|
|
101
|
-
#
|
102
|
-
|
115
|
+
# Handlers can check Chook::HandledEvent::Handlers.reloading?
|
116
|
+
# and do stuff if desired.
|
117
|
+
def self.reloading?
|
118
|
+
@reloading
|
119
|
+
end
|
120
|
+
|
121
|
+
# getter for @named_handlers
|
122
|
+
# These handlers are called by name via the route
|
123
|
+
# " post '/handler/:handler_name'"
|
124
|
+
#
|
125
|
+
# They are not tied to any event type by their filenames
|
126
|
+
# its up to the writers of the handlers to make sure
|
127
|
+
# the webhook that calls them is sending the correct event
|
128
|
+
# type.
|
129
|
+
#
|
130
|
+
# The data structure of @named_handlers is a
|
131
|
+
# Hash of Strings to Pathnames or Anon Objects:
|
132
|
+
# {
|
133
|
+
# handler_filename => Pathname or Obj,
|
134
|
+
# handler_filename => Pathname or Obj,
|
135
|
+
# handler_filename => Pathname or Obj
|
136
|
+
# }
|
137
|
+
#
|
138
|
+
# @return [Hash {String => Pathname, Proc}]
|
139
|
+
def self.named_handlers
|
140
|
+
@named_handlers ||= {}
|
141
|
+
end
|
142
|
+
|
143
|
+
# the Pathname objects for all loaded handlers
|
144
|
+
#
|
145
|
+
# @return [Array<Pathname>]
|
146
|
+
#
|
147
|
+
def self.all_handler_paths
|
148
|
+
hndlrs = named_handlers.values
|
149
|
+
hndlrs += handlers.values.flatten
|
150
|
+
hndlrs.map do |hndlr|
|
151
|
+
hndlr.is_a?(Pathname) ? hndlr : hndlr.handler_file
|
152
|
+
end
|
153
|
+
end
|
103
154
|
|
104
155
|
# Load all the event handlers from the handler_dir or an arbitrary dir.
|
105
156
|
#
|
157
|
+
#
|
158
|
+
# Handler files must be either:
|
159
|
+
# - An executable file, which will have the raw JSON from the JSS piped
|
160
|
+
# to it's stdin when executed
|
161
|
+
# or
|
162
|
+
# - A non-executable file of ruby code like this:
|
163
|
+
# Chook.event_handler do |event|
|
164
|
+
# # your code goes here.
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# (see the Chook README for details about writing the ruby handlers)
|
168
|
+
#
|
106
169
|
# @param from_dir [String, Pathname] directory from which to load the
|
107
170
|
# handlers. Defaults to CONFIG.handler_dir or DEFAULT_HANDLER_DIR if
|
108
171
|
# config is unset
|
@@ -112,27 +175,55 @@ module Chook
|
|
112
175
|
#
|
113
176
|
# @return [void]
|
114
177
|
#
|
115
|
-
def self.load_handlers(from_dir: Chook
|
178
|
+
def self.load_handlers(from_dir: Chook.config.handler_dir, reload: false)
|
179
|
+
# use default if needed
|
116
180
|
from_dir ||= DEFAULT_HANDLER_DIR
|
181
|
+
handler_dir = Pathname.new(from_dir)
|
182
|
+
named_handler_dir = handler_dir + NAMED_HANDLER_SUBDIR
|
183
|
+
load_type = 'Loading'
|
184
|
+
|
117
185
|
if reload
|
118
|
-
@
|
186
|
+
@reloading = true
|
119
187
|
@handlers = {}
|
188
|
+
@named_handlers = {}
|
120
189
|
@loaded_handler = nil
|
190
|
+
load_type = 'Re-loading'
|
121
191
|
end
|
122
192
|
|
123
|
-
|
124
|
-
|
193
|
+
# General Handlers
|
194
|
+
Chook.logger.info "#{load_type} general handlers from directory: #{handler_dir}"
|
195
|
+
if handler_dir.directory? && handler_dir.readable?
|
196
|
+
handler_dir.children.each do |handler_file|
|
197
|
+
# ignore if marked to
|
198
|
+
next if handler_file.basename.to_s.start_with? DO_NOT_LOAD_PREFIX
|
199
|
+
|
200
|
+
load_general_handler(handler_file) if handler_file.file? && handler_file.readable?
|
201
|
+
end
|
202
|
+
Chook.logger.info handlers.empty? ? 'No general handlers found' : "Loaded #{handlers.values.flatten.size} general handlers for #{handlers.keys.size} event triggers"
|
203
|
+
else
|
204
|
+
Chook.logger.error "General handler directory '#{from_dir}' not a readable directory. No general handlers loaded. "
|
205
|
+
end
|
206
|
+
|
207
|
+
# Named Handlers
|
208
|
+
Chook.logger.info "#{load_type} named handlers from directory: #{named_handler_dir}"
|
209
|
+
if named_handler_dir.directory? && named_handler_dir.readable?
|
210
|
+
named_handler_dir.children.each do |handler_file|
|
211
|
+
# ignore if marked to
|
212
|
+
next if handler_file.basename.to_s.start_with? DO_NOT_LOAD_PREFIX
|
125
213
|
|
126
|
-
|
127
|
-
|
214
|
+
load_named_handler(handler_file) if handler_file.file? && handler_file.readable?
|
215
|
+
end
|
216
|
+
Chook.logger.info "Loaded #{named_handlers.size} named handlers"
|
217
|
+
else
|
218
|
+
Chook.logger.error "Named handler directory '#{named_handler_dir}' not a readable directory. No named handlers loaded. "
|
128
219
|
end
|
129
220
|
|
130
|
-
@
|
131
|
-
@handlers.values.flatten.size
|
221
|
+
@reloading = false
|
132
222
|
end # load handlers
|
133
223
|
|
134
|
-
# Load
|
135
|
-
#
|
224
|
+
# Load a general event handler from a file.
|
225
|
+
#
|
226
|
+
# General Handler files must begin with the name of the event they handle,
|
136
227
|
# e.g. ComputerAdded, followed by: nothing, a dot, a dash, or
|
137
228
|
# and underscore. Case doesn't matter.
|
138
229
|
# So all of these are OK:
|
@@ -142,49 +233,113 @@ module Chook
|
|
142
233
|
# Computeradded-update-ldap
|
143
234
|
# There can be as many as desired for each event.
|
144
235
|
#
|
145
|
-
#
|
146
|
-
# - An executable file, which will have the raw JSON from the JSS piped
|
147
|
-
# to it's stdin when executed
|
148
|
-
# or
|
149
|
-
# - A non-executable file of ruby code like this:
|
150
|
-
# Chook.event_handler do |event|
|
151
|
-
# # your code goes here.
|
152
|
-
# end
|
153
|
-
#
|
154
|
-
# (see the Chook README for details about writing the ruby handlers)
|
155
|
-
#
|
156
|
-
# @param from_file [Pathname] the file from which to load the handler
|
236
|
+
# @param handler_file [Pathname] the file from which to load the handler
|
157
237
|
#
|
158
238
|
# @return [void]
|
159
239
|
#
|
160
|
-
def self.
|
161
|
-
|
240
|
+
def self.load_general_handler(handler_file)
|
241
|
+
Chook.logger.debug "Starting load of general handler file '#{handler_file.basename}'"
|
242
|
+
|
162
243
|
event_name = event_name_from_handler_filename(handler_file)
|
163
|
-
|
244
|
+
unless event_name
|
245
|
+
Chook.logger.debug "Ignoring general handler file '#{handler_file.basename}': Filename doesn't start with event name"
|
246
|
+
return
|
247
|
+
end
|
164
248
|
|
165
249
|
# create an array for this event's handlers, if needed
|
166
|
-
|
250
|
+
handlers[event_name] ||= []
|
167
251
|
|
252
|
+
# external? if so, its executable and we only care about its pathname
|
168
253
|
if handler_file.executable?
|
169
|
-
|
170
|
-
|
171
|
-
@handlers[event_name] << handler_file
|
172
|
-
puts "===> Loaded executable handler file '#{handler_file.basename}'"
|
173
|
-
end
|
254
|
+
Chook.logger.info "Loading external general handler file '#{handler_file.basename}' for #{event_name} events"
|
255
|
+
handlers[event_name] << handler_file
|
174
256
|
return
|
175
257
|
end
|
176
258
|
|
177
|
-
#
|
178
|
-
|
179
|
-
|
180
|
-
if @loaded_handler
|
181
|
-
|
182
|
-
|
183
|
-
|
259
|
+
# Internal, we store an object with a .handle method
|
260
|
+
Chook.logger.info "Loading internal general handler file '#{handler_file.basename}' for #{event_name} events"
|
261
|
+
load_internal_handler handler_file
|
262
|
+
handlers[event_name] << @loaded_handler if @loaded_handler
|
263
|
+
|
264
|
+
end # self.load_general_handler(handler_file)
|
265
|
+
|
266
|
+
# Load a named event handler from a file.
|
267
|
+
#
|
268
|
+
# Named Handler files can have any name, as they are called directly
|
269
|
+
# from a Jamf webhook via URL.
|
270
|
+
#
|
271
|
+
# @param handler_file [Pathname] the file from which to load the handler
|
272
|
+
#
|
273
|
+
# @return [void]
|
274
|
+
#
|
275
|
+
def self.load_named_handler(handler_file)
|
276
|
+
Chook.logger.debug "Starting load of named handler file '#{handler_file.basename}'"
|
277
|
+
|
278
|
+
# external? if so, its executable and we only care about its pathname
|
279
|
+
if handler_file.executable?
|
280
|
+
Chook.logger.info "Loading external named handler file '#{handler_file.basename}'"
|
281
|
+
named_handlers[handler_file.basename.to_s] = handler_file
|
282
|
+
return
|
283
|
+
end
|
284
|
+
|
285
|
+
# Internal, we store an object with a .handle method
|
286
|
+
Chook.logger.info "Loading internal named handler file '#{handler_file.basename}'"
|
287
|
+
load_internal_handler handler_file
|
288
|
+
named_handlers[handler_file.basename.to_s] = @loaded_handler if @loaded_handler
|
289
|
+
end # self.load_general_handler(handler_file)
|
290
|
+
|
291
|
+
# if the given file is executable, store it's path as a handler for the event
|
292
|
+
#
|
293
|
+
# @return [Boolean] did we load an external handler?
|
294
|
+
#
|
295
|
+
def self.load_external_handler(handler_file, event_name, named)
|
296
|
+
return false unless handler_file.executable?
|
297
|
+
|
298
|
+
say_named = named ? 'named ' : ''
|
299
|
+
Chook.logger.info "Loading #{say_named}external handler file '#{handler_file.basename}' for #{event_name} events"
|
300
|
+
|
301
|
+
if named
|
302
|
+
named_handlers[event_name][handler_file.basename.to_s] = handler_file
|
184
303
|
else
|
185
|
-
|
304
|
+
# store the Pathname, we'll pipe JSON to it
|
305
|
+
handlers[event_name] << handler_file
|
306
|
+
end
|
307
|
+
|
308
|
+
true
|
309
|
+
end
|
310
|
+
|
311
|
+
# if a given path is not executable, try to load it as an internal handler
|
312
|
+
#
|
313
|
+
# @param handler_file[Pathname] the handler file
|
314
|
+
#
|
315
|
+
# @return [Object] and anonymous object that has a .handle method
|
316
|
+
#
|
317
|
+
def self.load_internal_handler(handler_file)
|
318
|
+
# load the file. If written correctly, it will
|
319
|
+
# put an anon. Object with a #handle method into @loaded_handler
|
320
|
+
unless handler_file.read =~ INTERNAL_HANDLER_BLOCK_START_RE
|
321
|
+
Chook.logger.error "Internal handler file '#{handler_file}' missing event_handler block"
|
322
|
+
return nil
|
323
|
+
end
|
324
|
+
|
325
|
+
# reset @loaded_handler - the `load` call will refill it
|
326
|
+
# see Chook.event_handler
|
327
|
+
@loaded_handler = nil
|
328
|
+
|
329
|
+
begin
|
330
|
+
load handler_file.to_s
|
331
|
+
raise '@loaded handler nil after loading file' unless @loaded_handler
|
332
|
+
rescue => e
|
333
|
+
Chook.logger.error "FAILED loading internal handler file '#{handler_file}': #{e}"
|
334
|
+
return
|
186
335
|
end
|
187
|
-
|
336
|
+
|
337
|
+
# add a method to the object to get its Pathname
|
338
|
+
@loaded_handler.define_singleton_method(:handler_file) { handler_file }
|
339
|
+
|
340
|
+
# return it
|
341
|
+
@loaded_handler
|
342
|
+
end
|
188
343
|
|
189
344
|
# Given a handler filename, return the event name it wants to handle
|
190
345
|
#
|
@@ -194,9 +349,16 @@ module Chook
|
|
194
349
|
# @return [String,nil] The matching event name or nil if no match
|
195
350
|
#
|
196
351
|
def self.event_name_from_handler_filename(filename)
|
352
|
+
filename = filename.basename
|
197
353
|
@event_names ||= Chook::Event::EVENTS.keys
|
198
|
-
desired_event_name = filename.
|
199
|
-
@event_names.select { |n| desired_event_name.casecmp(n).zero? }.first
|
354
|
+
desired_event_name = filename.to_s.split(/\.|-|_/).first
|
355
|
+
ename = @event_names.select { |n| desired_event_name.casecmp(n).zero? }.first
|
356
|
+
if ename
|
357
|
+
Chook.logger.debug "Found event name '#{ename}' at start of filename '#{filename}'"
|
358
|
+
else
|
359
|
+
Chook.logger.debug "No known event name at start of filename '#{filename}'"
|
360
|
+
end
|
361
|
+
ename
|
200
362
|
end
|
201
363
|
|
202
364
|
end # module Handler
|
@@ -0,0 +1,86 @@
|
|
1
|
+
### Copyright 2017 Pixar
|
2
|
+
|
3
|
+
###
|
4
|
+
### Licensed under the Apache License, Version 2.0 (the "Apache License")
|
5
|
+
### with the following modification; you may not use this file except in
|
6
|
+
### compliance with the Apache License and the following modification to it:
|
7
|
+
### Section 6. Trademarks. is deleted and replaced with:
|
8
|
+
###
|
9
|
+
### 6. Trademarks. This License does not grant permission to use the trade
|
10
|
+
### names, trademarks, service marks, or product names of the Licensor
|
11
|
+
### and its affiliates, except as required to comply with Section 4(c) of
|
12
|
+
### the License and to reproduce the content of the NOTICE file.
|
13
|
+
###
|
14
|
+
### You may obtain a copy of the Apache License at
|
15
|
+
###
|
16
|
+
### http://www.apache.org/licenses/LICENSE-2.0
|
17
|
+
###
|
18
|
+
### Unless required by applicable law or agreed to in writing, software
|
19
|
+
### distributed under the Apache License with the above modification is
|
20
|
+
### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
21
|
+
### KIND, either express or implied. See the Apache License for the specific
|
22
|
+
### language governing permissions and limitations under the Apache License.
|
23
|
+
###
|
24
|
+
###
|
25
|
+
|
26
|
+
module Chook
|
27
|
+
|
28
|
+
# a simple object embedded in a Handled Event that
|
29
|
+
# allows a standardize way to note event-related log entries
|
30
|
+
# with the event object_id.
|
31
|
+
#
|
32
|
+
# Every Handled Event has one of these instances exposed in it's
|
33
|
+
# #logger attribute, and usable from within 'internal' handlers
|
34
|
+
#
|
35
|
+
# Here's an example.
|
36
|
+
#
|
37
|
+
# Say you have a ComputerSmartGroupMembershipChanged event
|
38
|
+
#
|
39
|
+
# calling `event.logger.info "foobar"` will generate the log message:
|
40
|
+
#
|
41
|
+
# Event 1234567: foobar
|
42
|
+
#
|
43
|
+
class HandledEventLogger
|
44
|
+
|
45
|
+
def initialize(event)
|
46
|
+
@event = event
|
47
|
+
end
|
48
|
+
|
49
|
+
def event_message(msg)
|
50
|
+
"Event #{@event.id}: #{msg}"
|
51
|
+
end
|
52
|
+
|
53
|
+
def debug(msg)
|
54
|
+
Chook::Server::Log.logger.debug event_message(msg)
|
55
|
+
end
|
56
|
+
|
57
|
+
def info(msg)
|
58
|
+
Chook::Server::Log.logger.info event_message(msg)
|
59
|
+
end
|
60
|
+
|
61
|
+
def warn(msg)
|
62
|
+
Chook::Server::Log.logger.warn event_message(msg)
|
63
|
+
end
|
64
|
+
|
65
|
+
def error(msg)
|
66
|
+
Chook::Server::Log.logger.error event_message(msg)
|
67
|
+
end
|
68
|
+
|
69
|
+
def fatal(msg)
|
70
|
+
Chook::Server::Log.logger.fatal event_message(msg)
|
71
|
+
end
|
72
|
+
|
73
|
+
def unknown(msg)
|
74
|
+
Chook::Server::Log.logger.unknown event_message(msg)
|
75
|
+
end
|
76
|
+
|
77
|
+
# log an exception - multiple log lines
|
78
|
+
# the first being the error message the rest being indented backtrace
|
79
|
+
def log_exception(exception)
|
80
|
+
error "#{exception.class}: #{exception}"
|
81
|
+
exception.backtrace.each { |l| error "..#{l}" }
|
82
|
+
end
|
83
|
+
|
84
|
+
end # class HandledEventLogger
|
85
|
+
|
86
|
+
end # module
|