ruby-jss 0.6.5 → 0.6.6

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 (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +57 -5
  3. data/lib/jss.rb +78 -94
  4. data/lib/jss/api_connection.rb +8 -0
  5. data/lib/jss/api_object.rb +126 -102
  6. data/lib/jss/api_object/creatable.rb +33 -15
  7. data/lib/jss/api_object/distribution_point.rb +4 -1
  8. data/lib/jss/api_object/extension_attribute.rb +1 -1
  9. data/lib/jss/api_object/package.rb +121 -187
  10. data/lib/jss/api_object/policy.rb +590 -251
  11. data/lib/jss/api_object/script.rb +92 -128
  12. data/lib/jss/api_object/self_servable.rb +93 -117
  13. data/lib/jss/api_object/updatable.rb +12 -27
  14. data/lib/jss/api_object/uploadable.rb +12 -15
  15. data/lib/jss/client.rb +178 -156
  16. data/lib/jss/db_connection.rb +34 -49
  17. data/lib/jss/ruby_extensions/string.rb +25 -21
  18. data/lib/jss/version.rb +1 -1
  19. data/lib/jss/webhooks.rb +52 -0
  20. data/lib/jss/webhooks/README.md +269 -0
  21. data/lib/jss/webhooks/configuration.rb +212 -0
  22. data/lib/jss/webhooks/data/sample_handlers/RestAPIOperation-executable +90 -0
  23. data/lib/jss/webhooks/data/sample_handlers/RestAPIOperation.rb +44 -0
  24. data/lib/jss/webhooks/data/sample_jsons/ComputerAdded.json +27 -0
  25. data/lib/jss/webhooks/data/sample_jsons/ComputerCheckIn.json +27 -0
  26. data/lib/jss/webhooks/data/sample_jsons/ComputerInventoryCompleted.json +27 -0
  27. data/lib/jss/webhooks/data/sample_jsons/ComputerPolicyFinished.json +27 -0
  28. data/lib/jss/webhooks/data/sample_jsons/ComputerPushCapabilityChanged.json +27 -0
  29. data/lib/jss/webhooks/data/sample_jsons/JSSShutdown.json +14 -0
  30. data/lib/jss/webhooks/data/sample_jsons/JSSStartup.json +14 -0
  31. data/lib/jss/webhooks/data/sample_jsons/MobileDeviceCheckIn.json +26 -0
  32. data/lib/jss/webhooks/data/sample_jsons/MobileDeviceCommandCompleted.json +26 -0
  33. data/lib/jss/webhooks/data/sample_jsons/MobileDeviceEnrolled.json +26 -0
  34. data/lib/jss/webhooks/data/sample_jsons/MobileDevicePushSent.json +26 -0
  35. data/lib/jss/webhooks/data/sample_jsons/MobileDeviceUnEnrolled.json +26 -0
  36. data/lib/jss/webhooks/data/sample_jsons/PatchSoftwareTitleUpdated.json +14 -0
  37. data/lib/jss/webhooks/data/sample_jsons/PushSent.json +11 -0
  38. data/lib/jss/webhooks/data/sample_jsons/RestAPIOperation.json +15 -0
  39. data/lib/jss/webhooks/data/sample_jsons/SCEPChallenge.json +10 -0
  40. data/lib/jss/webhooks/data/sample_jsons/SmartGroupComputerMembershipChange.json +13 -0
  41. data/lib/jss/webhooks/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +13 -0
  42. data/lib/jss/webhooks/event.rb +138 -0
  43. data/lib/jss/webhooks/event/computer_added.rb +37 -0
  44. data/lib/jss/webhooks/event/computer_check_in.rb +37 -0
  45. data/lib/jss/webhooks/event/computer_inventory_completed.rb +37 -0
  46. data/lib/jss/webhooks/event/computer_policy_finished.rb +37 -0
  47. data/lib/jss/webhooks/event/computer_push_capability_changed.rb +37 -0
  48. data/lib/jss/webhooks/event/handlers.rb +191 -0
  49. data/lib/jss/webhooks/event/jss_shutdown.rb +37 -0
  50. data/lib/jss/webhooks/event/jss_startup.rb +37 -0
  51. data/lib/jss/webhooks/event/mobile_device_check_in.rb +37 -0
  52. data/lib/jss/webhooks/event/mobile_device_command_completed.rb +37 -0
  53. data/lib/jss/webhooks/event/mobile_device_enrolled.rb +37 -0
  54. data/lib/jss/webhooks/event/mobile_device_push_sent.rb +37 -0
  55. data/lib/jss/webhooks/event/mobile_device_unenrolled.rb +37 -0
  56. data/lib/jss/webhooks/event/patch_software_title_updated.rb +37 -0
  57. data/lib/jss/webhooks/event/push_sent.rb +37 -0
  58. data/lib/jss/webhooks/event/rest_api_operation.rb +37 -0
  59. data/lib/jss/webhooks/event/scep_challenge.rb +37 -0
  60. data/lib/jss/webhooks/event/smart_group_computer_membership_change.rb +37 -0
  61. data/lib/jss/webhooks/event/smart_group_mobile_device_membership_change.rb +37 -0
  62. data/lib/jss/webhooks/event/webhook.rb +39 -0
  63. data/lib/jss/webhooks/event_objects.rb +111 -0
  64. data/lib/jss/webhooks/event_objects/computer.rb +48 -0
  65. data/lib/jss/webhooks/event_objects/jss.rb +35 -0
  66. data/lib/jss/webhooks/event_objects/mobile_device.rb +47 -0
  67. data/lib/jss/webhooks/event_objects/patch_software_title_update.rb +37 -0
  68. data/lib/jss/webhooks/event_objects/push.rb +32 -0
  69. data/lib/jss/webhooks/event_objects/rest_api_operation.rb +36 -0
  70. data/lib/jss/webhooks/event_objects/scep_challenge.rb +31 -0
  71. data/lib/jss/webhooks/event_objects/smart_group.rb +34 -0
  72. data/lib/jss/webhooks/server_app.rb +36 -0
  73. data/lib/jss/webhooks/server_app/routes.rb +26 -0
  74. data/lib/jss/webhooks/server_app/routes/handle_webhook_event.rb +38 -0
  75. data/lib/jss/webhooks/server_app/routes/home.rb +36 -0
  76. data/lib/jss/webhooks/server_app/self_signed_cert.rb +64 -0
  77. data/lib/jss/webhooks/server_app/server.rb +59 -0
  78. data/lib/jss/webhooks/version.rb +31 -0
  79. metadata +63 -4
@@ -25,20 +25,15 @@
25
25
  ###
26
26
  module JSS
27
27
 
28
- #####################################
29
28
  ### Module Variables
30
29
  #####################################
31
30
 
32
-
33
- #####################################
34
31
  ### Module Methods
35
32
  #####################################
36
33
 
37
- #####################################
38
34
  ### Sub-Modules
39
35
  #####################################
40
36
 
41
- ###
42
37
  ### A mix-in module that allows objects to be created in the JSS
43
38
  ### via the API.
44
39
  ###
@@ -63,35 +58,58 @@ module JSS
63
58
  ###
64
59
  module Creatable
65
60
 
66
- #####################################
67
61
  ### Constants
68
62
  #####################################
69
63
 
70
64
  CREATABLE = true
71
65
 
72
- #####################################
73
66
  ### Variables
74
67
  #####################################
75
68
 
76
- #####################################
77
69
  ### Mixed-in Instance Methods
78
70
  #####################################
79
71
 
80
- ###
81
72
  ### Create a new object in the JSS.
82
73
  ###
83
74
  ### @return [Integer] the jss ID of the newly created object
84
75
  ###
85
76
  def create
86
- raise JSS::UnsupportedError, "Creating or editing #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." unless CREATABLE
77
+ raise JSS::UnsupportedError, "Creating or editing #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." unless respond_to? :create
87
78
  raise AlreadyExistsError, "This #{self.class::RSRC_OBJECT_KEY} already exists. Use #update to make changes." if @in_jss
88
- JSS::API.post_rsrc( @rest_rsrc, rest_xml) =~ /><id>(\d+)<\/id></
89
-
90
- @id = $1.to_i
79
+ JSS::API.post_rsrc(@rest_rsrc, rest_xml) =~ %r{><id>(\d+)</id><}
80
+ @id = Regexp.last_match(1).to_i
91
81
  @in_jss = true
92
82
  @need_to_update = false
93
- @rest_rsrc = "#{self.class::RSRC_BASE}/id/#{@id}"
94
- return @id
83
+ @rest_rsrc = "#{self.class::RSRC_BASE}/id/#{@id}"
84
+ @id
85
+ end
86
+
87
+ ### make a clone of this API object, with a new name. The class must be creatable
88
+ ###
89
+ ### @param name [String] the name for the new object
90
+ ###
91
+ ### @return [APIObject] An uncreated clone of this APIObject with the given name
92
+ ###
93
+ def clone(new_name)
94
+ raise JSS::UnsupportedError, 'This class is not creatable in via ruby-jss' unless respond_to? :create
95
+ raise JSS::AlreadyExistsError, "A #{self.class::RSRC_OBJECT_KEY} already exists with that name" if \
96
+ self.class.all_names.include? new_name
97
+
98
+ orig_in_jss = @in_jss
99
+ @in_jss = false
100
+ orig_id = @id
101
+ @id = nil
102
+ orig_rsrc = @rest_rsrc
103
+ @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape new_name}"
104
+
105
+ new_obj = dup
106
+
107
+ @in_jss = orig_in_jss
108
+ @id = orig_id
109
+ @rest_rsrc = orig_rsrc
110
+ new_obj.name = new_name
111
+
112
+ new_obj
95
113
  end
96
114
 
97
115
  end # module Creatable
@@ -90,7 +90,10 @@ module JSS
90
90
  ### An empty SHA256 digest
91
91
  EMPTY_PW_256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
92
92
 
93
+ ### Set default local mount for distribution point
94
+ DEFAULT_MOUNTPOINT_DIR = Pathname.new "/tmp"
93
95
 
96
+ DEFAULT_MOUNTPOINT_PREFIX = "CasperDistribution-id"
94
97
 
95
98
  #####################################
96
99
  ### Class Variables
@@ -317,7 +320,7 @@ module JSS
317
320
 
318
321
 
319
322
  ### if we mount for fileservice, where's the mountpoint?
320
- @mountpoint = Pathname.new "/Volumes/CasperDistribution-id-#{@id}"
323
+ @mountpoint = Pathname.new "/#{DEFAULT_MOUNTPOINT_DIR}/#{DEFAULT_MOUNTPOINT_PREFIX}#{@id}"
321
324
 
322
325
  end #init
323
326
 
@@ -167,7 +167,7 @@ module JSS
167
167
 
168
168
  ### the name of the EA might have spaces and caps, which the will come to us as symbols with the spaces
169
169
  ### as underscores, like this.
170
- @symbolized_name = @name.gsub(' ','_').to_sym
170
+ @symbolized_name = @name.gsub(/-| /,'_').to_sym
171
171
 
172
172
  end # init
173
173
 
@@ -25,50 +25,39 @@
25
25
  ###
26
26
  module JSS
27
27
 
28
- #####################################
29
28
  ### Module Constants
30
29
  #####################################
31
30
 
32
- #####################################
33
31
  ### Module Variables
34
32
  #####################################
35
33
 
36
- #####################################
37
34
  ### Module Methods
38
35
  #####################################
39
36
 
40
- #####################################
41
37
  ### Classes
42
38
  #####################################
43
39
 
44
- ###
45
40
  ### A Package in the JSS
46
41
  ###
47
42
  ### Also the API provides no access to the package's
48
43
  ### file list (index), so indexing must be done separately (usually via Casper Admin)
49
44
  ###
50
- ###
51
- ### @see JSS::APIObject
52
- ###
53
- class Package < JSS::APIObject
45
+ class Package < JSS::APIObject
54
46
 
55
- #####################################
56
47
  ### Mix-Ins
57
48
  #####################################
58
49
 
59
50
  include JSS::Creatable
60
51
  include JSS::Updatable
61
52
 
62
- #####################################
63
53
  ### Class Methods
64
54
  #####################################
65
55
 
66
- #####################################
67
56
  ### Class Constants
68
57
  #####################################
69
58
 
70
59
  ### The base for REST resources of this class
71
- RSRC_BASE = "packages"
60
+ RSRC_BASE = 'packages'.freeze
72
61
 
73
62
  ### the hash key used for the JSON list output of all objects in the JSS
74
63
  RSRC_LIST_KEY = :packages
@@ -78,13 +67,13 @@ module JSS
78
67
  RSRC_OBJECT_KEY = :package
79
68
 
80
69
  ### these keys, as well as :id and :name, are present in valid API JSON data for this class
81
- VALID_DATA_KEYS = [:fill_existing_users, :fill_user_template, :reboot_required ]
70
+ VALID_DATA_KEYS = [:fill_existing_users, :fill_user_template, :reboot_required].freeze
82
71
 
83
72
  ### The pkg storage folder on the distribution point
84
- DIST_POINT_PKGS_FOLDER = "Packages"
73
+ DIST_POINT_PKGS_FOLDER = 'Packages'.freeze
85
74
 
86
75
  ### The possible values for cpu_type (required_processor) in a JSS package
87
- CPU_TYPES = ["None", "x86", "ppc"]
76
+ CPU_TYPES = %w(None x86 ppc).freeze
88
77
 
89
78
  ### the possible priorities
90
79
  PRIORITIES = (1..20)
@@ -93,23 +82,20 @@ module JSS
93
82
  DEFAULT_PRIORITY = 10
94
83
 
95
84
  ### by default, no processor requirement
96
- DEFAULT_PROCESSOR = "None"
85
+ DEFAULT_PROCESSOR = 'None'.freeze
97
86
 
98
87
  ### When we shouldn't install anything (e.g. switch w/package)
99
- DO_NOT_INSTALL = "Do Not Install"
88
+ DO_NOT_INSTALL = 'Do Not Install'.freeze
100
89
 
101
90
  ### The table in the database for this object
102
- DB_TABLE = "packages"
91
+ DB_TABLE = 'packages'.freeze
103
92
 
104
- #####################################
105
93
  ### Class Variables
106
94
  #####################################
107
95
 
108
- #####################################
109
96
  ### Class Methods
110
97
  #####################################
111
98
 
112
- #####################################
113
99
  ### Attributes
114
100
  #####################################
115
101
 
@@ -161,19 +147,16 @@ module JSS
161
147
  ### @return [Boolean] does this pkg cause a notification to be sent on self-heal?
162
148
  attr_reader :send_notification
163
149
 
164
-
165
- ###
166
150
  ### @see JSS::APIObject#initialize
167
151
  ###
168
- def initialize (args = {})
169
-
152
+ def initialize(args = {})
170
153
  super
171
154
 
172
155
  ### now we have pkg_data with something in it, so fill out the instance vars
173
156
  @allow_uninstalled = @init_data[:allow_uninstalled]
174
157
  @boot_volume_required = @init_data[:boot_volume_required]
175
158
  @category = JSS::APIObject.get_name(@init_data[:category])
176
- @category = nil if @category.to_s.casecmp("No category assigned") == 0
159
+ @category = nil if @category.to_s.casecmp('No category assigned').zero?
177
160
  @filename = @init_data[:filename] || @init_data[:name]
178
161
  @fill_existing_users = @init_data[:fill_existing_users]
179
162
  @fill_user_template = @init_data[:fill_user_template]
@@ -186,7 +169,7 @@ module JSS
186
169
  @priority = @init_data[:priority] || DEFAULT_PRIORITY
187
170
  @reboot_required = @init_data[:reboot_required]
188
171
  @required_processor = @init_data[:required_processor] || DEFAULT_PROCESSOR
189
- @required_processor = nil if @required_processor.to_s.casecmp('none') == 0
172
+ @required_processor = nil if @required_processor.to_s.casecmp('none').zero?
190
173
  @send_notification = @init_data[:send_notification]
191
174
  @switch_with_package = @init_data[:switch_with_package] || DO_NOT_INSTALL
192
175
 
@@ -194,9 +177,6 @@ module JSS
194
177
  @receipt = @filename ? (JSS::Client::RECEIPTS_FOLDER + @filename.to_s.sub(/.zip$/, '')) : nil
195
178
  end # init
196
179
 
197
-
198
-
199
- ###
200
180
  ### Change the 'allow to be uninstalled' field in the JSS
201
181
  ### NOTE The package must be indexed before this works. Right now, that means
202
182
  ### using CasperAdmin.app
@@ -205,7 +185,7 @@ module JSS
205
185
  ###
206
186
  ### @return [void]
207
187
  ###
208
- def allow_uninstalled= (new_val)
188
+ def allow_uninstalled=(new_val)
209
189
  return nil if new_val == @allow_uninstalled
210
190
 
211
191
  ### removable? defaults to false
@@ -215,13 +195,10 @@ module JSS
215
195
  new_val = false if new_val.to_s.empty?
216
196
  raise JSS::InvalidDataError, "allow_uninstalled must be boolean 'true' or 'false'" unless JSS::TRUE_FALSE.include? new_val
217
197
 
218
- @allow_uninstalled= new_val
198
+ @allow_uninstalled = new_val
219
199
  @need_to_update = true
220
-
221
200
  end
222
201
 
223
-
224
- ###
225
202
  ### Change the boot volume required field in the JSS
226
203
  ###
227
204
  ### @param new_val[Boolean]
@@ -231,20 +208,18 @@ module JSS
231
208
  def boot_volume_required=(new_val)
232
209
  return nil if new_val == @boot_volume_required
233
210
  new_val = false if new_val.to_s.empty?
234
- raise JSS::InvalidDataError, "install_if_reported_available must be boolean true or false" unless JSS::TRUE_FALSE.include? new_val
211
+ raise JSS::InvalidDataError, 'install_if_reported_available must be boolean true or false' unless JSS::TRUE_FALSE.include? new_val
235
212
  @boot_volume_required = new_val
236
213
  @need_to_update = true
237
214
  end
238
215
 
239
-
240
- ###
241
216
  ### Change the category in the JSS
242
217
  ###
243
218
  ### @param new_val[String] must be one listed by 'JSS::Category.all_names'
244
219
  ###
245
220
  ### @return [void]
246
221
  ###
247
- def category= (new_val)
222
+ def category=(new_val)
248
223
  return nil if new_val == @category
249
224
  new_val = nil if new_val == ''
250
225
  new_val ||= JSS::Category::DEFAULT_CATEGORY
@@ -253,7 +228,6 @@ module JSS
253
228
  @need_to_update = true
254
229
  end
255
230
 
256
- ###
257
231
  ### Change the package filename.
258
232
  ### Setting it to nil or empty will make it match the display name
259
233
  ###
@@ -261,24 +235,22 @@ module JSS
261
235
  ###
262
236
  ### @return [void]
263
237
  ###
264
- def filename= (new_val)
238
+ def filename=(new_val)
265
239
  new_val = nil if new_val == ''
266
240
  new_val ||= @name
267
241
  return nil if new_val == @filename
268
- $stderr.puts "WARNING: you must change the filename on the master Distribution Point. See JSS::Package.update_master_filename." if @in_jss
242
+ $stderr.puts 'WARNING: you must change the filename on the master Distribution Point. See JSS::Package.update_master_filename.' if @in_jss
269
243
  @filename = new_val
270
244
  @need_to_update = true
271
245
  end
272
246
 
273
-
274
- ###
275
247
  ### Change the Fill Existing Users value
276
248
  ###
277
249
  ### @param new_val[Boolean]
278
250
  ###
279
251
  ### @return [void]
280
252
  ###
281
- def fill_existing_users= (new_val)
253
+ def fill_existing_users=(new_val)
282
254
  return nil if new_val == @fill_existing_users
283
255
  new_val = false if new_val.to_s.empty?
284
256
  raise JSS::InvalidDataError, "fill_existing_users must be boolean 'true' or 'false'" unless JSS::TRUE_FALSE.include? new_val
@@ -286,14 +258,13 @@ module JSS
286
258
  @need_to_update = true
287
259
  end
288
260
 
289
- ###
290
261
  ### Change the fill_user_template value
291
262
  ###
292
263
  ### @param new_val[Boolean]
293
264
  ###
294
265
  ### @return [void]
295
266
  ###
296
- def fill_user_template= (new_val)
267
+ def fill_user_template=(new_val)
297
268
  return nil if new_val == @fill_user_template
298
269
  new_val = false if new_val.to_s.empty?
299
270
  raise JSS::InvalidDataError, "fill_user_template must be boolean 'true' or 'false'" unless JSS::TRUE_FALSE.include? new_val
@@ -301,57 +272,48 @@ module JSS
301
272
  @need_to_update = true
302
273
  end
303
274
 
304
-
305
-
306
- ###
307
275
  ### Change the info field in the JSS.
308
276
  ###
309
277
  ### @param new_val[String]
310
278
  ###
311
279
  ### @return [void]
312
280
  ###
313
- def info= (new_val)
281
+ def info=(new_val)
314
282
  return nil if new_val == @info
315
283
  ### line breaks should be \r
316
- new_val = new_val.to_s.gsub(/\n/, "\r")
284
+ new_val = new_val.to_s.tr("\n", "\r")
317
285
  @info = new_val
318
286
  @need_to_update = true
319
287
  end
320
288
 
321
-
322
- ###
323
289
  ### Change the if_in_swupdate field in the JSS
324
290
  ###
325
291
  ### @param new_val[Boolean]
326
292
  ###
327
293
  ### @return [void]
328
294
  ###
329
- def install_if_reported_available= (new_val)
295
+ def install_if_reported_available=(new_val)
330
296
  return nil if new_val == @install_if_reported_available
331
297
  new_val = false if new_val.to_s.empty?
332
- raise JSS::InvalidDataError, "install_if_reported_available must be boolean true or false" unless JSS::TRUE_FALSE.include? new_val
298
+ raise JSS::InvalidDataError, 'install_if_reported_available must be boolean true or false' unless JSS::TRUE_FALSE.include? new_val
333
299
  @install_if_reported_available = new_val
334
300
  @need_to_update = true
335
301
  end
336
302
 
337
-
338
-
339
- ###
340
303
  ### Change the notes field in the JSS.NewLines are converted \r.
341
304
  ###
342
305
  ### @param new_val[String]
343
306
  ###
344
307
  ### @return [void]
345
308
  ###
346
- def notes= (new_val)
309
+ def notes=(new_val)
347
310
  return nil if new_val == @notes
348
311
  ### line breaks should be \r
349
- new_val = new_val.to_s.gsub(/\n/, "\r")
312
+ new_val = new_val.to_s.tr("\n", "\r")
350
313
  @notes = new_val
351
314
  @need_to_update = true
352
315
  end
353
316
 
354
- ###
355
317
  ### Change the os_requirements field in the JSS
356
318
  ### E.g. 10.5, 10.5.3, 10.6.x
357
319
  ###
@@ -364,20 +326,20 @@ module JSS
364
326
  ###
365
327
  ### @see JSS.expand_min_os
366
328
  ###
367
- def os_requirements= (new_val)
329
+ def os_requirements=(new_val)
368
330
  ### nil should be an empty array
369
331
  new_val = [] if new_val.to_s.empty?
370
332
 
371
333
  ### if any value starts with >=, expand it
372
334
  case new_val
373
- when String
374
- new_val = JSS.expand_min_os(new_val) if new_val =~ /^>=/
375
- when Array
376
- new_val.map!{|a| a =~ /^>=/ ? JSS.expand_min_os(a) : a }
377
- new_val.flatten!
378
- new_val.uniq!
379
- else
380
- raise JSS::InvalidDataError, "os_requirements must be a String or an Array of strings"
335
+ when String
336
+ new_val = JSS.expand_min_os(new_val) if new_val =~ /^>=/
337
+ when Array
338
+ new_val.map! { |a| a =~ /^>=/ ? JSS.expand_min_os(a) : a }
339
+ new_val.flatten!
340
+ new_val.uniq!
341
+ else
342
+ raise JSS::InvalidDataError, 'os_requirements must be a String or an Array of strings'
381
343
  end
382
344
  ### get the array version
383
345
  @os_requirements = JSS.to_s_and_a(new_val)[:arrayform]
@@ -393,34 +355,31 @@ module JSS
393
355
  ### @return [Boolean] can this pkg be installed with the os
394
356
  ### given?
395
357
  ###
396
- def os_ok? (os = nil)
358
+ def os_ok?(os = nil)
397
359
  JSS.os_ok? @os_requirements, os
398
360
  end
399
361
 
400
-
401
- ###
402
362
  ### Change the priority field in the JSS
403
363
  ###
404
364
  ### @param new_val[Integer] one of PRIORITIES
405
365
  ###
406
366
  ### @return [void]
407
367
  ###
408
- def priority= (new_val)
368
+ def priority=(new_val)
409
369
  return nil if new_val == @priority
410
370
  new_val = DEFAULT_PRIORITY if new_val.to_s.empty?
411
- raise JSS::InvalidDataError, ":priority must be an integer from 1-20" unless PRIORITIES.include? new_val
371
+ raise JSS::InvalidDataError, ':priority must be an integer from 1-20' unless PRIORITIES.include? new_val
412
372
  @priority = new_val
413
373
  @need_to_update = true
414
374
  end
415
375
 
416
- ###
417
376
  ### Change the reboot-required field in the JSS
418
377
  ###
419
378
  ### @param new_val[Boolean]
420
379
  ###
421
380
  ### @return [void]
422
381
  ###
423
- def reboot_required= (new_val)
382
+ def reboot_required=(new_val)
424
383
  return nil if new_val == @reboot_required
425
384
  new_val = false if new_val.to_s.empty?
426
385
  raise JSS::InvalidDataError, "reboot must be boolean 'true' or 'false'" unless JSS::TRUE_FALSE.include? new_val
@@ -428,16 +387,13 @@ module JSS
428
387
  @need_to_update = true
429
388
  end
430
389
 
431
-
432
-
433
- ###
434
390
  ### Change the required processor field in the JSS
435
391
  ###
436
392
  ### @param new_val[String] one of {CPU_TYPES}
437
393
  ###
438
394
  ### @return [void]
439
395
  ###
440
- def required_processor= (new_val)
396
+ def required_processor=(new_val)
441
397
  return nil if new_val == @required_processor
442
398
 
443
399
  new_val = DEFAULT_PROCESSOR if new_val.to_s.empty?
@@ -456,45 +412,41 @@ module JSS
456
412
  ### @return [Boolean] can this pkg be installed with the processor
457
413
  ### given?
458
414
  ###
459
- def processor_ok? (processor = nil)
415
+ def processor_ok?(processor = nil)
460
416
  JSS.processor_ok? @required_processor, processor
461
417
  end
462
418
 
463
-
464
-
465
419
  ### Change the notify field in the JSS
466
420
  ###
467
421
  ### @param new_val[Boolean]
468
422
  ###
469
423
  ### @return [void]
470
424
  ###
471
- def send_notification= (new_val)
425
+ def send_notification=(new_val)
472
426
  return nil if new_val == @send_notification
473
427
  new_val = false if new_val.to_s.empty?
474
- raise JSS::InvalidDataError, "send_notification must be boolean true or false" unless JSS::TRUE_FALSE.include? new_val
428
+ raise JSS::InvalidDataError, 'send_notification must be boolean true or false' unless JSS::TRUE_FALSE.include? new_val
475
429
  @send_notification = new_val
476
430
  @need_to_update = true
477
431
  end
478
432
 
479
-
480
433
  ### Change which pkg should be installed if this one can't.
481
434
  ###
482
435
  ### @param new_val[String] the name of an existing package or "Do Not Install"
483
436
  ###
484
437
  ### @return [void]
485
438
  ###
486
- def switch_with_package= (new_val)
439
+ def switch_with_package=(new_val)
487
440
  return nil if new_val == @switch_with_package
488
441
  new_val = nil if new_val.to_s.empty?
489
442
 
490
- raise JSS::NoSuchItemError, "No package named '#{new_val}' exists in the JSS" if new_val and not self.class.all_names.include? new_val
443
+ raise JSS::NoSuchItemError, "No package named '#{new_val}' exists in the JSS" if new_val && (!self.class.all_names.include? new_val)
491
444
 
492
445
  new_val ||= DO_NOT_INSTALL
493
446
  @switch_with_package = new_val
494
447
  @need_to_update = true
495
448
  end
496
449
 
497
- ###
498
450
  ### Is this packaged installed on the current machine (via casper)?
499
451
  ### We just look for the receipt, which is the @filename less any possible .zip extension.
500
452
  ###
@@ -504,7 +456,6 @@ module JSS
504
456
  @receipt.file?
505
457
  end
506
458
 
507
- ###
508
459
  ### Upload a locally-readable file to the master distribution point.
509
460
  ### If the file is a directory (like a bundle .pk/.mpkg) it will be zipped before
510
461
  ### uploading and the @filename will be adjusted accordingly
@@ -521,12 +472,11 @@ module JSS
521
472
  ###
522
473
  ### @return [void]
523
474
  ###
524
- def upload_master_file (local_file_path, rw_pw, unmount = true)
525
-
526
- raise JSS::NoSuchItemError, "Please create this package in the JSS before uploading it." unless @in_jss
475
+ def upload_master_file(local_file_path, rw_pw, unmount = true)
476
+ raise JSS::NoSuchItemError, 'Please create this package in the JSS before uploading it.' unless @in_jss
527
477
 
528
478
  mdp = JSS::DistributionPoint.master_distribution_point
529
- destination = mdp.mount(rw_pw, :rw) +"#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
479
+ destination = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
530
480
 
531
481
  local_path = Pathname.new local_file_path
532
482
  raise JSS::NoSuchItemError, "Local file '#{@local_file}' doesn't exist" unless local_path.exist?
@@ -534,10 +484,10 @@ module JSS
534
484
  ### should we zip it?
535
485
  if local_path.directory?
536
486
  begin
537
- zipdir = Pathname.new "/tmp/jssgemtmp-#{Time.new.strftime "%Y%m%d%H%M%S"}-#{$$}"
487
+ zipdir = Pathname.new "/tmp/jssgemtmp-#{Time.new.strftime '%Y%m%d%H%M%S'}-#{$PROCESS_ID}"
538
488
  zipdir.mkpath
539
- zipdir.chmod 0700
540
- zipfile = zipdir + (local_path.basename.to_s + ".zip")
489
+ zipdir.chmod 0o700
490
+ zipfile = zipdir + (local_path.basename.to_s + '.zip')
541
491
 
542
492
  ### go to the same dir as the local file
543
493
  wd = Dir.pwd
@@ -546,11 +496,11 @@ module JSS
546
496
  ### the contents of the zip file have to have the same name as the zip file itself (minus the .zip)
547
497
  ### so temporarily rename the source
548
498
  local_path.rename(local_path.parent + @filename)
549
- raise "There was a problem zipping the pkg bundle" unless system "/usr/bin/zip -qr '#{zipfile}' '#{@filename}'"
499
+ raise 'There was a problem zipping the pkg bundle' unless system "/usr/bin/zip -qr '#{zipfile}' '#{@filename}'"
550
500
 
551
501
  ensure
552
502
  ### rename the source to the original name
553
- (local_path.parent + @filename).rename local_path if (local_path.parent + @filename).exist?
503
+ (local_path.parent + @filename).rename local_path if (local_path.parent + @filename).exist?
554
504
  ### go back where we started
555
505
  Dir.chdir wd
556
506
  end # begin
@@ -561,13 +511,12 @@ module JSS
561
511
  self.filename = zipfile.basename.to_s
562
512
 
563
513
  end # if directory
564
- self.update
514
+ update
565
515
  FileUtils.copy_entry local_path, destination
566
516
 
567
517
  mdp.unmount if unmount
568
518
  end # upload
569
519
 
570
-
571
520
  ### Change the name of a package file on the master distribution point.
572
521
  ###
573
522
  ### @param new_file_name[String]
@@ -581,26 +530,23 @@ module JSS
581
530
  ###
582
531
  ### @return [nil]
583
532
  ###
584
- def update_master_filename(old_file_name, new_file_name, rw_pw , unmount = true )
533
+ def update_master_filename(old_file_name, new_file_name, rw_pw, unmount = true)
585
534
  raise JSS::NoSuchItemError, "#{old_file_name} does not exist in the jss." unless @in_jss
586
535
  mdp = JSS::DistributionPoint.master_distribution_point
587
- pkgs_dir = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}"
536
+ pkgs_dir = mdp.mount(rw_pw, :rw) + DIST_POINT_PKGS_FOLDER.to_s
588
537
  old_file = pkgs_dir + old_file_name
538
+ raise JSS::NoSuchItemError, "File not found on the master distribution point at #{DIST_POINT_PKGS_FOLDER}/#{old_file_name}." unless \
539
+ old_file.exist?
540
+
589
541
  new_file = pkgs_dir + new_file_name
590
- if new_file.extname.empty?
591
542
  ### use the extension of the original file.
592
- new_file = pkgs_dir + (new_file_name + old_file.extname)
593
- end
594
- if old_file.exist?
595
- old_file.rename new_file
596
- else
597
- raise JSS::NoSuchItemError, "Original file not found on the master distribution point at #{DIST_POINT_PKGS_FOLDER}/#{old_file_name}."
598
- end # if exist
543
+ new_file = pkgs_dir + (new_file_name + old_file.extname) if new_file.extname.empty?
544
+
545
+ old_file.rename new_file
599
546
  mdp.unmount if unmount
600
- return nil
547
+ nil
601
548
  end # update_master_filename
602
549
 
603
-
604
550
  ### Delete the filename from the master distribution point, if it exists.
605
551
  ###
606
552
  ### If you'll be uploading several files you can specify unmount as false, and do it manually when all
@@ -613,7 +559,7 @@ module JSS
613
559
  ###
614
560
  ### @return [Boolean] was the file deleted?
615
561
  ###
616
- def delete_master_file (rw_pw, unmount = true)
562
+ def delete_master_file(rw_pw, unmount = true)
617
563
  mdp = JSS::DistributionPoint.master_distribution_point
618
564
  file = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_PKGS_FOLDER}/#{@filename}"
619
565
  if file.exist?
@@ -623,10 +569,9 @@ module JSS
623
569
  did_it = false
624
570
  end # if exists
625
571
  mdp.unmount if unmount
626
- return did_it
572
+ did_it
627
573
  end # delete master file
628
574
 
629
-
630
575
  ### Delete this package from the JSS, optionally
631
576
  ### deleting the master dist point file also.
632
577
  ###
@@ -637,9 +582,9 @@ module JSS
637
582
  ###
638
583
  ### @param unmount[Boolean] whether or not ot unount the distribution point when finished.
639
584
  ###
640
- def delete (delete_file: false, rw_pw: nil, unmount: true)
585
+ def delete(delete_file: false, rw_pw: nil, unmount: true)
641
586
  super()
642
- delete_master_file(rw_pw, unmount) if delete_file
587
+ delete_master_file(rw_pw, unmount) if delete_file
643
588
  end
644
589
 
645
590
  ### Install this package via the jamf binary 'install' command from the
@@ -682,9 +627,8 @@ module JSS
682
627
  ###
683
628
  ### @todo deal with cert-based https authentication in dist points
684
629
  ###
685
- def install (args = {})
686
-
687
- raise JSS::UnsupportedError, "You must have root privileges to install packages" unless JSS.superuser?
630
+ def install(args = {})
631
+ raise JSS::UnsupportedError, 'You must have root privileges to install packages' unless JSS.superuser?
688
632
 
689
633
  args[:target] ||= '/'
690
634
 
@@ -698,7 +642,7 @@ module JSS
698
642
  # but
699
643
  # in >=9.72: jamf install -package foo.pkg -path http://mycasper.myorg.edu/CasperShare/Packages/foo.pkg
700
644
  #
701
- append_at_vers = JSS.parse_jss_version("9.72")[:version]
645
+ append_at_vers = JSS.parse_jss_version('9.72')[:version]
702
646
  our_vers = JSS.parse_jss_version(JSS::API.server.raw_version)[:version]
703
647
  no_filename_in_url = (our_vers < append_at_vers)
704
648
 
@@ -713,15 +657,15 @@ module JSS
713
657
  mdp = JSS::DistributionPoint.my_distribution_point
714
658
 
715
659
  ### how do we access our dist. point? with http?
716
- if mdp.http_downloads_enabled and (not args[:no_http])
660
+ if mdp.http_downloads_enabled && !(args[:no_http])
717
661
  using_http = true
718
662
  src_path = mdp.http_url
719
663
  if mdp.username_password_required
720
- raise JSS::MissingDataError, "No password provided for http download" unless ro_pw
721
- raise JSS::InvaldDatatError, "Incorrect password for http access to distribution point." unless mdp.check_pw(:http, ro_pw)
664
+ raise JSS::MissingDataError, 'No password provided for http download' unless ro_pw
665
+ raise JSS::InvaldDatatError, 'Incorrect password for http access to distribution point.' unless mdp.check_pw(:http, ro_pw)
722
666
  # insert the name and pw into the uri
723
667
  # reserved_chars = Regexp.new("[^#{URI::REGEXP::PATTERN::UNRESERVED}]") # we'll escape all the chars that aren't unreserved
724
- src_path = src_path.sub(%r{(https?://)(\S)}, "#{$1}#{CGI.escape mdp.http_username}:#{CGI.escape ro_pw}@#{$2}")
668
+ src_path = src_path.sub(%r{(https?://)(\S)}, "#{Regexp.last_match(1)}#{CGI.escape mdp.http_username}:#{CGI.escape ro_pw}@#{Regexp.last_match(2)}")
725
669
  end
726
670
 
727
671
  # or with filesharing?
@@ -735,12 +679,12 @@ module JSS
735
679
  end # if args[:alt_download_url]
736
680
 
737
681
  if using_http
738
- src_path += "#{@filename}" unless no_filename_in_url
682
+ src_path += @filename.to_s unless no_filename_in_url
739
683
  end
740
684
 
741
685
  ### are we doing "fill existing users" or "fill user template"?
742
- do_feu = args[:feu] ? "-feu" : ""
743
- do_fut = args[:fut] ? "-fut" : ""
686
+ do_feu = args[:feu] ? '-feu' : ''
687
+ do_fut = args[:fut] ? '-fut' : ''
744
688
 
745
689
  ### the install args for jamf
746
690
  command_args = "-package '#{@filename}' -path '#{src_path}' -target '#{args[:target]}' #{do_feu} #{do_fut} -showProgress -verbose"
@@ -749,21 +693,17 @@ module JSS
749
693
  install_out = JSS::Client.run_jamf :install, command_args, args[:verbose]
750
694
 
751
695
  install_out =~ %r{<exitCode>(\d+)</exitCode>}
752
- install_exit = $1 ? $1.to_i : nil
753
- install_exit ||= $?.exitstatus
754
-
696
+ install_exit = Regexp.last_match(1) ? Regexp.last_match(1).to_i : nil
697
+ install_exit ||= $CHILD_STATUS.exitstatus
755
698
 
756
- if (args.include? :unmount)
699
+ if args.include? :unmount
757
700
  mdp.unmount unless using_http
758
701
  end
759
702
 
760
- return install_exit == 0 ? true : false
703
+ install_exit.zero? ? true : false
761
704
  end
762
705
 
763
- ###
764
- ### @note This code must be run as root to uninstall packages
765
- ###
766
- ### Causes the pkg to be uninstalled via the jamf command.
706
+ ### Uninstall this pkg via the jamf command.
767
707
  ###
768
708
  ### @param args[Hash] the arguments for installation
769
709
  ###
@@ -777,28 +717,29 @@ module JSS
777
717
  ###
778
718
  ### @return [Process::Status] the result of the 'jamf uninstall' command
779
719
  ###
780
- def uninstall (args = {})
781
-
782
- raise JSS::UnsupportedError, \
783
- "This package cannot be uninstalled. Please use CasperAdmin to index it and allow uninstalls" unless removable?
784
- raise JSS::UnsupportedError, "You must have root privileges to uninstall packages" unless JSS.superuser?
720
+ ### @note This code must be run as root to uninstall packages
721
+ ###
722
+ def uninstall(args = {})
723
+ unless removable?
724
+ raise JSS::UnsupportedError, \
725
+ 'This package cannot be uninstalled. Please use CasperAdmin to index it and allow uninstalls'
726
+ end
727
+ raise JSS::UnsupportedError, 'You must have root privileges to uninstall packages' unless JSS.superuser?
785
728
  args[:target] ||= '/'
786
729
 
787
730
  ### are we doing "fill existing users" or "fill user template"?
788
- do_feu = args[:feu] ? "-feu" : ""
789
- do_fut = args[:fut] ? "-fut" : ""
731
+ do_feu = args[:feu] ? '-feu' : ''
732
+ do_fut = args[:fut] ? '-fut' : ''
790
733
 
791
734
  ### use jamf binary to uninstall the pkg
792
735
  jamf_opts = "-target '#{args[:target]}' -id '#{@id}' #{do_feu} #{do_fut}"
793
736
 
794
737
  ### run it via a client
795
- uninstall_out = JSS::Client.run_jamf "uninstall", jamf_opts, args[:verbose]
738
+ JSS::Client.run_jamf 'uninstall', jamf_opts, args[:verbose]
796
739
 
797
- return $?
740
+ $CHILD_STATUS
798
741
  end
799
742
 
800
-
801
-
802
743
  ### What type of package is this?
803
744
  ###
804
745
  ### @return [Symbol] :pkg or :dmg or:unknown
@@ -811,42 +752,9 @@ module JSS
811
752
  end
812
753
  end
813
754
 
814
-
815
- ################################
816
- ### Private Instance Methods
755
+ ### Aliases
817
756
  ################################
818
757
 
819
- private
820
-
821
-
822
- ###
823
- ### Return the REST XML for this pkg, with the current values,
824
- ### for saving or updating
825
- ###
826
- def rest_xml
827
- doc = REXML::Document.new APIConnection::XML_HEADER
828
- pkg = doc.add_element "package"
829
- pkg.add_element('allow_uninstalled').text = @allow_uninstalled
830
- pkg.add_element('boot_volume_required').text = @boot_volume_required
831
- pkg.add_element('category').text = @category.to_s.casecmp("No category assigned") == 0 ? "" : @category
832
- pkg.add_element('filename').text = @filename
833
- pkg.add_element('fill_existing_users').text = @fill_existing_users
834
- pkg.add_element('fill_user_template').text = @fill_user_template
835
- pkg.add_element('info').text = @info
836
- pkg.add_element('install_if_reported_available').text = @install_if_reported_available
837
- pkg.add_element('name').text = @name
838
- pkg.add_element('notes').text = @notes
839
- pkg.add_element('os_requirements').text = JSS.to_s_and_a(@os_requirements)[:stringform]
840
- pkg.add_element('priority').text = @priority
841
- pkg.add_element('reboot_required').text = @reboot_required
842
- pkg.add_element('required_processor').text = @required_processor.to_s.empty? ? "None" : @required_processor
843
- pkg.add_element('send_notification').text = @send_notification
844
- pkg.add_element('switch_with_package').text = @switch_with_package
845
- return doc.to_s
846
- end # rest xml
847
-
848
- public
849
-
850
758
  # aliases under their methods seem to confuse the YARD documenter, so I'm putting them all here.
851
759
  alias feu fill_existing_users
852
760
  alias feu? fill_existing_users
@@ -874,9 +782,35 @@ module JSS
874
782
  alias cpu_type= required_processor=
875
783
  alias notify= send_notification=
876
784
 
785
+ ### Private Instance Methods
786
+ ################################
877
787
 
788
+ private
878
789
 
879
-
790
+ ### Return the REST XML for this pkg, with the current values,
791
+ ### for saving or updating
792
+ ###
793
+ def rest_xml
794
+ doc = REXML::Document.new APIConnection::XML_HEADER
795
+ pkg = doc.add_element 'package'
796
+ pkg.add_element('allow_uninstalled').text = @allow_uninstalled
797
+ pkg.add_element('boot_volume_required').text = @boot_volume_required
798
+ pkg.add_element('category').text = @category.to_s.casecmp('No category assigned').zero? ? '' : @category
799
+ pkg.add_element('filename').text = @filename
800
+ pkg.add_element('fill_existing_users').text = @fill_existing_users
801
+ pkg.add_element('fill_user_template').text = @fill_user_template
802
+ pkg.add_element('info').text = @info
803
+ pkg.add_element('install_if_reported_available').text = @install_if_reported_available
804
+ pkg.add_element('name').text = @name
805
+ pkg.add_element('notes').text = @notes
806
+ pkg.add_element('os_requirements').text = JSS.to_s_and_a(@os_requirements)[:stringform]
807
+ pkg.add_element('priority').text = @priority
808
+ pkg.add_element('reboot_required').text = @reboot_required
809
+ pkg.add_element('required_processor').text = @required_processor.to_s.empty? ? 'None' : @required_processor
810
+ pkg.add_element('send_notification').text = @send_notification
811
+ pkg.add_element('switch_with_package').text = @switch_with_package
812
+ doc.to_s
813
+ end # rest xml
880
814
 
881
815
  end # class Package
882
816