Module: Chook::HandledEvent::Handlers
- Defined in:
- lib/chook/event/handled_event/handlers.rb
Overview
The Handlers namespace module
Constant Summary collapse
- DO_NOT_LOAD_PREFIX =
Don’t load any handlers whose filenames start with this
'Ignore-'.freeze
- DEFAULT_HANDLER_DIR =
'/Library/Application Support/Chook'.freeze
- NAMED_HANDLER_SUBDIR =
Handlers that are only called by name using the route:
post '/handler/:handler_name'
are located in this subdirection of the handler directory
'NamedHandlers'.freeze
- INTERNAL_HANDLER_BLOCK_START_RE =
internal handler files must match this regex somewhere
/Chook.event_handler( ?\{| do) *\|/
Class Method Summary collapse
-
.all_handler_paths ⇒ Array<Pathname>
the Pathname objects for all loaded handlers.
-
.event_name_from_handler_filename(filename) ⇒ String?
Given a handler filename, return the event name it wants to handle.
-
.handlers ⇒ Hash{String => Array}
Getter for @handlers.
-
.load_external_handler(handler_file, event_name, named) ⇒ Boolean
if the given file is executable, store it’s path as a handler for the event.
-
.load_general_handler(handler_file) ⇒ void
Load a general event handler from a file.
-
.load_handlers(from_dir: Chook.config.handler_dir, reload: false) ⇒ void
Load all the event handlers from the handler_dir or an arbitrary dir.
-
.load_internal_handler(handler_file) ⇒ Object
if a given path is not executable, try to load it as an internal handler.
-
.load_named_handler(handler_file) ⇒ void
Load a named event handler from a file.
-
.loaded_handler ⇒ Obj?
self loaded_handler=.
-
.loaded_handler=(anon_obj) ⇒ Object
A holding place for internal handlers as they are loaded before being added to the @handlers Hash see Chook.event_handler(&block).
-
.named_handlers ⇒ Hash {String => Pathname, Proc}
getter for @named_handlers These handlers are called by name via the route “ post ‘/handler/:handler_name’”.
-
.reloading? ⇒ Boolean
Handlers can check Chook::HandledEvent::Handlers.reloading? and do stuff if desired.
Class Method Details
.all_handler_paths ⇒ Array<Pathname>
the Pathname objects for all loaded handlers
147 148 149 150 151 152 153 |
# File 'lib/chook/event/handled_event/handlers.rb', line 147 def self.all_handler_paths hndlrs = named_handlers.values hndlrs += handlers.values.flatten hndlrs.map do |hndlr| hndlr.is_a?(Pathname) ? hndlr : hndlr.handler_file end end |
.event_name_from_handler_filename(filename) ⇒ String?
Given a handler filename, return the event name it wants to handle
351 352 353 354 355 356 357 358 359 360 361 362 |
# File 'lib/chook/event/handled_event/handlers.rb', line 351 def self.event_name_from_handler_filename(filename) filename = filename.basename @event_names ||= Chook::Event::EVENTS.keys desired_event_name = filename.to_s.split(/\.|-|_/).first ename = @event_names.select { |n| desired_event_name.casecmp(n).zero? }.first if ename Chook.logger.debug "Found event name '#{ename}' at start of filename '#{filename}'" else Chook.logger.debug "No known event name at start of filename '#{filename}'" end ename end |
.handlers ⇒ Hash{String => Array}
Getter for @handlers
come from the JSS to an Array of handlers for the event. The handlers are either Pathnames to executable external handlers or Objcts with a #handle method, for internal handlers
(The objects also have a #handler_file attribute that is the Pathname)
111 112 113 |
# File 'lib/chook/event/handled_event/handlers.rb', line 111 def self.handlers @handlers ||= {} end |
.load_external_handler(handler_file, event_name, named) ⇒ Boolean
if the given file is executable, store it’s path as a handler for the event
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/chook/event/handled_event/handlers.rb', line 295 def self.load_external_handler(handler_file, event_name, named) return false unless handler_file.executable? say_named = named ? 'named ' : '' Chook.logger.info "Loading #{say_named}external handler file '#{handler_file.basename}' for #{event_name} events" if named named_handlers[event_name][handler_file.basename.to_s] = handler_file else # store the Pathname, we'll pipe JSON to it handlers[event_name] << handler_file end true end |
.load_general_handler(handler_file) ⇒ void
This method returns an undefined value.
Load a general event handler from a file.
General Handler files must begin with the name of the event they handle, e.g. ComputerAdded, followed by: nothing, a dot, a dash, or and underscore. Case doesn’t matter. So all of these are OK: ComputerAdded computeradded.sh COMPUTERAdded_notify_team Computeradded-update-ldap There can be as many as desired for each event.
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/chook/event/handled_event/handlers.rb', line 240 def self.load_general_handler(handler_file) Chook.logger.debug "Starting load of general handler file '#{handler_file.basename}'" event_name = event_name_from_handler_filename(handler_file) unless event_name Chook.logger.debug "Ignoring general handler file '#{handler_file.basename}': Filename doesn't start with event name" return end # create an array for this event's handlers, if needed handlers[event_name] ||= [] # external? if so, its executable and we only care about its pathname if handler_file.executable? Chook.logger.info "Loading external general handler file '#{handler_file.basename}' for #{event_name} events" handlers[event_name] << handler_file return end # Internal, we store an object with a .handle method Chook.logger.info "Loading internal general handler file '#{handler_file.basename}' for #{event_name} events" load_internal_handler handler_file handlers[event_name] << @loaded_handler if @loaded_handler end |
.load_handlers(from_dir: Chook.config.handler_dir, reload: false) ⇒ void
This method returns an undefined value.
Load all the event handlers from the handler_dir or an arbitrary dir.
Handler files must be either:
- An executable file, which will have the raw JSON from the JSS piped
to it's stdin when executed
or
- A non-executable file of ruby code like this:
Chook.event_handler do |event|
# your code goes here.
end
(see the Chook README for details about writing the ruby handlers)
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/chook/event/handled_event/handlers.rb', line 178 def self.load_handlers(from_dir: Chook.config.handler_dir, reload: false) # use default if needed from_dir ||= DEFAULT_HANDLER_DIR handler_dir = Pathname.new(from_dir) named_handler_dir = handler_dir + NAMED_HANDLER_SUBDIR load_type = 'Loading' if reload @reloading = true @handlers = {} @named_handlers = {} @loaded_handler = nil load_type = 'Re-loading' end # General Handlers Chook.logger.info "#{load_type} general handlers from directory: #{handler_dir}" if handler_dir.directory? && handler_dir.readable? handler_dir.children.each do |handler_file| # ignore if marked to next if handler_file.basename.to_s.start_with? DO_NOT_LOAD_PREFIX load_general_handler(handler_file) if handler_file.file? && handler_file.readable? end Chook.logger.info handlers.empty? ? 'No general handlers found' : "Loaded #{handlers.values.flatten.size} general handlers for #{handlers.keys.size} event triggers" else Chook.logger.error "General handler directory '#{from_dir}' not a readable directory. No general handlers loaded. " end # Named Handlers Chook.logger.info "#{load_type} named handlers from directory: #{named_handler_dir}" if named_handler_dir.directory? && named_handler_dir.readable? named_handler_dir.children.each do |handler_file| # ignore if marked to next if handler_file.basename.to_s.start_with? DO_NOT_LOAD_PREFIX load_named_handler(handler_file) if handler_file.file? && handler_file.readable? end Chook.logger.info "Loaded #{named_handlers.size} named handlers" else Chook.logger.error "Named handler directory '#{named_handler_dir}' not a readable directory. No named handlers loaded. " end @reloading = false end |
.load_internal_handler(handler_file) ⇒ Object
if a given path is not executable, try to load it as an internal handler
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/chook/event/handled_event/handlers.rb', line 317 def self.load_internal_handler(handler_file) # load the file. If written correctly, it will # put an anon. Object with a #handle method into @loaded_handler unless handler_file.read =~ INTERNAL_HANDLER_BLOCK_START_RE Chook.logger.error "Internal handler file '#{handler_file}' missing event_handler block" return nil end # reset @loaded_handler - the `load` call will refill it # see Chook.event_handler @loaded_handler = nil begin load handler_file.to_s raise '@loaded handler nil after loading file' unless @loaded_handler rescue => e Chook.logger.error "FAILED loading internal handler file '#{handler_file}': #{e}" return end # add a method to the object to get its Pathname @loaded_handler.define_singleton_method(:handler_file) { handler_file } # return it @loaded_handler end |
.load_named_handler(handler_file) ⇒ void
This method returns an undefined value.
Load a named event handler from a file.
Named Handler files can have any name, as they are called directly from a Jamf webhook via URL.
275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/chook/event/handled_event/handlers.rb', line 275 def self.load_named_handler(handler_file) Chook.logger.debug "Starting load of named handler file '#{handler_file.basename}'" # external? if so, its executable and we only care about its pathname if handler_file.executable? Chook.logger.info "Loading external named handler file '#{handler_file.basename}'" named_handlers[handler_file.basename.to_s] = handler_file return end # Internal, we store an object with a .handle method Chook.logger.info "Loading internal named handler file '#{handler_file.basename}'" load_internal_handler handler_file named_handlers[handler_file.basename.to_s] = @loaded_handler if @loaded_handler end |
.loaded_handler ⇒ Obj?
self loaded_handler=
destined for storage in @handlers
89 90 91 |
# File 'lib/chook/event/handled_event/handlers.rb', line 89 def self.loaded_handler @loaded_handler end |
.loaded_handler=(anon_obj) ⇒ Object
A holding place for internal handlers as they are loaded before being added to the @handlers Hash see Chook.event_handler(&block)
99 100 101 |
# File 'lib/chook/event/handled_event/handlers.rb', line 99 def self.loaded_handler=(anon_obj) @loaded_handler = anon_obj end |
.named_handlers ⇒ Hash {String => Pathname, Proc}
getter for @named_handlers These handlers are called by name via the route “ post ‘/handler/:handler_name’”
They are not tied to any event type by their filenames its up to the writers of the handlers to make sure the webhook that calls them is sending the correct event type.
The data structure of @named_handlers is a Hash of Strings to Pathnames or Anon Objects:
handler_filename => Pathname or Obj,
handler_filename => Pathname or Obj,
handler_filename => Pathname or Obj
139 140 141 |
# File 'lib/chook/event/handled_event/handlers.rb', line 139 def self.named_handlers @named_handlers ||= {} end |
.reloading? ⇒ Boolean
Handlers can check Chook::HandledEvent::Handlers.reloading? and do stuff if desired.
117 118 119 |
# File 'lib/chook/event/handled_event/handlers.rb', line 117 def self.reloading? @reloading end |