ruby-jss 0.6.5 → 0.6.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

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