Class: JSS::Script
- Includes:
- Categorizable, Creatable, Updatable
- Defined in:
- lib/jss/api_object/script.rb,
lib/jss.rb
Overview
A Script in the JSS.
As of Casper 9.4, the script contents as stored in the database are accessible via the API
This class will save the script contents back to the database with the Creatable#create or Updatable#update methods
If your scripts are stored on the master distribution point instead of the database, you can use #upload_master_file to save it to the server, and #delete_master_file to delete it from the server.
Use the #run method to run the script on the local machine via the ‘jamf runScript’ command
Constant Summary collapse
- RSRC_BASE =
The base for REST resources of this class
'scripts'.freeze
- RSRC_LIST_KEY =
the hash key used for the JSON list output of all objects in the JSS
:scripts
- RSRC_OBJECT_KEY =
The hash key used for the JSON object output. It’s also used in various error messages
:script
- VALID_DATA_KEYS =
these keys, as well as :id and :name, are present in valid API JSON data for this class
[:parameters, :filename, :os_requirements].freeze
- DIST_POINT_SCRIPTS_FOLDER =
The script storage folder on the distribution point, if used
'Scripts'.freeze
- PRIORITIES =
Priority to use for running the script in relation to other actions during imaging
['Before', 'After', 'At Reboot'].freeze
- DEFAULT_PRIORITY =
which is default?
'After'.freeze
- PARAMETER_KEYS =
The keys used in the @parameters Hash
[:parameter4, :parameter5, :parameter6, :parameter7, :parameter8, :parameter9, :parameter10, :parameter11].freeze
- OBJECT_HISTORY_OBJECT_TYPE =
the object type for this object in the object history table. See APIObject#add_object_history_entry
91
Instance Attribute Summary collapse
-
#category ⇒ String
readonly
The category of this script, stored in the JSS as the id number from the categories table.
-
#filename ⇒ String
The file name of the script, if stored in a dist.
-
#info ⇒ String
The info field for this script.
-
#need_to_update ⇒ Boolean
included
from Updatable
readonly
Do we have unsaved changes?.
-
#notes ⇒ String
The notes field for this script.
-
#os_requirements ⇒ Array<String>
(also: #oses)
The OS versions this can be installed onto.
-
#parameters ⇒ Hash
Script parameters 4-11.
-
#priority ⇒ String
Either ‘Before’ or ‘After’ or “At Reboot”.
-
#script_contents ⇒ String
(also: #code, #contents)
The actual code for this script, if it’s stored in the database.
Instance Method Summary collapse
-
#category=(new_cat) ⇒ void
included
from Categorizable
Change the category of this object.
-
#category_assigned? ⇒ Boolean
(also: #categorized?)
included
from Categorizable
Does this object have a category assigned?.
-
#category_id ⇒ Integer
included
from Categorizable
The id of the category for this object.
-
#category_name ⇒ String
(also: #category)
included
from Categorizable
The name of the category for this object.
-
#category_object ⇒ JSS::Category
included
from Categorizable
The JSS::Category instance for this object’s category.
-
#clone(new_name, api: nil) ⇒ APIObject
included
from Creatable
make a clone of this API object, with a new name.
-
#create(api: nil) ⇒ Integer
included
from Creatable
Create a new object in the JSS.
-
#delete_master_file(rw_pw, unmount = true) ⇒ Boolean
Delete the filename from the master distribution point, if it exists.
-
#evaluate_new_category(new_cat) ⇒ Array<String, Integer>
included
from Categorizable
Given a category name or id, return the name and id TODO: use APIObject.exist? and/or APIObject.valid_id.
-
#initialize(args = {}) ⇒ Script
constructor
A new instance of Script.
-
#name=(new_val) ⇒ void
Change the script’s display name.
-
#run(opts = {}) ⇒ Array<(Integer,String)>
Run this script on the current machine using the “jamf runScript” command.
-
#set_parameter(param_num, new_val) ⇒ void
Change one of the stored parameters.
-
#unset_category ⇒ void
included
from Categorizable
Set the category to nothing.
-
#update ⇒ Boolean
included
from Updatable
Save changes to the JSS.
-
#upload_master_file(rw_pw, unmount = true) ⇒ void
Save the @script_contents for this script to a file on the Master Distribution point.
Constructor Details
#initialize(args = {}) ⇒ Script
Returns a new instance of Script.
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/jss/api_object/script.rb', line 133 def initialize(args = {}) super @filename = @init_data[:filename] || @name @info = @init_data[:info] @notes = @init_data[:notes] @os_requirements = @init_data[:os_requirements] ? JSS.to_s_and_a(@init_data[:os_requirements])[:arrayform] : [] @parameters = @init_data[:parameters] ? @init_data[:parameters] : {} @priority = @init_data[:priority] || DEFAULT_PRIORITY @script_contents = @init_data[:script_contents] end |
Instance Attribute Details
#category ⇒ String (readonly)
Returns the category of this script, stored in the JSS as the id number from the categories table.
121 122 123 |
# File 'lib/jss/api_object/script.rb', line 121 def category @category end |
#filename ⇒ String
Returns the file name of the script, if stored in a dist. point.
106 107 108 |
# File 'lib/jss/api_object/script.rb', line 106 def filename @filename end |
#info ⇒ String
Returns the info field for this script.
115 116 117 |
# File 'lib/jss/api_object/script.rb', line 115 def info @info end |
#need_to_update ⇒ Boolean (readonly) Originally defined in module Updatable
Returns do we have unsaved changes?.
#notes ⇒ String
Returns the notes field for this script.
118 119 120 |
# File 'lib/jss/api_object/script.rb', line 118 def notes @notes end |
#os_requirements ⇒ Array<String> Also known as: oses
Returns the OS versions this can be installed onto. For all minor versions, the format is 10.5.x.
109 110 111 |
# File 'lib/jss/api_object/script.rb', line 109 def os_requirements @os_requirements end |
#parameters ⇒ Hash
Returns script parameters 4-11. Parameters 1-3 are predefined as target drive, computer name, and username.
124 125 126 |
# File 'lib/jss/api_object/script.rb', line 124 def parameters @parameters end |
#priority ⇒ String
Returns either ‘Before’ or ‘After’ or “At Reboot”.
112 113 114 |
# File 'lib/jss/api_object/script.rb', line 112 def priority @priority end |
#script_contents ⇒ String Also known as: code, contents
Returns the actual code for this script, if it’s stored in the database.
127 128 129 |
# File 'lib/jss/api_object/script.rb', line 127 def script_contents @script_contents end |
Instance Method Details
#category=(new_cat) ⇒ void Originally defined in module Categorizable
This method returns an undefined value.
Change the category of this object. Any of the NON_CATEGORIES values will unset the category
#category_assigned? ⇒ Boolean Also known as: categorized? Originally defined in module Categorizable
Does this object have a category assigned?
#category_id ⇒ Integer Originally defined in module Categorizable
The id of the category for this object.
#category_name ⇒ String Also known as: category Originally defined in module Categorizable
The name of the category for this object. For backward compatibility, this is aliased to just ‘category’
#category_object ⇒ JSS::Category Originally defined in module Categorizable
The JSS::Category instance for this object’s category
#clone(new_name, api: nil) ⇒ APIObject Originally defined in module Creatable
make a clone of this API object, with a new name. The class must be creatable
#create(api: nil) ⇒ Integer Originally defined in module Creatable
Create a new object in the JSS.
#delete_master_file(rw_pw, unmount = true) ⇒ Boolean
Delete the filename from the master distribution point, if it exists.
If you’ll be uploading several files you can specify unmount as false, and do it manually when all are finished.
380 381 382 383 384 385 386 387 388 389 390 |
# File 'lib/jss/api_object/script.rb', line 380 def delete_master_file(rw_pw, unmount = true) file = JSS::DistributionPoint.master_distribution_point.mount(rw_pw, :rw) + "#{DIST_POINT_SCRIPTS_FOLDER}/#{@filename}" if file.exist? file.delete did_it = true else did_it = false end # if exists JSS::DistributionPoint.master_distribution_point.unmount if unmount did_it end |
#evaluate_new_category(new_cat) ⇒ Array<String, Integer> Originally defined in module Categorizable
Given a category name or id, return the name and id TODO: use APIObject.exist? and/or APIObject.valid_id
#name=(new_val) ⇒ void
This method returns an undefined value.
Change the script’s display name
If the filename is the same as the name, the filename will be changed also
174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/jss/api_object/script.rb', line 174 def name=(new_val) return nil if new_val == @name new_val = nil if new_val == '' raise JSS::MissingDataError, "Name can't be empty" unless new_val raise JSS::AlreadyExistsError, "A #{RSRC_OBJECT_KEY} already exists with the name '#{args[:name]}'" if JSS.send(LIST_METHOD).values.include? ### if the filename is the same, keep it the same @filename = new_val if @filename == @name @name = new_val ### if our REST resource is based on the name, update that too @rest_rsrc = "#{RSRC_BASE}/name/#{CGI.escape @name}" if @rest_rsrc.include? '/name/' @need_to_update = true end |
#run(opts = {}) ⇒ Array<(Integer,String)>
Run this script on the current machine using the “jamf runScript” command.
If the script code is available in the #script_contents attribute, then that code is saved to a tmp file, and executed. Otherwise, the script is assumed to be stored on the distribution point.
If the dist. point has http downloads enabled, then the URL is used as the path with the ‘jamf runScript’ command.
If http is not an option, the dist.point is mounted, and the script copied locally before running. In this case the options must include :ro_pw => ‘somepass’ to provide the read-only password for mounting the distribution point. If :unmount => true is provided, the dist. point will be unmounted immediately after copying the script locally. Otherwise it will remain mounted, in case there’s further need of it.
Any local on-disk copies of the script are removed after running.
After the script runs, this method returns a two-item Array.
-
the first item is an Integer, the exit status of the script itself (0 means success)
-
the second item is a String, the output (stdout + stderr) of the jamf binary, which will include the script output.
The exit status of the jamf binary process will be available as a Process::Status object in $? immediately after running.
NOTE In the WEB UI and API, the definable parameters are numbered 4-11, since 1, 2, & 3 are the target drive, computer name, and user name respectively. However, the jamf binary refers to them as p1-p8, and that’s how they are expected as options to #run. So if :p1=> “new param” is given as an aption to #run, it will override any value that the API provided in @parameters
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 |
# File 'lib/jss/api_object/script.rb', line 446 def run(opts = {}) opts[:target] ||= '/' opts[:p1] ||= @parameters[:parameter4] opts[:p2] ||= @parameters[:parameter5] opts[:p3] ||= @parameters[:parameter6] opts[:p4] ||= @parameters[:parameter7] opts[:p5] ||= @parameters[:parameter8] opts[:p6] ||= @parameters[:parameter9] opts[:p7] ||= @parameters[:parameter10] opts[:p8] ||= @parameters[:parameter11] dp_mount_pt = nil delete_exec = false begin # do we have the code already? if so, save it out and make it executable if @script_contents && !@script_contents.empty? script_path = JSS::Client::DOWNLOADS_FOLDER executable = script_path + @filename executable.jss_touch executable.chmod 0o700 executable.jss_save @script_contents delete_exec = true # otherwise, get it from the dist. point else dist_point = JSS::DistributionPoint.my_distribution_point api: @api ### how do we access our dist. point? if dist_point.http_downloads_enabled script_path = dist_point.http_url + "/#{DIST_POINT_SCRIPTS_FOLDER}/" else dp_mount_pt = dist_point.mount opts[:ro_pw] script_path = (dp_mount_pt + DIST_POINT_SCRIPTS_FOLDER) end # if http enabled end # if @script_contents and (not @script_contents.empty?) # build the command as an array. command_arry = ['-script', @filename, '-path', script_path.to_s] command_arry << '-target' command_arry << opts[:target].to_s command_arry << '-computerName' if opts[:computer_name] command_arry << opts[:computer_name] if opts[:computer_name] command_arry << '-username' if opts[:username] command_arry << opts[:username] if opts[:username] command_arry << '-p1' if opts[:p1] command_arry << opts[:p1] if opts[:p1] command_arry << '-p2' if opts[:p2] command_arry << opts[:p2] if opts[:p2] command_arry << '-p3' if opts[:p3] command_arry << opts[:p3] if opts[:p3] command_arry << '-p4' if opts[:p4] command_arry << opts[:p4] if opts[:p4] command_arry << '-p5' if opts[:p5] command_arry << opts[:p5] if opts[:p5] command_arry << '-p6' if opts[:p6] command_arry << opts[:p6] if opts[:p6] command_arry << '-p7' if opts[:p7] command_arry << opts[:p7] if opts[:p7] command_arry << '-p8' if opts[:p8] command_arry << opts[:p8] if opts[:p8] command_arry << '-verbose' if opts[:verbose] command = command_arry.shelljoin jamf_output = JSS::Client.run_jamf 'runScript', command, opts[:show_output] jamf_output =~ /^.*Script exit code: (\d+)(\D|$)/ script_exitstatus = Regexp.last_match(1).to_i ensure executable.delete if delete_exec && executable.exist? dist_point.unmount if dp_mount_pt && dp_mount_pt.mountpoint? && opts[:unmount] end # begin/ensure [script_exitstatus, jamf_output] end |
#set_parameter(param_num, new_val) ⇒ void
This method returns an undefined value.
Change one of the stored parameters
302 303 304 305 306 307 308 309 |
# File 'lib/jss/api_object/script.rb', line 302 def set_parameter(param_num, new_val) raise JSS::NoSuchItemError, 'Parameter numbers must be from 4-11' unless (4..11).cover? param_num pkey = "parameter#{param_num}".to_sym raise JSS::InvalidDataError, 'parameter values must be strings or nil' unless new_val.nil? || new_val.is_a?(String) return nil if new_val == @parameters[pkey] @parameters[pkey] = new_val @need_to_update = true end |
#unset_category ⇒ void Originally defined in module Categorizable
This method returns an undefined value.
Set the category to nothing
#update ⇒ Boolean Originally defined in module Updatable
Save changes to the JSS
#upload_master_file(rw_pw, unmount = true) ⇒ void
This method returns an undefined value.
Save the @script_contents for this script to a file on the Master Distribution point.
If you’ll be uploading several files you can specify unmount as false, and do it manually when all are finished.
use #script_contents= to set the script_contents from a String or Pathname
358 359 360 361 362 363 364 365 366 367 |
# File 'lib/jss/api_object/script.rb', line 358 def upload_master_file(rw_pw, unmount = true) raise JSS::MissingDataError, 'No code specified. Use #code= first.' if @script_contents.nil? || @script_contents.empty? mdp = JSS::DistributionPoint.master_distribution_point raise JSS::InvaldDatatError, 'Incorrect password for read-write access to master distribution point.' unless mdp.check_pw :rw, rw_pw destination = mdp.mount(rw_pw, :rw) + "#{DIST_POINT_SCRIPTS_FOLDER}/#{@filename}" destination.save @script_contents mdp.unmount if unmount end |