ruby-jss 0.6.3

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 (73) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGES.md +112 -0
  4. data/LICENSE.txt +174 -0
  5. data/README.md +426 -0
  6. data/THANKS.md +6 -0
  7. data/bin/cgrouper +485 -0
  8. data/bin/subnet-update +400 -0
  9. data/lib/jss-api.rb +2 -0
  10. data/lib/jss.rb +190 -0
  11. data/lib/jss/api_connection.rb +410 -0
  12. data/lib/jss/api_object.rb +616 -0
  13. data/lib/jss/api_object/advanced_search.rb +389 -0
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
  17. data/lib/jss/api_object/building.rb +92 -0
  18. data/lib/jss/api_object/category.rb +147 -0
  19. data/lib/jss/api_object/computer.rb +852 -0
  20. data/lib/jss/api_object/creatable.rb +98 -0
  21. data/lib/jss/api_object/criteriable.rb +189 -0
  22. data/lib/jss/api_object/criteriable/criteria.rb +231 -0
  23. data/lib/jss/api_object/criteriable/criterion.rb +228 -0
  24. data/lib/jss/api_object/department.rb +93 -0
  25. data/lib/jss/api_object/distribution_point.rb +560 -0
  26. data/lib/jss/api_object/extendable.rb +221 -0
  27. data/lib/jss/api_object/extension_attribute.rb +466 -0
  28. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  29. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  30. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  31. data/lib/jss/api_object/group.rb +380 -0
  32. data/lib/jss/api_object/group/computer_group.rb +124 -0
  33. data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
  34. data/lib/jss/api_object/group/user_group.rb +139 -0
  35. data/lib/jss/api_object/ldap_server.rb +535 -0
  36. data/lib/jss/api_object/locatable.rb +286 -0
  37. data/lib/jss/api_object/matchable.rb +97 -0
  38. data/lib/jss/api_object/mobile_device.rb +556 -0
  39. data/lib/jss/api_object/netboot_server.rb +148 -0
  40. data/lib/jss/api_object/network_segment.rb +414 -0
  41. data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
  42. data/lib/jss/api_object/package.rb +839 -0
  43. data/lib/jss/api_object/peripheral.rb +335 -0
  44. data/lib/jss/api_object/peripheral_type.rb +295 -0
  45. data/lib/jss/api_object/policy.rb +898 -0
  46. data/lib/jss/api_object/purchasable.rb +316 -0
  47. data/lib/jss/api_object/removable_macaddr.rb +98 -0
  48. data/lib/jss/api_object/scopable.rb +136 -0
  49. data/lib/jss/api_object/scopable/scope.rb +621 -0
  50. data/lib/jss/api_object/script.rb +631 -0
  51. data/lib/jss/api_object/self_servable.rb +356 -0
  52. data/lib/jss/api_object/site.rb +93 -0
  53. data/lib/jss/api_object/software_update_server.rb +109 -0
  54. data/lib/jss/api_object/updatable.rb +117 -0
  55. data/lib/jss/api_object/uploadable.rb +138 -0
  56. data/lib/jss/api_object/user.rb +272 -0
  57. data/lib/jss/client.rb +504 -0
  58. data/lib/jss/compatibility.rb +66 -0
  59. data/lib/jss/composer.rb +185 -0
  60. data/lib/jss/configuration.rb +306 -0
  61. data/lib/jss/db_connection.rb +298 -0
  62. data/lib/jss/exceptions.rb +95 -0
  63. data/lib/jss/ruby_extensions.rb +35 -0
  64. data/lib/jss/ruby_extensions/filetest.rb +43 -0
  65. data/lib/jss/ruby_extensions/hash.rb +79 -0
  66. data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
  67. data/lib/jss/ruby_extensions/pathname.rb +77 -0
  68. data/lib/jss/ruby_extensions/string.rb +59 -0
  69. data/lib/jss/ruby_extensions/time.rb +63 -0
  70. data/lib/jss/server.rb +108 -0
  71. data/lib/jss/utility.rb +478 -0
  72. data/lib/jss/version.rb +31 -0
  73. metadata +187 -0
@@ -0,0 +1,631 @@
1
+ ### Copyright 2016 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Constants
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Variables
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Module Methods
38
+ #####################################
39
+
40
+ #####################################
41
+ ### Classes
42
+ #####################################
43
+
44
+ ###
45
+ ### A Script in the JSS.
46
+ ###
47
+ ### As of Casper 9.4, the script contents as stored in the database are
48
+ ### accessible via the API
49
+ ###
50
+ ### This class will save the script contents back to the database with
51
+ ### the {#create} or {#update} methods
52
+ ###
53
+ ### If your scripts are stored on the master distribution point instead of
54
+ ### the database, you can use {#upload_master_file} to save it to the server,
55
+ ### and {#delete_master_file} to delete it from the server.
56
+ ###
57
+ ### Use the {#run} method to run the script on the local machine via the 'jamf runScript' command
58
+ ###
59
+ ### @see JSS::APIObject
60
+ ###
61
+ class Script < JSS::APIObject
62
+
63
+ #####################################
64
+ ### Mix-Ins
65
+ #####################################
66
+
67
+ include JSS::Creatable
68
+ include JSS::Updatable
69
+
70
+ #####################################
71
+ ### Class Methods
72
+ #####################################
73
+
74
+ #####################################
75
+ ### Class Constants
76
+ #####################################
77
+
78
+ ### The base for REST resources of this class
79
+ RSRC_BASE = "scripts"
80
+
81
+ ### the hash key used for the JSON list output of all objects in the JSS
82
+ RSRC_LIST_KEY = :scripts
83
+
84
+ ### The hash key used for the JSON object output.
85
+ ### It's also used in various error messages
86
+ RSRC_OBJECT_KEY = :script
87
+
88
+ ### these keys, as well as :id and :name, are present in valid API JSON data for this class
89
+ VALID_DATA_KEYS = [:parameters, :filename, :os_requirements ]
90
+
91
+ ### The script storage folder on the distribution point, if used
92
+ DIST_POINT_SCRIPTS_FOLDER = "Scripts"
93
+
94
+ ### Priority to use for running the script in relation to other actions during imaging
95
+ PRIORITIES = [ 'Before', 'After','At Reboot']
96
+
97
+ ### which is default?
98
+ DEFAULT_PRIORITY = "After"
99
+
100
+ ### The keys used in the @parameters Hash
101
+ PARAMETER_KEYS = [:parameter4, :parameter5, :parameter6,:parameter7, :parameter8, :parameter9, :parameter10, :parameter11]
102
+
103
+ #####################################
104
+ ### Attributes
105
+ #####################################
106
+
107
+ ### @return [String] the file name of the script, if stored in a dist. point
108
+ attr_reader :filename
109
+
110
+ ### @return [Array<String>] the OS versions this can be installed onto. For all minor versions, the format is 10.5.x
111
+ attr_reader :os_requirements
112
+
113
+ ### @return [String] either 'Before' or 'After' or "At Reboot".
114
+ attr_reader :priority
115
+
116
+ ### @return [String] the info field for this script
117
+ attr_reader :info
118
+
119
+ ### @return [String] the notes field for this script
120
+ attr_reader :notes
121
+
122
+ ### @return [String] the category of this script, stored in the JSS as the id number from the categories table
123
+ attr_reader :category
124
+
125
+ ### @return [Hash] script parameters 4-11. Parameters 1-3 are predefined as target drive, computer name, and username
126
+ attr_reader :parameters
127
+
128
+ ### @return {String] the actual code for this script, if it's stored in the database.
129
+ attr_reader :script_contents
130
+
131
+
132
+ #####################################
133
+ ### Constructor
134
+ #####################################
135
+
136
+ ###
137
+ ###
138
+ ###
139
+ def initialize (args = {})
140
+ super
141
+
142
+ @category = JSS::APIObject.get_name(@init_data[:category])
143
+ @filename = @init_data[:filename] || @name
144
+ @info = @init_data[:info]
145
+ @notes = @init_data[:notes]
146
+ @os_requirements = @init_data[:os_requirements] ? JSS.to_s_and_a(@init_data[:os_requirements] )[:arrayform] : []
147
+ @parameters = @init_data[:parameters] ? @init_data[:parameters] : {}
148
+ @priority = @init_data[:priority] || DEFAULT_PRIORITY
149
+ @script_contents = @init_data[:script_contents]
150
+
151
+ end # initialize
152
+
153
+ ###
154
+ ### Change the script filename
155
+ ###
156
+ ### Setting it to nil will make it match the script name
157
+ ###
158
+ ### @param new_val[String,Nil] the new filename
159
+ ###
160
+ ### @return [void]
161
+ ###
162
+ ### @note This method does NOT change the filename on the distribution point
163
+ ### if that's where you store your scripts.
164
+ ###
165
+ def filename= (new_val)
166
+
167
+ new_val = nil if new_val == ''
168
+ new_val = @name unless new_val
169
+
170
+ return nil if new_val == @filename
171
+
172
+ @filename = new_val
173
+ @need_to_update = true
174
+ end #filename=
175
+
176
+ ###
177
+ ### Change the script's display name
178
+ ###
179
+ ### If the filename is the same as the name, the filename will be changed also
180
+ ###
181
+ ### @param new_val[String] the new display name
182
+ ###
183
+ ### @return [void]
184
+ ###
185
+ def name= (new_val)
186
+ return nil if new_val == @name
187
+ new_val = nil if new_val == ''
188
+ raise JSS::MissingDataError, "Name can't be empty" unless new_val
189
+ raise JSS::AlreadyExistsError, "A #{RSRC_OBJECT_KEY} already exists with the name '#{args[:name]}'" if JSS.send(LIST_METHOD).values.include?
190
+
191
+ ### if the filename is the same, keep it the same
192
+ @filename = new_val if @filename == @name
193
+ @name = new_val
194
+
195
+ ### if our REST resource is based on the name, update that too
196
+ @rest_rsrc = "#{RSRC_BASE}/name/#{URI.escape @name}" if @rest_rsrc.include? '/name/'
197
+ @need_to_update = true
198
+ end #name=
199
+
200
+ ###
201
+ ### Change the os_requirements
202
+ ###
203
+ ### Minumum OS's can be specified as a string using the notation ">=10.6.7"
204
+ ### See the {JSS.expand_min_os} method for details.
205
+ ###
206
+ ### @param new_val[String, Array<String>] the new os requirements as a comma-separted String or an Array of Strings
207
+ ###
208
+ ### @return [void]
209
+ ###
210
+ ### @example String value
211
+ ### myscript.os_requirements "10.5, 10.5.3, 10.6.x"
212
+ ###
213
+ ### @example Array value
214
+ ### ok_oses = ['10.5', '10.5.3', '10.6.x']
215
+ ### myscript.os_requirements ok_oses
216
+ ###
217
+ ### @example Minimum OS
218
+ ### myscript.os_requirements ">=10.7.5"
219
+ ###
220
+ def os_requirements= (new_val)
221
+ ### nil should be an empty array
222
+ new_val = [] if new_val.to_s.empty?
223
+
224
+ ### if any value starts with >=, expand it
225
+ case new_val
226
+ when String
227
+ new_val = JSS.expand_min_os(new_val) if new_val =~ /^>=/
228
+ when Array
229
+ new_val.map!{|a| a =~ /^>=/ ? JSS.expand_min_os(a) : a }
230
+ new_val.flatten!
231
+ new_val.uniq!
232
+ else
233
+ raise JSS::InvalidDataError, "os_requirements must be a String or an Array of strings"
234
+ end # case
235
+
236
+ ### get the array version
237
+ @os_requirements = JSS.to_s_and_a(new_val)[:arrayform]
238
+ @need_to_update = true
239
+
240
+ end #os_requirements=
241
+
242
+ ###
243
+ ### Change the priority of this script
244
+ ###
245
+ ### @param new_val[Integer] the new priority, which must be one of {PRIORITIES}
246
+ ###
247
+ ### @return [void]
248
+ ###
249
+ def priority= (new_val)
250
+ return nil if new_val == @priority
251
+ new_val = DEFAULT_PRIORITY if new_val.nil? or new_val == ""
252
+ raise JSS::InvalidDataError, ":priority must be one of: #{PRIORITIES.join ', '}" unless PRIORITIES.include? new_val
253
+ @priority = new_val
254
+ @need_to_update = true
255
+ end #priority=
256
+
257
+ ###
258
+ ### Change the info field
259
+ ###
260
+ ### @param new_val[String] the new info
261
+ ###
262
+ ### @return [void]
263
+ ###
264
+ def info= (new_val)
265
+ return nil if new_val == @info
266
+ ### line breaks should be \r
267
+ new_val = new_val.to_s.gsub(/\n/, "\r")
268
+ @info = new_val
269
+ @need_to_update = true
270
+ end #info=
271
+
272
+ ###
273
+ ### Change the notes field
274
+ ###
275
+ ### @param new_val[String] the new notes
276
+ ###
277
+ ### @return [void]
278
+ ###
279
+ def notes= (new_val)
280
+ return nil if new_val == @notes
281
+ ### line breaks should be \r
282
+ new_val = new_val.to_s.gsub(/\n/, "\r")
283
+ @notes = new_val
284
+ @need_to_update = true
285
+ end #notes=
286
+
287
+ ###
288
+ ### Change the category
289
+ ###
290
+ ### @param new_val[String] the name of the new category, which must be in {JSS::Category.all_names}
291
+ ###
292
+ ### @return [void]
293
+ ###
294
+ def category= (new_val)
295
+ return nil if new_val == @category
296
+ new_val = nil if new_val == ''
297
+ new_val ||= JSS::Category::DEFAULT_CATEGORY
298
+ raise JSS::InvalidDataError, "Category #{new_val} is not known to the JSS" unless JSS::Category.all_names.include? new_val
299
+ @need_to_update = true
300
+ @category = new_val
301
+ end #category=
302
+
303
+ ###
304
+ ### Replace all the script parameters at once.
305
+ ###
306
+ ### This will replace the entire set with the hash provided.
307
+ ###
308
+ ### @param new_val[Hash] the Hash keys must exist in {PARAMETER_KEYS}
309
+ ###
310
+ ### @return [void]
311
+ ###
312
+ def parameters= (new_val)
313
+ return nil if new_val == @parameters
314
+ new_val = {} if new_val.nil? or new_val== ''
315
+
316
+ ### check the values
317
+ raise JSS::InvalidDataError, ":parameters must be a Hash with keys :parameter4 thru :parameter11" unless new_val.kind_of? Hash and (new_val.keys & PARAMETER_KEYS) == new_val.keys
318
+ new_val.each do |k,v|
319
+ raise JSS::InvalidDataError, ":parameter values must be strings or nil" unless v.nil? or v.kind_of? String
320
+ end
321
+
322
+ @parameters = new_val
323
+ @need_to_update = true
324
+ end # parameters=
325
+
326
+ ###
327
+ ### Change one of the stored parameters
328
+ ###
329
+ ### @param param_num[Integer] which param are we setting? must be 4..11
330
+ ###
331
+ ### @param new_val[String] the new value for the parameter
332
+ ###
333
+ ### @return [void]
334
+ ###
335
+ def set_parameter (param_num, new_val)
336
+ raise JSS::NoSuchItemError, "Parameter numbers must be from 4-11" unless (4..11).include? param_num
337
+ pkey = "parameter#{param_num}".to_sym
338
+ raise JSS::InvalidDataError, "parameter values must be strings or nil" unless new_val.nil? or new_val.kind_of? String
339
+ return nil if new_val == @parameters[pkey]
340
+ @parameters[pkey] = new_val
341
+ @need_to_update = true
342
+ end
343
+
344
+ ###
345
+ ### Change the executable code of this script.
346
+ ###
347
+ ### If the arg is a Pathname instance, or a String starting with "/"
348
+ ### Then the arg is assumed to be a file from which to read the code.
349
+ ###
350
+ ### Otherwise it should be a String with the code itself, and it must start with '#!"
351
+ ###
352
+ ### After doing this, use {#create} or {#update} to write it to the database or
353
+ ### use {#upload_master_file} to save it to the master dist. point.
354
+ ###
355
+ ### @param new_val[String,Pathname] the new script contents or a path to a file containing it.
356
+ ###
357
+ ### @return [void]
358
+ ###
359
+ def script_contents= (new_val)
360
+
361
+ new_code = case new_val
362
+ when String
363
+ if new_val.start_with? '/'
364
+ Pathname.new(new_val).read
365
+ else
366
+ new_val
367
+ end #if
368
+ when Pathname
369
+ new_val.read
370
+ else
371
+ raise JSS::InvalidDataError, "New code must be a String (path or code) or Pathname instance"
372
+ end # case
373
+
374
+ raise JSS::InvalidDataError, "Script contents must start with '#!'" unless new_code.start_with? '#!'
375
+
376
+ @script_contents = new_code
377
+ @need_to_update = true
378
+ end
379
+
380
+ ###
381
+ ### Save the @script_contents for this script to a file on the Master Distribution point.
382
+ ###
383
+ ### If you'll be uploading several files you can specify unmount as false, and do it manually when all
384
+ ### are finished.
385
+ ###
386
+ ### use {#script_contents=} to set the script_contents from a String or Pathname
387
+ ###
388
+ ### @param rw_pw[String] the password for the read/write account on the master Distribution Point
389
+ ###
390
+ ### @param unmount[Boolean] whether or not ot unount the distribution point when finished.
391
+ ###
392
+ ### @return [void]
393
+ ###
394
+ def upload_master_file( rw_pw, unmount = true)
395
+ raise JSS::MissingDataError, "No code specified. Use #code= first." if @script_contents.nil? or @script_contents.empty?
396
+
397
+ mdp = JSS::DistributionPoint.master_distribution_point
398
+ raise JSS::InvaldDatatError, "Incorrect password for read-write access to master distribution point." unless mdp.check_pw :rw, rw_pw
399
+
400
+ destination = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_SCRIPTS_FOLDER}/#{@filename}"
401
+ destination.save @script_contents
402
+ mdp.unmount if unmount
403
+ end # upload
404
+
405
+ ###
406
+ ### Delete the filename from the master distribution point, if it exists.
407
+ ###
408
+ ### If you'll be uploading several files you can specify unmount as false, and do it manually when all
409
+ ### are finished.
410
+ ###
411
+ ### @param rw_pw[String] the password for the read/write account on the master Distribution Point
412
+ ###
413
+ ### @param unmount[Boolean] whether or not ot unount the distribution point when finished.
414
+ ###
415
+ ### @return [Boolean] was the file deleted?
416
+ ###
417
+ def delete_master_file(rw_pw, unmount = true)
418
+ file = JSS::DistributionPoint.master_distribution_point.mount(rw_pw, :rw) + "#{DIST_POINT_SCRIPTS_FOLDER}/#{@filename}"
419
+ if file.exist?
420
+ file.delete
421
+ did_it = true
422
+ else
423
+ did_it = false
424
+ end # if exists
425
+ JSS::DistributionPoint.master_distribution_point.unmount if unmount
426
+ return did_it
427
+ end
428
+
429
+
430
+ ###
431
+ ### Run this script on the current machine using the "jamf runScript" command.
432
+ ###
433
+ ### If the script code is available in the {#script_contents} attribute, then that
434
+ ### code is saved to a tmp file, and executed. Otherwise, the script is assumed
435
+ ### to be stored on the distribution point.
436
+ ###
437
+ ### If the dist. point has http downloads enabled, then the URL is used as the path with the
438
+ ### 'jamf runScript' command.
439
+ ###
440
+ ### If http is not an option, the dist.point is mounted, and the script copied locally before running.
441
+ ### In this case the options must include :ro_pw => 'somepass'
442
+ ### to provide the read-only password for mounting the distribution point. If :unmount => true
443
+ ### is provided, the dist. point will be unmounted immediately after copying
444
+ ### the script locally. Otherwise it will remain mounted, in case there's further need of it.
445
+ ###
446
+ ### Any local on-disk copies of the script are removed after running.
447
+ ###
448
+ ### After the script runs, this method returns a two-item Array.
449
+ ### - the first item is an Integer, the exit status of the script itself (0 means success)
450
+ ### - the second item is a String, the output (stdout + stderr) of the jamf binary, which will include
451
+ ### the script output.
452
+ ### The exit status of the jamf binary process will be available as a Process::Status object
453
+ ### in $? immediately after running.
454
+ ###
455
+ ### @param opts[Hash] the options for running the script
456
+ ###
457
+ ### @option opts :target[String,Pathname] the 'target drive', passed to the script as the first commandline option.
458
+ ### Defaults to '/'
459
+ ###
460
+ ### @option opts :computer_name[String] the name of the computer, passed to the script as the second commandline
461
+ ### option. Defaults to the name of the current machine
462
+ ###
463
+ ### @option opts :username[String] the username to be passed to the script as the third commandline option.
464
+ ###
465
+ ### @option opts :p1..:p8[String] the values to be passed as the 4th - 11th commandline options, overriding
466
+ ### those defined with the script in the JSS
467
+ ###
468
+ ### @option opts :ro_pw[String] the read-only password for mounting the distribution point, if needed
469
+ ###
470
+ ### @option opts :unmount[Boolean} should the dist. point be unmounted when finished, if we mounted it?
471
+ ###
472
+ ### @option opts :verbose[Boolean] should the 'jamf runScript' command be verbose?
473
+ ###
474
+ ### @option opts :show_output[Boolean] should the output (stdout + stderr) of 'jamf runScript' be copied to
475
+ ### stdout in realtime, as well as returned?
476
+ ###
477
+ ### @return [Array<(Integer,String)>] the exit status of the *script* and stdout+stderr of 'jamf runScript'.
478
+ ### The exit status of the jamf binary will be available in $? immediately after running.
479
+ ###
480
+ ### *NOTE* In the WEB UI and API, the definable parameters are numbered 4-11, since 1, 2, & 3 are the
481
+ ### target drive, computer name, and user name respectively. However, the jamf binary refers to them as
482
+ ### p1-p8, and that's how they are expected as options to #run. So if :p1=> "new param" is given as an
483
+ ### aption to #run, it will override any value that the API provided in @parameters[:parameter4]
484
+ ###
485
+ def run( opts = {} )
486
+
487
+ opts[:target] ||= "/"
488
+ opts[:p1] ||= @parameters[:parameter4]
489
+ opts[:p2] ||= @parameters[:parameter5]
490
+ opts[:p3] ||= @parameters[:parameter6]
491
+ opts[:p4] ||= @parameters[:parameter7]
492
+ opts[:p5] ||= @parameters[:parameter8]
493
+ opts[:p6] ||= @parameters[:parameter9]
494
+ opts[:p7] ||= @parameters[:parameter10]
495
+ opts[:p8] ||= @parameters[:parameter11]
496
+
497
+ dp_mount_pt = nil
498
+ delete_exec = false
499
+
500
+ begin
501
+
502
+ # do we have the code already? if so, save it out and make it executable
503
+ if @script_contents and (not @script_contents.empty?)
504
+
505
+ script_path = JSS::Client::DOWNLOADS_FOLDER
506
+
507
+ executable = script_path + @filename
508
+
509
+ executable.jss_touch
510
+ executable.chmod 0700
511
+ executable.jss_save @script_contents
512
+ delete_exec = true
513
+
514
+ # otherwise, get it from the dist. point
515
+ else
516
+ dist_point = JSS::DistributionPoint.my_distribution_point
517
+
518
+ ### how do we access our dist. point?
519
+ if dist_point.http_downloads_enabled
520
+ script_path = dist_point.http_url + "/#{DIST_POINT_SCRIPTS_FOLDER}/"
521
+
522
+ else
523
+ dp_mount_pt = dist_point.mount opts[:ro_pw]
524
+
525
+ script_path = (dp_mount_pt + DIST_POINT_SCRIPTS_FOLDER)
526
+
527
+ end # if http enabled
528
+
529
+ end # if @script_contents and (not @script_contents.empty?)
530
+
531
+
532
+ # build the command as an array.
533
+ command_arry = ["-script", @filename, '-path', script_path.to_s]
534
+
535
+ command_arry << "-target"
536
+ command_arry << opts[:target].to_s
537
+
538
+ command_arry << "-computerName" if opts[:computer_name]
539
+ command_arry << opts[:computer_name] if opts[:computer_name]
540
+
541
+ command_arry << "-username" if opts[:username]
542
+ command_arry << opts[:username] if opts[:username]
543
+
544
+ command_arry << "-p1" if opts[:p1]
545
+ command_arry << opts[:p1] if opts[:p1]
546
+
547
+ command_arry << "-p2" if opts[:p2]
548
+ command_arry << opts[:p2] if opts[:p2]
549
+
550
+ command_arry << "-p3" if opts[:p3]
551
+ command_arry << opts[:p3] if opts[:p3]
552
+
553
+ command_arry << "-p4" if opts[:p4]
554
+ command_arry << opts[:p4] if opts[:p4]
555
+
556
+ command_arry << "-p5" if opts[:p5]
557
+ command_arry << opts[:p5] if opts[:p5]
558
+
559
+ command_arry << "-p6" if opts[:p6]
560
+ command_arry << opts[:p6] if opts[:p6]
561
+
562
+ command_arry << "-p7" if opts[:p7]
563
+ command_arry << opts[:p7] if opts[:p7]
564
+
565
+ command_arry << "-p8" if opts[:p8]
566
+ command_arry << opts[:p8] if opts[:p8]
567
+
568
+ command_arry << "-verbose" if opts[:verbose]
569
+
570
+ command = command_arry.shelljoin
571
+
572
+ jamf_output = JSS::Client.run_jamf "runScript", command, opts[:show_output]
573
+
574
+ jamf_output =~ /^.*Script exit code: (\d+)(\D|$)/
575
+
576
+ script_exitstatus = $1.to_i
577
+
578
+ ensure
579
+ executable.delete if delete_exec and executable.exist?
580
+ dist_point.unmount if (dp_mount_pt and dp_mount_pt.mountpoint? and opts[:unmount])
581
+ end # begin/ensure
582
+
583
+ return [script_exitstatus, jamf_output]
584
+
585
+ end # def run
586
+
587
+
588
+ # aliases under their methods seem to confuse the YARD documenter, so I'm putting them all here.
589
+ alias oses os_requirements
590
+ alias oses= os_requirements=
591
+ alias code script_contents
592
+ alias code= script_contents=
593
+ alias contents script_contents
594
+ alias contents= script_contents=
595
+
596
+
597
+ #####################################
598
+ ### Private Instance Methods
599
+ #####################################
600
+
601
+ private
602
+
603
+ ###
604
+ ### Return the xml for creating or updating this script in the JSS
605
+ ###
606
+ def rest_xml
607
+ doc = REXML::Document.new
608
+ scpt = doc.add_element "script"
609
+ scpt.add_element('category').text = @category
610
+ scpt.add_element('filename').text = @filename
611
+ scpt.add_element('id').text = @id
612
+ scpt.add_element('info').text = @info
613
+ scpt.add_element('name').text = @name
614
+ scpt.add_element('notes').text = @notes
615
+ scpt.add_element('os_requirements').text = JSS.to_s_and_a(@os_requirements)[:stringform]
616
+ scpt.add_element('priority').text = @priority
617
+
618
+ if @parameters.empty?
619
+ scpt.add_element('parameters').text = nil
620
+ else
621
+ pars = scpt.add_element('parameters')
622
+ PARAMETER_KEYS.each {|p| pars.add_element(p.to_s).text = @parameters[p]}
623
+ end
624
+
625
+ scpt.add_element('script_contents_encoded').text = Base64.encode64(@script_contents)
626
+
627
+ return doc.to_s
628
+ end # rest xml
629
+
630
+ end # class Script
631
+ end # midule