Class: Jamf::ExtensionAttribute
- Defined in:
- lib/jamf/api/classic/base_classes/extension_attribute.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:
-
TARGET_CLASS - the APIObject subclass to which the extention attribute applies. e.g. Computer
-
ALL_TARGETS_CRITERION - a Criteriable::Criterion instance that will be used in an AdvancedSearch to find all of members of the TARGET_CLASS
Direct Known Subclasses
ComputerExtensionAttribute, MobileDeviceExtensionAttribute, UserExtensionAttribute
Constant Summary collapse
- DATA_TYPE_STRING =
What kinds of data can be created by EAs? Note, Dates must be in the format “YYYY-MM-DD hh:mm:ss”
'String'.freeze
- DATA_TYPE_NUMBER =
'Number'.freeze
- DATA_TYPE_INTEGER =
'Integer'.freeze
- DATA_TYPE_DATE =
'Date'.freeze
- DATA_TYPES =
[DATA_TYPE_STRING, DATA_TYPE_DATE, DATA_TYPE_INTEGER].freeze
- DEFAULT_DATA_TYPE =
DATA_TYPE_STRING
- NUMERIC_TYPES =
ExtensionAttributes refer to the numeric data type as “Integer” but the ext. attr values that come with extendable objects refer to that data type as “Number”. Here's an array with both, so we can work with ether more easily.
[DATA_TYPE_NUMBER, DATA_TYPE_INTEGER].freeze
- INPUT_TYPE_FIELD =
Where does the data come from?
'Text Field'.freeze
- INPUT_TYPE_POPUP =
'Pop-up Menu'.freeze
- INPUT_TYPE_SCRIPT =
'script'.freeze
- INPUT_TYPE_LDAP =
'LDAP Attribute Mapping'.freeze
- INPUT_TYPES =
[ INPUT_TYPE_FIELD, INPUT_TYPE_POPUP, INPUT_TYPE_SCRIPT, INPUT_TYPE_LDAP ].freeze
- DEFAULT_INPUT_TYPE =
INPUT_TYPE_FIELD
- WEB_DISPLAY_CHOICE_GENERAL =
Where can it be displayed in the WebApp?
'General'.freeze
- WEB_DISPLAY_CHOICE_OS =
'Operating System'.freeze
- WEB_DISPLAY_CHOICE_HW =
'Hardware'.freeze
- WEB_DISPLAY_CHOICE_USER_LOC =
'User and Location'.freeze
- WEB_DISPLAY_CHOICE_PURCHASING =
'Purchasing'.freeze
- WEB_DISPLAY_CHOICE_EAS =
'Extension Attributes'.freeze
- WEB_DISPLAY_CHOICES =
[ WEB_DISPLAY_CHOICE_GENERAL, WEB_DISPLAY_CHOICE_OS, WEB_DISPLAY_CHOICE_HW, WEB_DISPLAY_CHOICE_USER_LOC, WEB_DISPLAY_CHOICE_PURCHASING, WEB_DISPLAY_CHOICE_EAS ].freeze
- DEFAULT_WEB_DISPLAY_CHOICE =
WEB_DISPLAY_CHOICE_EAS
- 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
-
#attribute_mapping ⇒ String
The LDAP attribute for the User's ldap entry that maps to this EA, when input type is INPUT_TYPE_LDAP.
-
#data_type ⇒ String
The type of data created by the EA.
-
#description ⇒ String
(also: #desc)
Description of the ext attrib.
-
#input_type ⇒ String
Where does this data come from? Must be one of the INPUT_TYPES.
-
#need_to_update ⇒ Boolean
included
from Updatable
readonly
Do we have unsaved changes?.
-
#popup_choices ⇒ Array<String>
The choices available in the UI when the @input_type is “Pop-up Menu”.
-
#web_display ⇒ String
In which part of the web UI does the data appear?.
Instance Method Summary collapse
-
#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.
-
#clone(new_name, api: nil, cnx: nil) ⇒ APIObject
included
from Creatable
make a clone of this API object, with a new name.
- #create ⇒ Object
- #delete ⇒ Object
- #from_ldap? ⇒ Boolean
- #from_popup_menu? ⇒ Boolean
- #from_script? ⇒ Boolean
- #from_text_field? ⇒ Boolean
-
#initialize(**args) ⇒ ExtensionAttribute
constructor
A new instance of ExtensionAttribute.
-
#latest_values ⇒ Array<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time,:as_of=>Time}>
for this EA on all inventory objects in the JSS.
-
#name=(newname) ⇒ void
included
from Updatable
Change the name of this item Remember to #update to push changes to the server.
- #update ⇒ Object
Constructor Details
#initialize(**args) ⇒ ExtensionAttribute
Returns a new instance of ExtensionAttribute.
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 152 def initialize(**args) super # @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 if @init_data[:input_type] @input_type = @init_data[:input_type][:type] @script = @init_data[:input_type][:script] @attribute_mapping = @init_data[:input_type][:attribute_mapping] @popup_choices = @init_data[:input_type][:popup_choices] # popups can always contain blank @popup_choices << Jamf::BLANK if @popup_choices # These two are deprecated - windows won't be supported for long @platform = @init_data[:input_type][:platform] @scripting_language = @init_data[:input_type][:scripting_language] end @input_type ||= DEFAULT_INPUT_TYPE @enabled = @init_data[:enabled] @web_display = @init_data[:inventory_display] || DEFAULT_WEB_DISPLAY_CHOICE # deprecated - no longer in the UI @recon_display = @init_data[:recon_display] || @web_display # When used in Advanced Search results, the EA name # has colons removed, spaces & dashes turned to underscores. # and then ruby-jss symbolizes the name. @symbolized_name = @name.gsub(':', '').gsub(/-| /, '_').to_sym end |
Instance Attribute Details
#attribute_mapping ⇒ String
Returns the LDAP attribute for the User's ldap entry that maps to this EA, when input type is INPUT_TYPE_LDAP.
142 143 144 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 142 def attribute_mapping @attribute_mapping end |
#data_type ⇒ String
Returns the type of data created by the EA. Must be one of DATA_TYPES.
133 134 135 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 133 def data_type @data_type end |
#description ⇒ String Also known as: desc
Returns description of the ext attrib.
129 130 131 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 129 def description @description end |
#input_type ⇒ String
Returns where does this data come from? Must be one of the INPUT_TYPES.
136 137 138 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 136 def input_type @input_type end |
#need_to_update ⇒ Boolean (readonly) Originally defined in module Updatable
Returns do we have unsaved changes?.
#popup_choices ⇒ Array<String>
Returns the choices available in the UI when the @input_type is “Pop-up Menu”.
139 140 141 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 139 def popup_choices @popup_choices end |
#web_display ⇒ String
Returns In which part of the web UI does the data appear?.
145 146 147 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 145 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 Jamf::Criterion::SEARCH_TYPES
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 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 391 def all_with_result(search_type, desired_value) raise Jamf::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss unless Jamf::Criteriable::Criterion::SEARCH_TYPES.include? search_type.to_s raise Jamf::InvalidDataError, 'Invalid search_type, see Jamf::Criteriable::Criterion::SEARCH_TYPES' end begin search_class = self.class::TARGET_CLASS::SEARCH_CLASS acs = search_class.make cnx: @cnx, name: "ruby-jss-EA-result-search-#{Time.now.to_jss_epoch}" acs.display_fields = [@name] crit_list = [Jamf::Criteriable::Criterion.new(and_or: 'and', name: @name, search_type: search_type.to_s, value: desired_value)] acs.criteria = Jamf::Criteriable::Criteria.new crit_list acs.create :get_results results = [] acs.search_results.each do |i| value = case @data_type when 'Date' then Jamf.parse_time 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 # each ensure acs.delete if acs.is_a? self.class::TARGET_CLASS::SEARCH_CLASS end results end |
#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
#create ⇒ Object
193 194 195 196 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 193 def create validate_for_save super end |
#delete ⇒ Object
209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 209 def delete orig_open_timeout = @cnx.cnx.[:open_timeout] orig_timeout = @cnx.cnx.[:timeout] @cnx.timeout = orig_timeout + 1800 @cnx.open_timeout = orig_open_timeout + 1800 begin super @cnx.flushcache self.class ensure @cnx.timeout = orig_timeout @cnx.open_timeout = orig_open_timeout end end |
#from_ldap? ⇒ Boolean
231 232 233 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 231 def from_ldap? @input_type == INPUT_TYPE_LDAP end |
#from_popup_menu? ⇒ Boolean
227 228 229 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 227 def @input_type == INPUT_TYPE_POPUP end |
#from_script? ⇒ Boolean
235 236 237 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 235 def from_script? @input_type == INPUT_TYPE_SCRIPT end |
#from_text_field? ⇒ Boolean
223 224 225 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 223 def from_text_field? @input_type == INPUT_TYPE_FIELD end |
#latest_values ⇒ Array<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, or for devices that have never collected inventory)
: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.
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 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 448 def latest_values raise Jamf::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, cnx: @cnx acs.display_fields = self.class::TARGET_CLASS == Jamf::User ? [@name, USERNAME_FIELD] : [@name, USERNAME_FIELD, LAST_RECON_FIELD] # search for 'Username like "" ' because all searchable object classes have a "Username" value crit = Jamf::Criteriable::Criterion.new(and_or: 'and', name: 'Username', search_type: 'like', value: '') # crit = self.class::ALL_TARGETS_CRITERION acs.criteria = Jamf::Criteriable::Criteria.new [crit] acs.create :get_results results = [] acs.search_results.each do |i| value = case @data_type when 'Date' then Jamf.parse_time i[@symbolized_name] when 'Integer' then i[@symbolized_name].to_i else i[@symbolized_name] end # case as_of = Jamf.parse_time(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 elsif search_class.all_names(:refresh, cnx: @cnx).include? tmp_advsrch search_class.fetch(name: tmp_advsrch, cnx: @cnx).delete 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.
#update ⇒ Object
200 201 202 203 204 205 |
# File 'lib/jamf/api/classic/base_classes/extension_attribute.rb', line 200 def update validate_for_save super # this flushes the cached EA itself, used for validating ea values. @cnx.flushcache self.class end |