chook 1.0.0.b1
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.
- checksums.yaml +7 -0
- data/LICENSE.txt +174 -0
- data/README.md +259 -0
- data/bin/chook-server +28 -0
- data/data/sample_handlers/RestAPIOperation-executable +91 -0
- data/data/sample_handlers/RestAPIOperation.rb +45 -0
- data/data/sample_handlers/SmartGroupComputerMembershipChange-executable +47 -0
- data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +33 -0
- data/data/sample_jsons/ComputerAdded.json +27 -0
- data/data/sample_jsons/ComputerCheckIn.json +27 -0
- data/data/sample_jsons/ComputerInventoryCompleted.json +27 -0
- data/data/sample_jsons/ComputerPolicyFinished.json +27 -0
- data/data/sample_jsons/ComputerPushCapabilityChanged.json +27 -0
- data/data/sample_jsons/JSSShutdown.json +14 -0
- data/data/sample_jsons/JSSStartup.json +14 -0
- data/data/sample_jsons/MobileDeviceCheckIn.json +26 -0
- data/data/sample_jsons/MobileDeviceCommandCompleted.json +26 -0
- data/data/sample_jsons/MobileDeviceEnrolled.json +26 -0
- data/data/sample_jsons/MobileDevicePushSent.json +26 -0
- data/data/sample_jsons/MobileDeviceUnEnrolled.json +26 -0
- data/data/sample_jsons/PatchSoftwareTitleUpdated.json +14 -0
- data/data/sample_jsons/PushSent.json +11 -0
- data/data/sample_jsons/README +4 -0
- data/data/sample_jsons/RestAPIOperation.json +15 -0
- data/data/sample_jsons/SCEPChallenge.json +10 -0
- data/data/sample_jsons/SmartGroupComputerMembershipChange.json +13 -0
- data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +13 -0
- data/lib/chook.rb +38 -0
- data/lib/chook/configuration.rb +198 -0
- data/lib/chook/event.rb +153 -0
- data/lib/chook/event/handled_event.rb +154 -0
- data/lib/chook/event/handled_event/handlers.rb +206 -0
- data/lib/chook/event/test_event.rb +140 -0
- data/lib/chook/event_handling.rb +40 -0
- data/lib/chook/event_testing.rb +43 -0
- data/lib/chook/foundation.rb +33 -0
- data/lib/chook/handled_events.rb +33 -0
- data/lib/chook/handled_subjects.rb +33 -0
- data/lib/chook/procs.rb +46 -0
- data/lib/chook/server.rb +121 -0
- data/lib/chook/server/routes.rb +27 -0
- data/lib/chook/server/routes/handle_webhook_event.rb +39 -0
- data/lib/chook/server/routes/home.rb +37 -0
- data/lib/chook/subject.rb +143 -0
- data/lib/chook/subject/computer.rb +121 -0
- data/lib/chook/subject/handled_subject.rb +84 -0
- data/lib/chook/subject/jss.rb +56 -0
- data/lib/chook/subject/mobile_device.rb +115 -0
- data/lib/chook/subject/patch_software_title_update.rb +55 -0
- data/lib/chook/subject/push.rb +38 -0
- data/lib/chook/subject/randomizers.rb +506 -0
- data/lib/chook/subject/rest_api_operation.rb +62 -0
- data/lib/chook/subject/samplers.rb +360 -0
- data/lib/chook/subject/scep_challenge.rb +32 -0
- data/lib/chook/subject/smart_group.rb +50 -0
- data/lib/chook/subject/test_subject.rb +195 -0
- data/lib/chook/subject/validators.rb +117 -0
- data/lib/chook/test_events.rb +33 -0
- data/lib/chook/test_subjects.rb +33 -0
- data/lib/chook/version.rb +32 -0
- metadata +129 -0
@@ -0,0 +1,154 @@
|
|
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
|
+
require 'chook/event/handled_event/handlers'
|
27
|
+
|
28
|
+
#
|
29
|
+
module Chook
|
30
|
+
|
31
|
+
# Load sample JSON files, one per event type
|
32
|
+
@sample_jsons = {}
|
33
|
+
base_dir = Pathname.new(__FILE__)
|
34
|
+
data_dir = base_dir.parent.parent.parent.parent
|
35
|
+
sample_json_dir = Pathname.new(data_dir.to_s + '/data/sample_jsons')
|
36
|
+
sample_json_dir.children.each do |jf|
|
37
|
+
event = jf.basename.to_s.chomp(jf.extname).to_sym
|
38
|
+
@sample_jsons[event] = jf.read
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.sample_jsons
|
42
|
+
@sample_jsons
|
43
|
+
end
|
44
|
+
|
45
|
+
# An event that has been recieved and needs to be handled.
|
46
|
+
#
|
47
|
+
# This is the parent class to all of the classes in the
|
48
|
+
# Chook::HandledEvents module, which are dynamically defined when this
|
49
|
+
# file is loaded.
|
50
|
+
#
|
51
|
+
# All constants, methods, and attributes that are common to HandledEvent
|
52
|
+
# classes are defined here, including the interaction with the Handlers
|
53
|
+
# module.
|
54
|
+
#
|
55
|
+
# Subclasses are automatically generated from the keys and values of
|
56
|
+
# Chook::Event::EVENTS
|
57
|
+
#
|
58
|
+
# Each subclass will have a constant SUBJECT_CLASS containing the
|
59
|
+
# class of their #subject attribute.
|
60
|
+
#
|
61
|
+
class HandledEvent < Chook::Event
|
62
|
+
|
63
|
+
#### Class Methods
|
64
|
+
|
65
|
+
# Given some raw_json from the jss, create and return the correct
|
66
|
+
# HandledEvent subclass
|
67
|
+
|
68
|
+
# For each event type in Chook::Event::EVENTS
|
69
|
+
# generate a class for it, set its SUBJECT_CLASS constant
|
70
|
+
# and add it to the HandledEvents module.
|
71
|
+
#
|
72
|
+
# @return [void]
|
73
|
+
#
|
74
|
+
def self.generate_classes
|
75
|
+
Chook::Event::EVENTS.each do |class_name, subject|
|
76
|
+
next if Chook::HandledEvents.const_defined? class_name
|
77
|
+
|
78
|
+
# make the new HandledEvent subclass
|
79
|
+
the_class = Class.new(Chook::HandledEvent)
|
80
|
+
|
81
|
+
# Set its EVENT_NAME constant, which is used
|
82
|
+
# for finding it's handlers, among other things.
|
83
|
+
the_class.const_set Chook::Event::EVENT_NAME_CONST, class_name
|
84
|
+
|
85
|
+
# Set its SUBJECT_CLASS constant to the appropriate
|
86
|
+
# class in the HandledSubjects module.
|
87
|
+
the_class.const_set Chook::Event::SUBJECT_CLASS_CONST, Chook::HandledSubjects.const_get(subject)
|
88
|
+
|
89
|
+
# Add the new class to the HandledEvents module.
|
90
|
+
Chook::HandledEvents.const_set(class_name, the_class)
|
91
|
+
end # each classname, subject
|
92
|
+
end # self.generate_classes
|
93
|
+
|
94
|
+
# Given the raw json from the JSS webhook,
|
95
|
+
# create an object of the correct Event subclass
|
96
|
+
#
|
97
|
+
# @param [String] raw_event_json The JSON http POST content from the JSS
|
98
|
+
#
|
99
|
+
# @return [JSSWebHooks::Event subclass] the Event subclass matching the event
|
100
|
+
#
|
101
|
+
def self.parse_event(raw_event_json)
|
102
|
+
event_json = JSON.parse(raw_event_json, symbolize_names: true)
|
103
|
+
event_name = event_json[:webhook][:webhookEvent]
|
104
|
+
Chook::HandledEvents.const_get(event_name).new raw_event_json
|
105
|
+
end
|
106
|
+
|
107
|
+
#### Attributes
|
108
|
+
|
109
|
+
# @return [Array<Proc,Pathname>] the handlers defined for this event.
|
110
|
+
# Each is either a proc, in which case it is called with this
|
111
|
+
# instance as its sole paramter, or its a Pathname to an executable
|
112
|
+
# file, in which case the @raw_json is passed to its stdin.
|
113
|
+
# See the Chook::HandledEvent::Handlers module.
|
114
|
+
attr_reader :handlers
|
115
|
+
|
116
|
+
#### Constructor
|
117
|
+
|
118
|
+
# Handled Events are always built from raw_json.
|
119
|
+
#
|
120
|
+
def initialize(raw_event_json)
|
121
|
+
super raw_json: raw_event_json
|
122
|
+
end # init
|
123
|
+
|
124
|
+
def handle
|
125
|
+
handlers = Handlers.handlers[self.class.const_get(Chook::Event::EVENT_NAME_CONST)]
|
126
|
+
handlers.each do |handler|
|
127
|
+
case handler
|
128
|
+
when Pathname
|
129
|
+
pipe_to_executable handler
|
130
|
+
when Proc
|
131
|
+
handle_with_proc handler
|
132
|
+
end # case
|
133
|
+
end # @handlers.each do |handler|
|
134
|
+
|
135
|
+
# the handle method should return a string,
|
136
|
+
# which is the body of the HTTP result for
|
137
|
+
# POSTing the event
|
138
|
+
"Processed by #{handlers.count} handlers\n"
|
139
|
+
end # def handle
|
140
|
+
|
141
|
+
# TODO: Add something here that cleans up old threads and forks
|
142
|
+
def pipe_to_executable(handler)
|
143
|
+
_thread = Thread.new do
|
144
|
+
IO.popen([handler.to_s], 'w') { |h| h.puts @raw_json }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def handle_with_proc(handler)
|
149
|
+
_thread = Thread.new { handler.call self }
|
150
|
+
end
|
151
|
+
|
152
|
+
end # class HandledEvent
|
153
|
+
|
154
|
+
end # module
|
@@ -0,0 +1,206 @@
|
|
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
|
+
module Chook
|
26
|
+
|
27
|
+
# This method is used by the Ruby event-handler files.
|
28
|
+
#
|
29
|
+
# Loading them should call this method and pass in a block
|
30
|
+
# with one parameter: a Chook::HandledEvent subclass instance.
|
31
|
+
#
|
32
|
+
# The block is then converted to a Proc instance in @loaded_event_handler
|
33
|
+
# and from there can be stored for use by the event identified by the filename.
|
34
|
+
#
|
35
|
+
# NOTE: the files should be read with 'load' not 'require', so that they can
|
36
|
+
# be re-loaded as needed
|
37
|
+
#
|
38
|
+
# @see_also Chook::load_handlers
|
39
|
+
#
|
40
|
+
# @param [Block] block the block to be used as an event handler
|
41
|
+
#
|
42
|
+
# @yieldparam [JSS::WebHooks::Event subclass] The event to be handled
|
43
|
+
#
|
44
|
+
# @return [Proc] the block converted to a Proc
|
45
|
+
#
|
46
|
+
def self.event_handler(&block)
|
47
|
+
HandledEvent::Handlers.loaded_handler = Proc.new(&block)
|
48
|
+
end
|
49
|
+
|
50
|
+
# the server class
|
51
|
+
class HandledEvent < Event
|
52
|
+
|
53
|
+
# The Handlers namespace module
|
54
|
+
module Handlers
|
55
|
+
|
56
|
+
# Module Constants
|
57
|
+
############################
|
58
|
+
|
59
|
+
DEFAULT_HANDLER_DIR = '/Library/Application Support/Chook'.freeze
|
60
|
+
|
61
|
+
# Module Instance Variables, & accessors
|
62
|
+
############################
|
63
|
+
|
64
|
+
# This holds the most recently loaded Proc handler
|
65
|
+
# until it can be stored in the @handlers Hash
|
66
|
+
@loaded_handler = nil
|
67
|
+
|
68
|
+
# Getter for @loaded_handler
|
69
|
+
#
|
70
|
+
# @return [Proc,nil] the most recent Proc loaded from a handler file.
|
71
|
+
# destined for storage in @handlers
|
72
|
+
#
|
73
|
+
def self.loaded_handler
|
74
|
+
@loaded_handler
|
75
|
+
end
|
76
|
+
|
77
|
+
# Setter for @loaded_event_handler
|
78
|
+
#
|
79
|
+
# @param a_proc [Proc] a Proc object for storage in @handlers
|
80
|
+
#
|
81
|
+
def self.loaded_handler=(a_proc)
|
82
|
+
@loaded_handler = a_proc
|
83
|
+
end
|
84
|
+
|
85
|
+
# A hash of loaded handlers.
|
86
|
+
# Keys are Strings - the name of the events handled
|
87
|
+
# Values are Arrays of either Procs, or Pathnames to executable files.
|
88
|
+
# See the .handlers getter Methods
|
89
|
+
@handlers = {}
|
90
|
+
|
91
|
+
# Getter for @event_handlers
|
92
|
+
#
|
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
|
+
def self.handlers
|
98
|
+
@handlers
|
99
|
+
end
|
100
|
+
|
101
|
+
# Module Methods
|
102
|
+
############################
|
103
|
+
|
104
|
+
# Load all the event handlers from the handler_dir or an arbitrary dir.
|
105
|
+
#
|
106
|
+
# @param from_dir [String, Pathname] directory from which to load the
|
107
|
+
# handlers. Defaults to CONFIG.handler_dir or DEFAULT_HANDLER_DIR if
|
108
|
+
# config is unset
|
109
|
+
#
|
110
|
+
# @param reload [Boolean] should we reload handlers if they've already
|
111
|
+
# been loaded?
|
112
|
+
#
|
113
|
+
# @return [void]
|
114
|
+
#
|
115
|
+
def self.load_handlers(from_dir: Chook::CONFIG.handler_dir, reload: false)
|
116
|
+
from_dir ||= DEFAULT_HANDLER_DIR
|
117
|
+
if reload
|
118
|
+
@handlers_loaded_from = nil
|
119
|
+
@handlers = {}
|
120
|
+
@loaded_handler = nil
|
121
|
+
end
|
122
|
+
|
123
|
+
handler_dir = Pathname.new(from_dir)
|
124
|
+
return unless handler_dir.directory? && handler_dir.readable?
|
125
|
+
|
126
|
+
handler_dir.children.each do |handler_file|
|
127
|
+
load_handler(handler_file) if handler_file.file? && handler_file.readable?
|
128
|
+
end
|
129
|
+
|
130
|
+
@handlers_loaded_from = handler_dir
|
131
|
+
@handlers.values.flatten.size
|
132
|
+
end # load handlers
|
133
|
+
|
134
|
+
# Load an event handler from a file.
|
135
|
+
# Handler files must begin with the name of the event they handle,
|
136
|
+
# e.g. ComputerAdded, followed by: nothing, a dot, a dash, or
|
137
|
+
# and underscore. Case doesn't matter.
|
138
|
+
# So all of these are OK:
|
139
|
+
# ComputerAdded
|
140
|
+
# computeradded.sh
|
141
|
+
# COMPUTERAdded_notify_team
|
142
|
+
# Computeradded-update-ldap
|
143
|
+
# There can be as many as desired for each event.
|
144
|
+
#
|
145
|
+
# Each must be either:
|
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
|
157
|
+
#
|
158
|
+
# @return [void]
|
159
|
+
#
|
160
|
+
def self.load_handler(from_file)
|
161
|
+
handler_file = Pathname.new from_file
|
162
|
+
event_name = event_name_from_handler_filename(handler_file)
|
163
|
+
return unless event_name
|
164
|
+
|
165
|
+
# create an array for this event's handlers, if needed
|
166
|
+
@handlers[event_name] ||= []
|
167
|
+
|
168
|
+
if handler_file.executable?
|
169
|
+
# store as a Pathname, we'll pipe JSON to it
|
170
|
+
unless @handlers[event_name].include? handler_file
|
171
|
+
@handlers[event_name] << handler_file
|
172
|
+
puts "===> Loaded executable handler file '#{handler_file.basename}'"
|
173
|
+
end
|
174
|
+
return
|
175
|
+
end
|
176
|
+
|
177
|
+
# load the file. If written correctly, it will
|
178
|
+
# put a Proc into @loaded_handler
|
179
|
+
load handler_file.to_s
|
180
|
+
if @loaded_handler
|
181
|
+
@handlers[event_name] << @loaded_handler
|
182
|
+
puts "===> Loaded internal handler file '#{handler_file.basename}'"
|
183
|
+
@loaded_handler = nil
|
184
|
+
else
|
185
|
+
puts "===> FAILED loading internal handler file '#{handler_file.basename}'"
|
186
|
+
end
|
187
|
+
end # self.load_handler(handler_file)
|
188
|
+
|
189
|
+
# Given a handler filename, return the event name it wants to handle
|
190
|
+
#
|
191
|
+
# @param [Pathname] filename The filename from which to glean the
|
192
|
+
# event name.
|
193
|
+
#
|
194
|
+
# @return [String,nil] The matching event name or nil if no match
|
195
|
+
#
|
196
|
+
def self.event_name_from_handler_filename(filename)
|
197
|
+
@event_names ||= Chook::Event::EVENTS.keys
|
198
|
+
desired_event_name = filename.basename.to_s.split(/\.|-|_/).first
|
199
|
+
@event_names.select { |n| desired_event_name.casecmp(n).zero? }.first
|
200
|
+
end
|
201
|
+
|
202
|
+
end # module Handler
|
203
|
+
|
204
|
+
end # class handledevent
|
205
|
+
|
206
|
+
end # module
|
@@ -0,0 +1,140 @@
|
|
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
|
+
# An event that will be sent to a Webhook Server, simulating
|
29
|
+
# one from the JSS.
|
30
|
+
#
|
31
|
+
# This is the parent class to all of the classes in the
|
32
|
+
# Chook::TestEvents module, which are dynamically defined when this
|
33
|
+
# file is loaded.
|
34
|
+
#
|
35
|
+
# All constants, methods, and attributes that are common to TestEvent
|
36
|
+
# classes are defined here.
|
37
|
+
#
|
38
|
+
class TestEvent < Chook::Event
|
39
|
+
|
40
|
+
EVENT_ATTRIBUTES = %w(webhook_id webhook_name subject).freeze
|
41
|
+
|
42
|
+
# For each event type in Chook::Event::EVENTS.keys
|
43
|
+
# generate a TestEvent class for it, set its SUBJECT_CLASS constant
|
44
|
+
# and add it to the TestEvents module.
|
45
|
+
#
|
46
|
+
# @return [void]
|
47
|
+
#
|
48
|
+
def self.generate_classes
|
49
|
+
Chook::Event::EVENTS.each do |classname, subject|
|
50
|
+
next if Chook::TestEvents.const_defined? classname
|
51
|
+
# make the new TestEvent subclass
|
52
|
+
new_class = Class.new(Chook::TestEvent) do
|
53
|
+
# Setters & Getters
|
54
|
+
EVENT_ATTRIBUTES.each do |attribute|
|
55
|
+
# Getter
|
56
|
+
attr_reader attribute
|
57
|
+
# Setter
|
58
|
+
if attribute == 'subject'
|
59
|
+
define_method("#{attribute}=") do |new_val|
|
60
|
+
raise "Invalid TestSubject: Chook::TestEvents::#{classname} requires a Chook::TestSubjects::#{EVENTS[classname]}" unless Chook::Validators.send(:valid_test_subject, classname, new_val)
|
61
|
+
instance_variable_set(('@' + attribute.to_s), new_val)
|
62
|
+
end # end define_method
|
63
|
+
else
|
64
|
+
define_method("#{attribute}=") do |new_val|
|
65
|
+
instance_variable_set(('@' + attribute.to_s), new_val)
|
66
|
+
end # end define_method
|
67
|
+
end
|
68
|
+
end # end EVENT_ATTRIBUTES.each do |attribute|
|
69
|
+
end # end new_class
|
70
|
+
|
71
|
+
# Set its EVENT_NAME constant
|
72
|
+
new_class.const_set Chook::TestEvent::EVENT_NAME_CONST, classname
|
73
|
+
|
74
|
+
# Set its SUBJECT_CLASS constant to the appropriate
|
75
|
+
# class in the TestEvents module.
|
76
|
+
new_class.const_set Chook::TestEvent::SUBJECT_CLASS_CONST, Chook::TestSubjects.const_get(subject)
|
77
|
+
|
78
|
+
# Add the new class to the HandledEvents module.
|
79
|
+
Chook::TestEvents.const_set(classname, new_class)
|
80
|
+
end # each classname, subject
|
81
|
+
end # self.generate_classes
|
82
|
+
|
83
|
+
# json_hash
|
84
|
+
# Used by the fire method
|
85
|
+
#
|
86
|
+
# @return [Hash] A JSON Event payload formatted as a Hash.
|
87
|
+
#
|
88
|
+
def json_hash
|
89
|
+
raw_hash_form = {}
|
90
|
+
raw_hash_form['webhook'.to_sym] = { 'webhookEvent'.to_sym => self.class.to_s.split('::')[-1] }
|
91
|
+
EVENT_ATTRIBUTES.each do |json_attribute|
|
92
|
+
next if json_attribute.include? 'json'
|
93
|
+
if json_attribute == 'subject'
|
94
|
+
raw_hash_form['event'.to_sym] = instance_variable_get('@' + json_attribute).json_hash
|
95
|
+
else
|
96
|
+
json_hash_attribute = json_attribute.split('webhook_')[1] || json_attribute
|
97
|
+
nested_hash = Hash.new do |hash, key|
|
98
|
+
hash[key] = {}
|
99
|
+
end # end nested_hash
|
100
|
+
nested_hash[json_hash_attribute.to_sym] = instance_variable_get('@' + json_attribute)
|
101
|
+
raw_hash_form['webhook'.to_sym][nested_hash.keys[0]] = nested_hash[nested_hash.keys[0]]
|
102
|
+
end
|
103
|
+
end # end EVENT_ATTRIBUTES.each do |json_attribute|
|
104
|
+
raw_hash_form # This is the structural equivalent of the Chook::Event @json_hash form
|
105
|
+
end # end json_hash
|
106
|
+
|
107
|
+
# fire
|
108
|
+
#
|
109
|
+
# @param [String] server_url The URL of a server that can handle an Event
|
110
|
+
# @return [void]
|
111
|
+
#
|
112
|
+
def fire(server_url)
|
113
|
+
raise 'Please provide a destination server URL' unless server_url
|
114
|
+
uri = URI.parse(server_url)
|
115
|
+
raise 'Please provide a valid destination server URL' if uri.host.nil?
|
116
|
+
data = json_hash.to_json # This is the structural equivalent of the Chook::Event @raw_json form
|
117
|
+
http_connection = Net::HTTP.new uri.host, uri.port
|
118
|
+
http_connection.post(uri, data)
|
119
|
+
end # end fire
|
120
|
+
|
121
|
+
# initialize
|
122
|
+
# The optional argument is a Hash with the appropriate keys defiend
|
123
|
+
#
|
124
|
+
# @param [Hash] event_data nil or Hash
|
125
|
+
# @return [TestEvent] A new TestEvents subclass object
|
126
|
+
#
|
127
|
+
def initialize(event_data = nil)
|
128
|
+
if event_data
|
129
|
+
event_data.each do |key, value|
|
130
|
+
next unless EVENT_ATTRIBUTES.include? key
|
131
|
+
instance_variable_set(('@' + key.to_s), value)
|
132
|
+
end # event_data.each
|
133
|
+
else
|
134
|
+
EVENT_ATTRIBUTES.each { |attribute| instance_variable_set(('@' + attribute.to_s), nil) }
|
135
|
+
end # end if event_data
|
136
|
+
end # end init
|
137
|
+
|
138
|
+
end # class TestEvent
|
139
|
+
|
140
|
+
end # module
|