Class: Jamf::Script

Inherits:
APIObject show all
Includes:
Categorizable, Creatable, Updatable
Defined in:
lib/jamf/api/classic/api_objects/script.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

According to Jamf as of early 2021, it has been some years now since its been possible to store script contents on a dist. point - they are all always in the database.

Use the #run method to run the script on the local machine.

See Also:

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
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
CATEGORY_SUBSET =

Where is the Category in the API JSON?

:top
CATEGORY_DATA_TYPE =

How is the category stored in the API data?

String

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**args) ⇒ Script

Returns a new instance of Script.



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/jamf/api/classic/api_objects/script.rb', line 136

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]
  @script_contents_encoded = @init_data[:script_contents_encoded]
  if @script_contents && @script_contents_encoded.to_s.empty?
    @script_contents_encoded = Base64.encode64 @script_contents
  end
end

Instance Attribute Details

#filenameString

Returns the file name of the script, if stored in a dist. point.

Returns:

  • (String)

    the file name of the script, if stored in a dist. point



107
108
109
# File 'lib/jamf/api/classic/api_objects/script.rb', line 107

def filename
  @filename
end

#infoString

Returns the info field for this script.

Returns:

  • (String)

    the info field for this script



116
117
118
# File 'lib/jamf/api/classic/api_objects/script.rb', line 116

def info
  @info
end

#need_to_updateBoolean (readonly) Originally defined in module Updatable

Returns do we have unsaved changes?.

Returns:

  • (Boolean)

    do we have unsaved changes?

#notesString

Returns the notes field for this script.

Returns:

  • (String)

    the notes field for this script



119
120
121
# File 'lib/jamf/api/classic/api_objects/script.rb', line 119

def notes
  @notes
end

#os_requirementsArray<String> Also known as: oses

Returns the OS versions this can be installed onto. For all minor versions, the format is 10.5.x.

Returns:

  • (Array<String>)

    the OS versions this can be installed onto. For all minor versions, the format is 10.5.x



110
111
112
# File 'lib/jamf/api/classic/api_objects/script.rb', line 110

def os_requirements
  @os_requirements
end

#parametersHash Also known as: parameter_labels, parameter_descriptions

Returns descriptions of parameters 4-11. Parameters 1-3 are predefined as target drive, computer name, and username.

Returns:

  • (Hash)

    descriptions of parameters 4-11. Parameters 1-3 are predefined as target drive, computer name, and username



122
123
124
# File 'lib/jamf/api/classic/api_objects/script.rb', line 122

def parameters
  @parameters
end

#priorityString

Returns either ‘Before’ or ‘After’ or “At Reboot”.

Returns:

  • (String)

    either ‘Before’ or ‘After’ or “At Reboot”.



113
114
115
# File 'lib/jamf/api/classic/api_objects/script.rb', line 113

def priority
  @priority
end

#script_contentsString Also known as: code, contents

Returns the actual code for this script, if it’s stored in the database.

Returns:

  • (String)

    the actual code for this script, if it’s stored in the database.



127
128
129
# File 'lib/jamf/api/classic/api_objects/script.rb', line 127

def script_contents
  @script_contents
end

#script_contents_encodedString (readonly)

Returns the code for this script, Base64-encoded.

Returns:

  • (String)

    the code for this script, Base64-encoded



130
131
132
# File 'lib/jamf/api/classic/api_objects/script.rb', line 130

def script_contents_encoded
  @script_contents_encoded
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

Parameters:

  • new_cat (Integer, String)

    The new category

Raises:

#category_assigned?Boolean Also known as: categorized? Originally defined in module Categorizable

Does this object have a category assigned?

Returns:

  • (Boolean)

    Does this object have a category assigned?

#category_idInteger Originally defined in module Categorizable

The id of the category for this object.

Returns:

  • (Integer)

    The id of the category for this object.

#category_nameString 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’

Returns:

  • (String)

    The name of the category for this object.

#category_objectJamf::Category Originally defined in module Categorizable

The Jamf::Category instance for this object’s category

Returns:

  • (Jamf::Category)

    The Jamf::Category instance for this object’s category

#clone(new_name, api: nil, cnx: nil) ⇒ APIObject Originally defined in module Creatable

make a clone of this API object, with a new name. The class must be creatable

Parameters:

  • name (String)

    the name for the new object

  • cnx (Jamf::Connection) (defaults to: nil)

    the API in which to create the object Defaults to the API used to instantiate this object

Returns:

  • (APIObject)

    An unsaved clone of this APIObject with the given name

Raises:

#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

Parameters:

  • new_cat (String, Integer)

    The name or id of a possible category

Returns:

  • (Array<String, Integer>)

    The matching name and id, which may be nil.

#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

Parameters:

  • new_val (String)

    the new display name

Raises:



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/jamf/api/classic/api_objects/script.rb', line 181

def name=(new_val)
  new_val = new_val.to_s
  return if new_val == @name

  raise Jamf::MissingDataError, "Name can't be empty" if new_val.empty?
  raise Jamf::AlreadyExistsError, "A script already exists with the name '#{new_val}'" if Jamf::Script.all_names.include? new_val

  # if the filename matches the name, change that too.
  @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.to_s}" if @rest_rsrc.include? '/name/'
  @need_to_update = true
end

#run(**opts) ⇒ Array<(Integer,String)>

Run this script on the current machine.

If the script code is available in the #script_contents attribute, then that code is saved to a tmp file, and executed. The tmp file is deleted immediately 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 script.

The exit status of the jamf binary process will be available as a Process::Status object in $? immediately after running.

Parameters:

  • opts (Hash)

    the options for running the script

Options Hash (**opts):

  • :target (String, Pathname)

    the ‘target drive’, passed to the script as the first commandline option. Defaults to ‘/’

  • :computer_name (String)

    the name of the computer, passed to the script as the second commandline option. Defaults to the name of the current machine

  • :username (String)

    the username to be passed to the script as the third commandline option. Defaults to the current console user.

  • :p4..:p11 (String)

    the values to be passed as the 4th - 11th commandline params Script params 1, 2, & 3 are the target:, computer_name: and username: params

  • :show_output (Boolean)

    should the output (stdout + stderr) be copied to stdout in realtime, as well as returned?

Returns:

  • (Array<(Integer,String)>)

    the exit status and stdout+stderr of the script

Raises:



388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
# File 'lib/jamf/api/classic/api_objects/script.rb', line 388

def run(**opts)
  raise Jamf::MissingDataError, 'script_contents does not start with #!' unless @script_contents.to_s.start_with? '#!'

  opts[:target] ||= '/'
  opts[:computer_name] ||= Jamf::Client.run_jamf('getComputerName')[/>(.*?)</, 1]
  opts[:username] ||= Jamf::Client.console_user

  params = [opts[:target], opts[:computer_name], opts[:username]]
  params << opts[:p4]
  params << opts[:p5]
  params << opts[:p6]
  params << opts[:p7]
  params << opts[:p8]
  params << opts[:p9]
  params << opts[:p10]
  params << opts[:p11]

  # everything must be a string
  params.map! &:to_s

  # remove nils
  params.compact!

  # remove empty strings
  params.delete_if &:empty?

  return_value = []

  # Save and run the script from a private temp dir
  # which will be deleted when finished
  require 'tmpdir'
  Dir.mktmpdir do |dir|
    executable = Pathname.new "#{dir}/#{@name}"
    executable.jss_touch
    executable.chmod 0o700
    executable.jss_save @script_contents

    cmd = [executable.to_s]
    cmd += params

    stdout_and_stderr_str, status = Open3.capture2e(*cmd)

    return_value << status.exitstatus
    return_value << stdout_and_stderr_str
  end # Dir.mktmpdirs

  return_value
end

#set_parameter(param_num, new_val) ⇒ void Also known as: set_parameter_label, set_parameter_description

This method returns an undefined value.

Change one of the stored parameters

Parameters:

  • param_num (Integer)

    which param are we setting? must be 4..11

  • new_val (String)

    the new value for the parameter

Raises:



310
311
312
313
314
315
316
317
# File 'lib/jamf/api/classic/api_objects/script.rb', line 310

def set_parameter(param_num, new_val)
  raise Jamf::NoSuchItemError, 'Parameter numbers must be from 4-11' unless (4..11).cover? param_num
  pkey = "parameter#{param_num}".to_sym
  raise Jamf::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_categoryvoid Originally defined in module Categorizable

This method returns an undefined value.

Set the category to nothing