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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +174 -0
  3. data/README.md +259 -0
  4. data/bin/chook-server +28 -0
  5. data/data/sample_handlers/RestAPIOperation-executable +91 -0
  6. data/data/sample_handlers/RestAPIOperation.rb +45 -0
  7. data/data/sample_handlers/SmartGroupComputerMembershipChange-executable +47 -0
  8. data/data/sample_handlers/SmartGroupComputerMembershipChange.rb +33 -0
  9. data/data/sample_jsons/ComputerAdded.json +27 -0
  10. data/data/sample_jsons/ComputerCheckIn.json +27 -0
  11. data/data/sample_jsons/ComputerInventoryCompleted.json +27 -0
  12. data/data/sample_jsons/ComputerPolicyFinished.json +27 -0
  13. data/data/sample_jsons/ComputerPushCapabilityChanged.json +27 -0
  14. data/data/sample_jsons/JSSShutdown.json +14 -0
  15. data/data/sample_jsons/JSSStartup.json +14 -0
  16. data/data/sample_jsons/MobileDeviceCheckIn.json +26 -0
  17. data/data/sample_jsons/MobileDeviceCommandCompleted.json +26 -0
  18. data/data/sample_jsons/MobileDeviceEnrolled.json +26 -0
  19. data/data/sample_jsons/MobileDevicePushSent.json +26 -0
  20. data/data/sample_jsons/MobileDeviceUnEnrolled.json +26 -0
  21. data/data/sample_jsons/PatchSoftwareTitleUpdated.json +14 -0
  22. data/data/sample_jsons/PushSent.json +11 -0
  23. data/data/sample_jsons/README +4 -0
  24. data/data/sample_jsons/RestAPIOperation.json +15 -0
  25. data/data/sample_jsons/SCEPChallenge.json +10 -0
  26. data/data/sample_jsons/SmartGroupComputerMembershipChange.json +13 -0
  27. data/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +13 -0
  28. data/lib/chook.rb +38 -0
  29. data/lib/chook/configuration.rb +198 -0
  30. data/lib/chook/event.rb +153 -0
  31. data/lib/chook/event/handled_event.rb +154 -0
  32. data/lib/chook/event/handled_event/handlers.rb +206 -0
  33. data/lib/chook/event/test_event.rb +140 -0
  34. data/lib/chook/event_handling.rb +40 -0
  35. data/lib/chook/event_testing.rb +43 -0
  36. data/lib/chook/foundation.rb +33 -0
  37. data/lib/chook/handled_events.rb +33 -0
  38. data/lib/chook/handled_subjects.rb +33 -0
  39. data/lib/chook/procs.rb +46 -0
  40. data/lib/chook/server.rb +121 -0
  41. data/lib/chook/server/routes.rb +27 -0
  42. data/lib/chook/server/routes/handle_webhook_event.rb +39 -0
  43. data/lib/chook/server/routes/home.rb +37 -0
  44. data/lib/chook/subject.rb +143 -0
  45. data/lib/chook/subject/computer.rb +121 -0
  46. data/lib/chook/subject/handled_subject.rb +84 -0
  47. data/lib/chook/subject/jss.rb +56 -0
  48. data/lib/chook/subject/mobile_device.rb +115 -0
  49. data/lib/chook/subject/patch_software_title_update.rb +55 -0
  50. data/lib/chook/subject/push.rb +38 -0
  51. data/lib/chook/subject/randomizers.rb +506 -0
  52. data/lib/chook/subject/rest_api_operation.rb +62 -0
  53. data/lib/chook/subject/samplers.rb +360 -0
  54. data/lib/chook/subject/scep_challenge.rb +32 -0
  55. data/lib/chook/subject/smart_group.rb +50 -0
  56. data/lib/chook/subject/test_subject.rb +195 -0
  57. data/lib/chook/subject/validators.rb +117 -0
  58. data/lib/chook/test_events.rb +33 -0
  59. data/lib/chook/test_subjects.rb +33 -0
  60. data/lib/chook/version.rb +32 -0
  61. metadata +129 -0
@@ -0,0 +1,55 @@
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
+ Chook::Subject.classes[Chook::Subject::PATCH_SW_UPDATE] = {
26
+ name: {
27
+ validation: :patch,
28
+ randomizer: :patch,
29
+ api_object_attribute: :name
30
+ },
31
+ latestVersion: {
32
+ validation: String,
33
+ randomizer: :version,
34
+ sampler: :patch_latest_version,
35
+ api_object_attribute: :patch_latest_version
36
+ },
37
+ lastUpdate: {
38
+ to_json: :to_jss_epoch,
39
+ validation: Time,
40
+ randomizer: :time,
41
+ sampler: :patch_last_update,
42
+ api_object_attribute: :patch_last_update
43
+ },
44
+ reportUrl: {
45
+ validation: :url,
46
+ randomizer: :url,
47
+ sampler: :patch_report_url,
48
+ api_object_attribute: :patch_report_url
49
+ },
50
+ jssID: {
51
+ validation: Integer,
52
+ randomizer: :int,
53
+ api_object_attribute: :id
54
+ }
55
+ }
@@ -0,0 +1,38 @@
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
+ Chook::Subject.classes[Chook::Subject::PUSH] = {
26
+ type: { # TODO: "PushSent" for a Computer or "MobileDevicePushSent" for a Mobile Device
27
+ validation: String,
28
+ randomizer: :push,
29
+ # sampler:,
30
+ # api_object_attribute: :type
31
+ },
32
+ jssID: {
33
+ validation: Integer,
34
+ randomizer: :int,
35
+ # sampler: :jssid, # TODO: This should be computer_jssid or mobile_jssid based on the type, see above
36
+ # api_object_attribute: :id
37
+ }
38
+ }
@@ -0,0 +1,506 @@
1
+ require 'securerandom'
2
+
3
+ module Chook
4
+
5
+ # A namespace for holding methods and constants
6
+ # used for creating random data for Test Events and Test Subjects.
7
+ #
8
+ module Randomizers
9
+
10
+ WORDS = Pathname.new '/usr/share/dict/words'
11
+
12
+ NAMES = Pathname.new '/usr/share/dict/propernames'
13
+
14
+ REST_OPS = %w(GET POST PUT DELETE).freeze
15
+
16
+ MOBILE_SERIAL_CHARACTER_SETS = [
17
+ %w(F D C H),
18
+ %w(4 L Q 7 M 3 K N 2 9 5 C 8 1 X Y 6 0 J F T G D A P R),
19
+ %w(L X T 8 Q 9 K V P 7 R J F 6 G N 3 M 5 Y W 4 1 H 2 C D),
20
+ %w(K M L J H G N F 3 P B Q R S A),
21
+ %w(H 6 4 C G V J 5 T R N K X 1 F L 9 Q 8 W M 2 P D 7 3 Y A),
22
+ %w(J 1 2 8 B W 0 C 4 7 F 5 6 M 3 G A E Q S N R D Z X 9 P K V Y H U T L),
23
+ %w(3 2 S Y V R M Q F J 1 8 9 L 6 H W A 4 0 E T U 5 N 7 X Z K G B D C P),
24
+ %w(V 7 Z R P C G 8 A 2 J X Q 4 D E N B 9 0 H K Y 3 6 1 L T 5 M W F U S),
25
+ %w(F D G 9 7 H 1),
26
+ %w(1 C N K F J 8 R T 2 P V 3 L 4 H 5 0 6 D M X 9 G),
27
+ %w(9 M D 1 J H 8 C 2 F P G W T Y 5 R Q 7 3 V N K X L 6 0),
28
+ %w(6 5 K 4 J W T 2 0 V M Y 9 N 8 3 1 H Q L D R 7 P G C F X)
29
+ ].freeze
30
+
31
+ COMPUTER_SERIAL_CHARACTER_SETS = [
32
+ %w(C),
33
+ %w(0 2 1 P),
34
+ %w(7 2 V M W F Q X),
35
+ %w(K L F G M N J H D P Q R S),
36
+ %w(8 G 5 7 L T M 2 P 9 X 4 K J D W C H F Q V N R 3 6 1 Y),
37
+ %w(1 9 0 7 5 2 6 B A P 4 E 3 K F R G U W C L V 8 J D T X Y M Z N S H),
38
+ %w(9 U 2 S Q H M V Z J G P D N 5 Y X 7 3 E 6 0 K T 4 L C F 8 A B W 1 R),
39
+ %w(4 E N C Y H F A G 1 B 3 0 5 8 M J W L T S D V P R K U 6 Z 2 Q 7 9 X),
40
+ %w(D F G H),
41
+ %w(Y 6 D R H 5 W G F 0 8 T K V L 2 N 3 J 9 1 C Q),
42
+ %w(3 T Q 0 Y P 5 V R 8 4 2 J 7 1 C M H N D F 6 G W),
43
+ %w(H 6 X 4 5 W L J 8 G 3 P 7 T N 9 1 F M V 0 D R K 2 C Y)
44
+ ].freeze
45
+
46
+ SAMPLE_MOBILE_MODELS = [
47
+ 'iPhone SE',
48
+ 'iPhone 7',
49
+ 'iPhone 6S Plus',
50
+ 'iPhone 6S',
51
+ 'iPhone 6',
52
+ 'iPhone 5S (GSM)',
53
+ 'iPad Air 2 (CDMA)',
54
+ 'iPad Pro (9.7-inch Wi-Fi)',
55
+ 'iPhone 6 Plus',
56
+ 'iPad Pro (9.7-inch Cellular)',
57
+ 'iPhone 5C (GSM)',
58
+ 'iPad Air (GSM)',
59
+ 'iPhone 7 Plus',
60
+ 'iPad Pro (12.9-inch Wi-Fi)',
61
+ 'iPad Air (Wi-Fi)',
62
+ 'iPhone 5 (GSM)',
63
+ 'iPad mini 2nd Generation (GSM)',
64
+ 'iPad 3rd Generation (Wi-Fi)',
65
+ 'iPad mini 2nd Generation (Wi-Fi)',
66
+ 'iPad Air 2 (Wi-Fi)',
67
+ 'iPad mini 4 (GSM)',
68
+ 'iPod touch (5th Generation)',
69
+ 'iPod touch (6th Generation)',
70
+ 'iPad Pro (12.9-inch Cellular)',
71
+ 'iPhone 5 (CDMA)',
72
+ 'iPad 3rd Generation (GSM)',
73
+ 'iPhone 4S',
74
+ 'iPad 4th Generation (Wi-Fi)',
75
+ 'iPad mini 4 (Wi-Fi)',
76
+ 'iPad mini 3 (Wi-Fi)',
77
+ 'iPhone 4 (GSM)',
78
+ 'iPhone 5S (CDMA)',
79
+ 'iPad 4th Generation (GSM)',
80
+ 'iPad 2 (Wi-Fi)',
81
+ 'iPad 4th Generation (CDMA)',
82
+ 'iPad (Original)',
83
+ 'iPad 2 (GSM)',
84
+ 'iPad mini (GSM)',
85
+ 'iPhone 5C (CDMA)',
86
+ 'iPad 3rd Generation (CDMA)',
87
+ 'iPhone3,2',
88
+ 'iPad6,11',
89
+ 'iPad mini 3 (GSM)',
90
+ 'iPad mini (CDMA)'
91
+ ].freeze
92
+
93
+ SAMPLE_COMPUTER_MODELS = [
94
+ 'MacBookPro12,1',
95
+ 'MacBookAir7,2',
96
+ 'MacBookPro11,5',
97
+ 'MacPro1,1',
98
+ 'MacPro6,1',
99
+ 'MacBookAir6,2',
100
+ 'MacBookPro11,2',
101
+ 'MacBookPro13,3',
102
+ 'Xserve3,1',
103
+ 'MacPro4,1',
104
+ 'Macmini3,1',
105
+ 'iMac15,1',
106
+ 'MacBookPro11,1',
107
+ 'MacBook9,1',
108
+ 'Macmini4,1',
109
+ 'MacPro5,1',
110
+ 'Xserve1,1',
111
+ 'MacPro3,1',
112
+ 'Macmini1,1',
113
+ 'iMac14,2',
114
+ 'Macmini6,2',
115
+ 'Macmini7,1',
116
+ 'MacBookAir6,1',
117
+ 'MacBook4,1',
118
+ 'iMac11,1',
119
+ 'MacBookPro1,1',
120
+ 'MacBookPro5,3',
121
+ 'iMac7,1',
122
+ 'MacBookAir5,2',
123
+ 'iMac13,2',
124
+ 'VMware7,1',
125
+ 'MacBook5,2',
126
+ 'MacBookPro13,2',
127
+ 'iMac11,3',
128
+ 'MacBookPro7,1',
129
+ 'MacBookPro11,3',
130
+ 'MacBookPro9,2',
131
+ 'MacBookAir3,1',
132
+ 'iMac11,2',
133
+ 'MacBookPro6,2',
134
+ 'MacBookPro9,1',
135
+ 'MacBookPro8,2',
136
+ 'MacBookPro13,1',
137
+ 'iMac12,2',
138
+ 'MacBookPro8,1',
139
+ 'MacBook7,1',
140
+ 'iMac14,1',
141
+ 'Macmini5,2',
142
+ 'iMac13,1',
143
+ 'iMac12,1',
144
+ 'iMac17,1',
145
+ 'MacBookAir7,1',
146
+ 'MacBookPro10,1',
147
+ 'MacBookAir5,1',
148
+ 'MacBookAir4,2',
149
+ 'Macmini5,1',
150
+ 'Xserve2,1',
151
+ '“MacPro6,1”'
152
+ ].freeze
153
+
154
+ # Keeping this set of PUSH_COMMANDS in here just in case JAMF decides to make the Push webhooks more useful...
155
+ # PUSH_COMMANDS = [
156
+ # 'Settings',
157
+ # 'DeviceLock',
158
+ # 'EraseDevice',
159
+ # 'ClearPasscode',
160
+ # 'UnmanageDevice',
161
+ # 'UpdateInventory',
162
+ # 'ClearRestrictionsPassword',
163
+ # 'SettingsEnableDataRoaming',
164
+ # 'SettingsDisableDataRoaming',
165
+ # 'SettingsEnableVoiceRoaming',
166
+ # 'SettingsDisableVoiceRoaming',
167
+ # 'SettingsEnableAppAnalytics',
168
+ # 'SettingsDisableAppAnalytics',
169
+ # 'SettingsEnableDiagnosticSubmission',
170
+ # 'SettingsDisableDiagnosticSubmission',
171
+ # 'BlankPush',
172
+ # 'Wallpaper', # supervised only
173
+ # 'DeviceName', # supervised only
174
+ # 'ShutDownDevice', # supervised only
175
+ # 'RestartDevice', # supervised only
176
+ # 'PasscodeLockGracePeriod' # shared iPad only
177
+ # ].freeze
178
+
179
+ PUSH_COMMANDS = %w(MobileDevicePushSent PushSent).freeze
180
+
181
+ # A full list of supported titles is unfortunately not available via the API :(
182
+ PATCH_SOFTWARE_TITLES = [
183
+ 'Adobe AIR',
184
+ 'Adobe Acrobat Pro DC',
185
+ 'Adobe Acrobat Pro XI',
186
+ 'Adobe Acrobat Reader DC',
187
+ 'Adobe Acrobat Reader XI',
188
+ 'Adobe After Effects CC',
189
+ 'Adobe Bridge CC Adobe',
190
+ 'Adobe Core Components',
191
+ 'Adobe Dreamweaver CC',
192
+ 'Adobe Fireworks CS6',
193
+ 'Adobe Flash Player',
194
+ 'Adobe Illustrator CC',
195
+ 'Adobe InDesign CC',
196
+ 'Adobe Photoshop CC',
197
+ 'Adobe Photoshop Lightroom CC',
198
+ 'Adobe Prelude CC',
199
+ 'Adobe Premiere Pro CC',
200
+ 'Adobe Shockwave Player',
201
+ 'Google Chrome',
202
+ 'Java SE Development Kit 7',
203
+ 'Java SE Development Kit 8',
204
+ 'Java SE Runtime Environment JRE 7',
205
+ 'Java SE Runtime Environment JRE 8',
206
+ 'McAfee Endpoint Security for Mac',
207
+ 'Microsoft AutoUpdate',
208
+ 'Microsoft Excel 2016',
209
+ 'Microsoft OneNote 2016',
210
+ 'Microsoft Outlook 2016',
211
+ 'Microsoft PowerPoint 2016',
212
+ 'Microsoft Silverlight',
213
+ 'Microsoft Word 2016',
214
+ 'Mozilla Firefox Extended Support Release (ESR)',
215
+ 'Mozilla Firefox',
216
+ 'Skype',
217
+ 'Skype for Business'
218
+ ].freeze
219
+
220
+ # Random Word
221
+ # Use this to generate device or username Strings
222
+ #
223
+ # @return [String] Randomly generated US English word to stand in for a username, device name, etc.
224
+ #
225
+ def self.word
226
+ WORDS.read.lines.sample.chomp
227
+ end # end word
228
+
229
+ # Random Name
230
+ #
231
+ # @return [String] Randomly generated US English formatted "FirstName LastName".
232
+ #
233
+ def self.name
234
+ NAMES.read.lines.sample.chomp + ' ' + NAMES.read.lines.sample.chomp
235
+ end # end name
236
+
237
+ # Random Email
238
+ #
239
+ # @return [String] Randomly generated email address formatted String e.g. FirstNameLastName@randomword.com
240
+ #
241
+ def self.email_address
242
+ name.gsub(' ','.') + '@' + word + '.com'
243
+ end # end email_address
244
+
245
+ # Random Int
246
+ #
247
+ # @param [Integer] Optionally choose the length of the returned random Integer
248
+ # @return [Integer] Randomized number of an optionally specified length
249
+ #
250
+ def self.int(x = 1)
251
+ startpoint = 10**(x - 1)
252
+ endpoint = (10**x) - 1
253
+ rand(startpoint..endpoint)
254
+ end # end int
255
+
256
+ # Random Serial Number
257
+ #
258
+ # @param [Array<Array>] A dataset for generating a serial number
259
+ # @return [String] Valid Computer or Mobile Device Serial Number
260
+ #
261
+ def self.serial_number_from(dataset)
262
+ serial = ''
263
+ dataset.each { |pos| serial << pos.sample }
264
+ serial
265
+ end # end serial_number
266
+
267
+ # Computer Serial Number
268
+ #
269
+ # @return [String] Valid Computer Serial Number
270
+ #
271
+ def self.computer_serial_number
272
+ serial_number_from COMPUTER_SERIAL_CHARACTER_SETS
273
+ end # end computer_serial_number
274
+
275
+ # Mobile Serial Number (wrapper)
276
+ #
277
+ # @return [String] Valid Mobile Device Serial Number
278
+ #
279
+ def self.mobile_serial_number
280
+ serial_number_from MOBILE_SERIAL_CHARACTER_SETS
281
+ end # mobile_serial_number
282
+
283
+ # Random U*ID
284
+ # MobileDevice UDID and Mac UUID are poorly distingusished in Jamf Pro.
285
+ # In a Jamf Pro Computer record, the "UDID" in the web interface corresponds to the Hardware UUID.
286
+ # On a Jamf Pro MobileDevice record, the UDID is actually a UDID.
287
+ # Since these are actually different things, they are generated differently.
288
+ #
289
+ # @return [String] Randomly generated UUID/UDID formatted String
290
+ #
291
+ def self.udid(mobile = false)
292
+ if mobile
293
+ # UDID = SHA1(serial + IMEI + wifiMac + bluetoothMac)
294
+ Digest::SHA1.hexdigest(serial_number(mobile: true) + int(15).to_s + mac_address + mac_address)
295
+ else
296
+ # UUID
297
+ # In its canonical textual representation, the sixteen octets of a UUID are represented as 32 hexadecimal (base 16) digits
298
+ # displayed in five groups separated by hyphens, in the form 8-4-4-4-12 for a total of 36 characters (32 alphanumeric characters and four hyphens).
299
+ # For example:
300
+ # 123e4567-e89b-12d3-a456-426655440000
301
+ indexes = [8, 13, 18, 23]
302
+ uuid = SecureRandom.hex(16).upcase
303
+ indexes.each { |idx| uuid.insert(idx, '-') }
304
+ uuid.upcase
305
+ end
306
+ end # end udid
307
+
308
+ # Computer UUID (wrapper)
309
+ #
310
+ # @return [String] Randomly generated computer UUID formatted String
311
+ #
312
+ def self.computer_udid
313
+ udid
314
+ end # end computer_udid
315
+
316
+ # Mobile UDID (wrapper)
317
+ #
318
+ # @return [String] Randomly generated mobile UDID formatted String
319
+ #
320
+ def self.mobile_udid
321
+ udid(true)
322
+ end # end mobile_udid
323
+
324
+ # Product is null in the sample JSONs... And there isn't anything labeled "product" in JSS::API.get_rsrc("mobiledevices/id/#{id}")
325
+ def self.product
326
+ nil
327
+ end # end product
328
+
329
+ # Random MAC Address
330
+ #
331
+ # @return [String] Randomly generated MAC address formatted String
332
+ #
333
+ def self.mac_address
334
+ SecureRandom.hex(6).upcase.scan(/.{2}/).join(':')
335
+ end # end mac_address
336
+
337
+ # Random IMEI
338
+ #
339
+ # @return [String] Randomly generated IMEI formatted number String
340
+ #
341
+ def self.imei
342
+ indexes = [2, 9, 16]
343
+ imei = int(15).to_s
344
+ indexes.each { |idx| imei.insert(idx, ' ') }
345
+ imei
346
+ end # end imei
347
+
348
+ # Random ICCID
349
+ #
350
+ # @return [String] Randomly generated ICCID formatted number String
351
+ #
352
+ def self.iccid
353
+ int(20).to_s.scan(/.{4}/).join(' ')
354
+ end # end iccid
355
+
356
+ # Random Model
357
+ #
358
+ # @param [Boolean] mobile Returns a valid Computer model by default, mobile: true returns a valid Mobile Device model
359
+ # @return [String] Randomly selected Computer or MobileDevice model
360
+ #
361
+ def self.model(mobile = false)
362
+ if mobile
363
+ SAMPLE_MOBILE_MODELS.sample
364
+ else
365
+ SAMPLE_COMPUTER_MODELS.sample
366
+ end
367
+ end # end model
368
+
369
+ # Mobile Model (wrapper)
370
+ #
371
+ # @return [String] Randomly selected MobileDevice model
372
+ #
373
+ def self.mobile_model
374
+ model(true)
375
+ end # end mobile_model
376
+
377
+ # Computer Model (wrapper)
378
+ #
379
+ # @return [String] Randomly selected Computer model
380
+ #
381
+ def self.computer_model
382
+ model
383
+ end # end computer_model
384
+
385
+ # Version
386
+ #
387
+ # @return [String] Carrier Settings Version formatted String
388
+ #
389
+ def self.version
390
+ [int(2), int].join('.')
391
+ end # end version
392
+
393
+ # Random OS Version
394
+ #
395
+ # @param [Boolean] mobile Returns a randomized Computer OS version by default, mobile: true returns a randomized Mobile Device OS version
396
+ # @return [Type] String
397
+ #
398
+ def self.os_version(mobile = false)
399
+ if mobile
400
+ [rand(4..11), int, int].join('.')
401
+ else
402
+ [10, rand(6..15), int].join('.')
403
+ end
404
+ end # end os_version
405
+
406
+ # Mobile OS Version (wrapper)
407
+ #
408
+ # @return [String] Operating System Version from a MobileDevice in the JSS
409
+ #
410
+ def self.mobile_os_version
411
+ os_version(true)
412
+ end # end mobile_os_version
413
+
414
+ # Computer OS Version (wrapper)
415
+ #
416
+ # @return [String] Operating System Version from a Computer in the JSS
417
+ #
418
+ def self.computer_os_version
419
+ os_version
420
+ end # end computer_os_version
421
+
422
+ # Random OS Build
423
+ #
424
+ # @return [String] Randomized OS build string
425
+ #
426
+ def self.os_build
427
+ SecureRandom.hex(3).upcase
428
+ end # end os_build
429
+
430
+ # Random Boolean
431
+ #
432
+ # @return [Boolean] True or False
433
+ #
434
+ def self.bool
435
+ rand(0..1).zero?
436
+ end # end bool
437
+
438
+ # Random REST Operation
439
+ #
440
+ # @return [String] Random GET, POST, PUT, or DELETE
441
+ #
442
+ def self.rest_operation
443
+ REST_OPS.sample
444
+ end # end rest_operation
445
+
446
+ # Random Phone Number
447
+ #
448
+ # @return [String] Random US-formatted Phone Number
449
+ #
450
+ def self.phone
451
+ raw_phone = int(10).to_s.split(//)
452
+ [3, 7].each { |index| raw_phone.insert(index, '-') }
453
+ raw_phone.join('')
454
+ end # end phone
455
+
456
+ # Random Room Number
457
+ #
458
+ # @return [String] Random Room Number
459
+ #
460
+ def self.room
461
+ int((1..4).to_a.sample).to_s
462
+ end # end room
463
+
464
+ # Random Push Command
465
+ #
466
+ # @return [String] Random Push Command from PUSH_COMMANDS
467
+ #
468
+ def self.push
469
+ PUSH_COMMANDS.sample
470
+ end # end push
471
+
472
+ # Random Patch Software Title
473
+ #
474
+ # @return [String] Random Patch Software Title
475
+ #
476
+ def self.patch
477
+ PATCH_SOFTWARE_TITLES.sample
478
+ end # end patch
479
+
480
+ # Random Time (for lastUpdate in Patch Software Update subject)
481
+ #
482
+ # @return [Time] A random date and time
483
+ #
484
+ def self.time
485
+ Time.at(rand * Time.now.to_i)
486
+ end # end time
487
+
488
+ # Random URL-formatted String
489
+ #
490
+ # @return [String] A random URL-formatted String
491
+ #
492
+ def self.url
493
+ "http://www.#{word}.com:#{int}"
494
+ end # end url
495
+
496
+ # Random hostname-formatted String
497
+ #
498
+ # @return [String] A random hostname-formatted String
499
+ #
500
+ def self.host
501
+ "#{word}.#{word}.com"
502
+ end # end host
503
+
504
+ end # module randomizers
505
+
506
+ end # mod chook