Class: JSS::ExtensionAttribute

Inherits:
APIObject show all
Includes:
Creatable, Updatable
Defined in:
lib/jss/api_object/extension_attribute.rb,
lib/jss.rb

Overview

The parent class of ExtensionAttribute objects in the JSS.

The API extension attribute objects work with the definitions of extension attributes, not the resulting values stored in the JSS with the inventory reports.

This superclass, however, uses the AdvancedSearch subclasses to provide access to the reported values in two ways:

  • A list of target objects with a certain value for the ExtensionAttribute instance. See the #all_with_result method for details

  • A list of the most recent value for this ExtensionAttribute in all targets in the JSS

The ComputerExtensionAttribute subclass offers a ComputerExtensionAttribute#history method providing the history of values for the EA for one computer. This requires MySQL access to the JSS database since that history isn't available via the API.

Subclasses of ExtensionAttribute must define these constants:

See Also:

Constant Summary collapse

DATA_TYPES =

What kinds of data can be created by EAs? Note, Dates must be in the format “YYYY-MM-DD hh:mm:ss”

%w[String Date Integer].freeze
DEFAULT_DATA_TYPE =
'String'.freeze
INPUT_TYPES =

Where does the data come from?

['Text Field', 'Pop-up Menu', 'script', 'LDAP Attribute Mapping'].freeze
DEFAULT_INPUT_TYPE =
'Text Field'.freeze
WEB_DISPLAY_CHOICES =

Where can it be displayed in the WebApp? subclasses can add to this list

[
  'General',
  'Operating System',
  'Hardware',
  'User and Location',
  'Purchasing',
  'Extension Attributes'
].freeze
DEFAULT_WEB_DISPLAY_CHOICE =
'Extension Attributes'.freeze
LAST_RECON_FIELD =
'Last Inventory Update'.freeze
LAST_RECON_FIELD_SYM =
LAST_RECON_FIELD.tr(' ', '_').to_sym
USERNAME_FIELD =
'Username'.freeze
USERNAME_FIELD_SYM =
USERNAME_FIELD.to_sym

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ ExtensionAttribute

Returns a new instance of ExtensionAttribute



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/jss/api_object/extension_attribute.rb', line 121

def initialize(args = {})
  super args

  # @init_data now has the raw data
  # so fill in our attributes or set defaults

  @description = @init_data[:description]
  @data_type = @init_data[:data_type] || DEFAULT_DATA_TYPE
  @web_display = @init_data[:inventory_display] || DEFAULT_WEB_DISPLAY_CHOICE

  if @init_data[:input_type]
    @input_type = @init_data[:input_type][:type] || DEFAULT_INPUT_TYPE
    @popup_choices = @init_data[:input_type][:popup_choices]
    # popups can always contain blank
    @popup_choices << JSS::BLANK if @popup_choices
  else
    @input_type = DEFAULT_INPUT_TYPE
  end

  # the name of the EA might have spaces and caps, which the will come to us as symbols with the spaces
  # as underscores, like this.
  @symbolized_name = @name.gsub(/-| /, '_').to_sym
end

Instance Attribute Details

#data_typeString

Returns the type of data created by the EA. Must be one of DATA_TYPES

Returns:

  • (String)

    the type of data created by the EA. Must be one of DATA_TYPES



103
104
105
# File 'lib/jss/api_object/extension_attribute.rb', line 103

def data_type
  @data_type
end

#descriptionString Also known as: desc

Returns description of the ext attrib

Returns:

  • (String)

    description of the ext attrib



100
101
102
# File 'lib/jss/api_object/extension_attribute.rb', line 100

def description
  @description
end

#input_typeString

Returns where does this data come from? Must be one of the INPUT_TYPES.

Returns:

  • (String)

    where does this data come from? Must be one of the INPUT_TYPES.



106
107
108
# File 'lib/jss/api_object/extension_attribute.rb', line 106

def input_type
  @input_type
end

#need_to_updateBoolean (readonly) Originally defined in module Updatable

Returns do we have unsaved changes?

Returns:

  • (Boolean)

    do we have unsaved changes?

Returns the choices available in the UI when the @input_type is “Pop-up Menu”

Returns:

  • (Array<String>)

    the choices available in the UI when the @input_type is “Pop-up Menu”



109
110
111
# File 'lib/jss/api_object/extension_attribute.rb', line 109

def popup_choices
  @popup_choices
end

#web_displayString

Returns In which part of the web UI does the data appear?

Returns:

  • (String)

    In which part of the web UI does the data appear?



112
113
114
# File 'lib/jss/api_object/extension_attribute.rb', line 112

def web_display
  @web_display
end

Instance Method Details

#all_with_result(search_type, desired_value) ⇒ Array<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time}>

Get an Array of Hashes for all inventory objects with a desired result in their latest report for this EA.

Each Hash is one inventory object (computer, mobile device, user), with these keys:

:id - the computer id
:name - the computer name
:value - the matching ext attr value for the objects latest report.

This is done by creating a temprary AdvancedSearch for objects with matching values in the EA field, then getting the #search_results hash from it.

The AdvancedSearch is then deleted.

must be a member of JSS::Criterion::SEARCH_TYPES

Parameters:

  • search_type (String)

    how are we comparing the stored value with the desired value.

  • desired_value (String)

    the value to compare with the stored value to determine a match.

Returns:

Raises:



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/jss/api_object/extension_attribute.rb', line 288

def all_with_result(search_type, desired_value)
  raise JSS::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss
  raise JSS::InvalidDataError, 'Invalid search_type, see JSS::Criteriable::Criterion::SEARCH_TYPES' unless JSS::Criteriable::Criterion::SEARCH_TYPES.include? search_type.to_s
  begin
    search_class = self.class::TARGET_CLASS::SEARCH_CLASS
    acs = search_class.make api: @api, name: "ruby-jss-EA-result-search-#{Time.now.to_jss_epoch}"
    acs.display_fields = [@name]
    crit_list = [JSS::Criteriable::Criterion.new(and_or: 'and', name: @name, search_type: search_type.to_s, value: desired_value)]
    acs.criteria = JSS::Criteriable::Criteria.new crit_list

    acs.create :get_results

    results = []

    acs.search_results.each do |i|
      value = case @data_type
              when 'Date' then JSS.parse_datetime i[@symbolized_name]
              when 'Integer' then i[@symbolized_name].to_i
              else i[@symbolized_name]
      end # case
      results << { id: i[:id], name: i[:name], value: value }
    end
  ensure
    acs.delete if acs.is_a? self.class::TARGET_CLASS::SEARCH_CLASS
  end
  results
end

#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

Parameters:

  • name (String)

    the name for the new object

  • api (JSS::APIConnection)

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

Returns:

  • (APIObject)

    An uncreated clone of this APIObject with the given name

Raises:

#createObject

See Also:



152
153
154
155
156
157
# File 'lib/jss/api_object/extension_attribute.rb', line 152

def create
  if @input_type == 'Pop-up Menu'
    raise MissingDataError, 'No popup_choices set for Pop-up Menu input_type.' unless @popup_choices.is_a?(Array) && !@popup_choices.empty?
  end
  super
end

#deleteObject

See Also:



170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/jss/api_object/extension_attribute.rb', line 170

def delete
  orig_open_timeout = @api.cnx.options[:open_timeout]
  orig_timeout = @api.cnx.options[:timeout]
  @api.timeout = orig_timeout + 1800
  @api.open_timeout = orig_open_timeout + 1800
  begin
    super
  ensure
    @api.timeout = orig_timeout
    @api.open_timeout = orig_open_timeout
  end
end

#latest_valuesArray<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time,:as_of=>Time}>

for this EA on all inventory objects in the JSS.

Each Hash is one inventory object (computer, mobile device, user), with these keys:

:id - the jss id
:name - the object (computer, user, mobiledevice) name
:value - the most recent ext attr value for the object.
:as_of - the timestamp of when the value was collected (nil for User EAs)
:username - the username associated with the object

This is done by creating a temporary AdvancedSearch for all objects, with the EA as a display field. The #search_result then contains the desired data.

The AdvancedSearch is then deleted.

Returns:

Raises:

See Also:



341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
# File 'lib/jss/api_object/extension_attribute.rb', line 341

def latest_values
  raise JSS::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss
  tmp_advsrch = "ruby-jss-EA-latest-search-#{Time.now.to_jss_epoch}"

  begin
    search_class = self.class::TARGET_CLASS::SEARCH_CLASS
    acs = search_class.make name: tmp_advsrch, api: @api
    acs.display_fields = self.class::TARGET_CLASS == JSS::User ? [@name, USERNAME_FIELD] : [@name, USERNAME_FIELD, LAST_RECON_FIELD]

    # search for 'Username like "" ' because all searchable object classes have a "Username" value
    crit = JSS::Criteriable::Criterion.new(and_or: 'and', name: 'Username', search_type: 'like', value: '')
    # crit = self.class::ALL_TARGETS_CRITERION
    acs.criteria = JSS::Criteriable::Criteria.new [crit]
    acs.create :get_results

    results = []

    acs.search_results.each do |i|
      value = case @data_type
              when 'Date' then JSS.parse_datetime i[@symbolized_name]
              when 'Integer' then i[@symbolized_name].to_i
              else i[@symbolized_name]
      end # case

      as_of = Time.parse(i[LAST_RECON_FIELD_SYM]) if i[LAST_RECON_FIELD_SYM]

      results << { id: i[:id], name: i[:name], username: i[USERNAME_FIELD_SYM], value: value, as_of: as_of }
    end # acs.search_results.each
  ensure
    if defined? acs
      acs.delete if acs
    else
      search_class.fetch(name: tmp_advsrch, api: @api).delete if search_class.all_names(:refresh, api: @api).include? tmp_advsrch
    end
  end

  results
end

#name=(newname) ⇒ void Originally defined in module Updatable

This method returns an undefined value.

Change the name of this item Remember to #update to push changes to the server.

Parameters:

  • newname (String)

    the new name

Raises:

#updateObject

See Also:



161
162
163
164
165
166
# File 'lib/jss/api_object/extension_attribute.rb', line 161

def update
  if @input_type == 'Pop-up Menu'
    raise MissingDataError, 'No popup_choices set for Pop-up Menu input_type.' unless @popup_choices.is_a?(Array) && !@popup_choices.empty?
  end
  super
end