Class: Jamf::APIObject
- Includes:
- Comparable
- Defined in:
- lib/jamf/api/classic/base_classes/api_object.rb
Overview
This class is the parent to all JSS API objects. It provides standard methods and constants that apply to all API resouces.
See the README.md file for general info about using subclasses of Jamf::APIObject
Subclassing
Initilize / Constructor
All subclasses must call ‘super` in their initialize method, which will call the method defined here in APIObject. Not only does this retrieve the data from the API, it parses the raw JSON data into a Hash, & stores it in In general, subclasses should do any class-specific argument checking before calling super, and then afterwards use the contents of @init_data to populate any class-specific attributes. Populating @id, @name, @rest_rsrc, and @in_jss are handled here.
This class also handles parsing @init_data for any mixed-in modules, e.g. Scopable, Categorizable or Extendable. See those modules for any requirements they have when including them.
Object Creation
If a subclass should be able to be created in the JSS be sure to include Creatable
The constructor should verify any extra required data in the args
See Creatable for more details.
Object Modification
If a subclass should be modifiable in the JSS, include Updatable, q.v. for details.
Object Deletion
All subclasses can be deleted in the JSS.
Required Constants
Subclasses must provide certain constants in order to correctly interpret API data and communicate with the API:
RSRC_BASE [String]
The base for REST resources of this class
e.g. ‘computergroups’ in
https://casper.mycompany.com:8443/JSSResource/computergroups/id/12
RSRC_LIST_KEY [Symbol]
When GETting the RSRC_BASE for a subclass, an Array of Hashes is returned with one Hash of basic info for each object of that type in the JSS. All objects have their JSS id and name in that Hash, some have other data as well. This Array is used for a variety of purposes when using ruby-jss, since it gives you basic info about all objects, without having to fetch each one individually.
Here’s the top of the output from the ‘computergroups’ RSRC_BASE:
{:computer_groups=>
[{:id=>1020, :name=>"config-no-turnstile", :is_smart=>true},
{:id=>1357, :name=>"10.8 Laptops", :is_smart=>true},
{:id=>1094, :name=>"wifi_cert-expired", :is_smart=>true},
{:id=>1144, :name=>"mytestgroup", :is_smart=>false},
...
Notice that the Array we want is embedded in a one-item Hash, and the key in that Hash for the desired Array is the Symbol :computer_groups.
That symbol is the value needed in the RSRC_LIST_KEY constant.
The ‘.all_ids’, ‘.all_names’ and other ‘.all_*’ class methods use the list-resource Array to extract other Arrays of the desired values - which can be used to check for existance without retrieving an entire object, among other uses.
RSRC_OBJECT_KEY [Symbol]
The one-item Hash key used for individual JSON object output. It’s also used in various error messages
As with the list-resource output mentioned above, when GETting a specific object resource, there’s an extra layer of encapsulation in a one-item Hash. Here’s the top of the JSON for a single computer group fetched from ‘…computergroups/id/1043’
{:computer_group=>
{:id=>1043,
:name=>"tmp-no-d3",
:is_smart=>false,
:site=>{:id=>-1, :name=>"None"},
:criteria=>[],
:computers=>[
...
The data for the group itself is the inner Hash.
The RSRC_OBJECT_KEY in this case is set to :computer_group - the key in the top-level, one-item Hash that we need to get the real Hash about the object.
Optional Constants
OTHER_LOOKUP_KEYS
Fetching individual objects from the API is usuallly done via the object’s unique JSS id, via a resrouce URL like so:
...JSSResource/<RSRC_BASE>/id/<idnumber>
Most objects can also be looked-up by name, because the API also has and endpoint ..JSSResource/<RSRC_BASE>/name/<name> (See NON_UNIQUE_NAMES below)
Some objects, like Computers and MobileDevices, have other values that serve as unique identifiers and can also be used as ‘lookup keys’ for fetching individual objects. When this is the case, those values always appear in the objects list-resource data (See RSRC_LIST_KEY above).
For example, here’s a summary-hash for a single MobileDevice from the list-resource ‘…JSSResource/mobiledevices’, which you might get in the Array returned by Jamf::MobileDevice.all:
{
:id=>3964,
:name=>"Bear",
:device_name=>"Bear",
:udid=>"XXX",
:serial_number=>"YYY2244MM60",
:phone_number=>"510-555-1212",
:wifi_mac_address=>"00:00:00:00:00:00",
:managed=>true,
:supervised=>false,
:model=>"iPad Pro (9.7-inch Cellular)",
:model_identifier=>"iPad6,4",
:modelDisplay=>"iPad Pro (9.7-inch Cellular)",
:model_display=>"iPad Pro (9.7-inch Cellular)",
:username=>"fred"
}
For MobileDevices, serial_number, udid, and wifi_mac_address are also all unique identifiers for an individual device, and can be used to fetch them.
To specify other identifiers for an APIObject subclass, create the constant OTHER_LOOKUP_KEYS containing a Hash of Hashes, like so:
OTHER_LOOKUP_KEYS = {
serial_number: {
aliases: [:serialnumber, :sn],
fetch_rsrc_key: :serialnumber
},
udid: {
fetch_rsrc_key: :udid
},
wifi_mac_address: {
aliases: [:macaddress, :macaddr],
fetch_rsrc_key: :macaddress
}
}.freeze
The keys in OTHER_LOOKUP_KEYS are the keys in a summary-hash data from .all that hold a unique identifier. Each value is a Hash with one or two keys:
- aliases: [Array<Symbol>]
Aliases for that identifier, i.e. abbreviations or spelling variants.
These aliases can be used in fetching, and they also have
matching `.all_<aliase>s` methods.
If no aliases are needed, don't specify anything, as with the udid:
in the example above
- fetch_rsrc_key: [Symbol]
Often a unique identifier can be used to build a URL for fetching (or
updating or deleteing) an object with that value, rather than with id.
For example, while the MobileDevice in the example data above would
normally be fetched at the resource 'JSSResource/mobiledevices/id/3964'
it can also be fetched at
'JSSResource/mobiledevices/serialnumber/YYY2244MM60'.
Since the URL is built using 'serialnumber', the symbol :serialnumber
is used as the fetch_rsrc_key.
Setting a fetch_rsrc_key: for one of the OTHER_LOOKUP_KEYS tells ruby-jss
that such a URL is available, and fetching by that lookup key will be
faster when using that URL.
If a fetch_rsrc_key is not set, fetching will be slower, since the fetch
method must first refresh the list of all available objects to find the
id to use for building the resource URL.
This is also true when fetching without specifying which lookup key to
use, e.g. `.fetch 'foo'` vs. `.fetch sn: 'foo'`
The OTHER_LOOKUP_KEYS, if defined, are merged with the DEFAULT_LOOKUP_KEYS defined below via the APIObject.lookup_keys class method, They are used for:
-
creating list-methods: For each lookup key, a class method ‘.all_<key>s` is created automatically, e.g. `.all_serial_numbers`. The aliases are used to make alises of those methods, e.g. `.all_sns`
-
finding valid ids: The APIObject.valid_id class method looks at the known lookup keys to find an object’s id.
-
fetching: When an indentifier is given to ‘.fetch`, the fetch_rsrc_key is used to build the resource URL for fetching the object. If there is no fetch_rsrc_key, the lookup_keys and aliases are used to find the matching id, which is used to build the URL.
When no identifier is specified, .fetch uses .valid_id, described above.
NON_UNIQUE_NAMES
Some JSS objects, like Computers and MobileDevices, do not treat names as unique in the JSS, but they can still be used for fetching objects. The API itself will return data for a non-unique name lookup, but there’s no way to guarantee which object you get back.
In those subclasses, set NON_UNIQUE_NAMES to any value, and a Jamf::AmbiguousError exception will be raised when trying to fetch by name and the name isn’t unique.
Because of the extra processing, the check for this state will only happen when NON_UNIQUE_NAMES is set. If not set at all, the check doesn’t happen and if multiple objects have the same name, which one is returned is undefined.
When that’s the case, fetching explicitly by name, or when fetching with a plain search term that matches a non-unique name, will raise a Jamf::AmbiguousError exception,when the name isn’t unique. If that happens, you’ll have to use some other identifier to fetch the desired object.
Note: Fetching, finding valid id, and name collisions are case-insensitive.
Direct Known Subclasses
Account, AdvancedSearch, Building, Category, Computer, ComputerInvitation, ConfigurationProfile, Department, DirectoryBinding, DiskEncryptionConfiguration, DistributionPoint, DockItem, Ebook, ExtensionAttribute, Group, IBeacon, LdapServer, MacApplication, MobileDevice, MobileDeviceApplication, NetBootServer, NetworkSegment, Package, PatchPolicy, PatchSource, PatchTitle, Peripheral, PeripheralType, Policy, Printer, RemovableMacAddress, RestrictedSoftware, Script, Site, SoftwareUpdateServer, User, VPPAccount, WebHook
Constant Summary collapse
- API_SOURCE =
which API do APIObjects come from? The JPAPI equivalent is in Jamf::JPAPIResource
:classic
- OK_INSTANTIATORS =
‘.new’ can only be called from these methods:
['make', 'create', 'fetch', 'block in fetch'].freeze
- DEFAULT_LOOKUP_KEYS =
See the discussion of ‘Lookup Keys’ in the comments/docs for Jamf::APIObject
{ id: { fetch_rsrc_key: :id }, name: { fetch_rsrc_key: :name } }.freeze
- OBJECT_HISTORY_TABLE =
This table holds the object history for JSS objects. Object history is not available via the API, only MySQL.
'object_history'.freeze
Instance Attribute Summary collapse
-
#cnx ⇒ Jamf::Connection
(also: #api)
readonly
The API connection thru which we deal with this object.
-
#id ⇒ Integer
readonly
The JSS id number.
-
#in_jss ⇒ Boolean
(also: #in_jss?)
readonly
Is it in the JSS?.
-
#init_data ⇒ Object
readonly
The parsed JSON data retrieved from the API when this object was fetched.
-
#name ⇒ String
readonly
The name.
-
#rest_rsrc ⇒ String
readonly
The Rest resource for API access (the part after “JSSResource/” ).
Class Method Summary collapse
-
.all(refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Array<Hash{:name=>String, :id=> Integer}>
Return an Array of Hashes for all objects of this subclass in the JSS.
-
.all_objects(refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Array<APIObject>
Return an Array of Jamf::APIObject subclass instances e.g when called on Jamf::Package, return a hash of Jamf::Package instancesa for every package in the JSS.
-
.create(**args) ⇒ APIObject
Make a ruby instance of a not-yet-existing APIObject.
-
.define_identifier_list_methods ⇒ Object
Loop through the defined lookup keys and make .all_<key>s methods for each one, with alises as needed.
-
.delete(victims, refresh = true, api: nil, cnx: Jamf.cnx) ⇒ Array<Integer>
Delete one or more API objects by jss_id without instantiating them.
-
.duplicate_names(refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Hash {String => Integer}
Name => number of occurances.
-
.exist?(identifier, refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Boolean
Return true or false if an object of this subclass with the given Identifier exists on the server.
-
.fetch(searchterm = nil, **args) ⇒ APIObject
Retrieve an object from the API and return an instance of this APIObject subclass.
-
.fetch_rsrc_key(lookup_key) ⇒ Symbol?
Given a lookup key, or an alias of one, return the matching fetch_rsrc_key for building a fetch/GET resource URL, or nil if no fetch_rsrc_key is defined.
-
.get_name(a_thing) ⇒ String
Some API objects contain references to other API objects.
-
.get_raw(id, format: :json, as_string: false, api: nil, cnx: Jamf.cnx) ⇒ Hash, ...
Fetch the mostly- or fully-raw JSON or XML data for an object of this subclass.
-
.id_for_identifier(key, val, refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Integer?
Return the id of the object of this subclass with the given lookup key == a given identifier.
-
.lookup_keys(no_aliases: false, fetch_rsrc_keys: false) ⇒ Hash {Symbol: Symbol}, Array<Symbol>
What are all the lookup keys available for this class, with all their aliases (or optionally not) or with their fetch_rsrc_keys.
-
.make(**args) ⇒ Object
deprecated
Deprecated.
use .create instead
-
.map_all(ident, to:, cnx: Jamf.cnx, refresh: false, cached_list: nil) ⇒ Hash {Symbol: Object}
A Hash of all members of this collection where the keys are some identifier and values are any other attribute.
-
.map_all_ids_to(other_key, refresh = false, cached_list: nil, api: nil, cnx: Jamf.cnx) ⇒ Hash{Integer => Oject}
Return a hash of all objects of this subclass in the JSS where the key is the id, and the value is some other key in the data items returned by the Jamf::APIObject.all.
-
.new(**args) ⇒ Object
Disallow direct use of ruby’s .new class method for creating instances.
-
.post_raw(xml, api: nil, cnx: Jamf.cnx) ⇒ REXML::Document
POST some raw XML to the API for a given id in this subclass.
-
.put_raw(id, xml, api: nil, cnx: Jamf.cnx) ⇒ REXML::Document
PUT some raw XML to the API for a given id in this subclass.
-
.real_lookup_key(key) ⇒ Symbol
get the real lookup key frm a given alias.
-
.valid_id(identifier = nil, refresh = false, api: nil, cnx: Jamf.cnx, **ident_and_val) ⇒ Integer?
Return the id of the object of this subclass with the given identifier.
-
.validate_not_metaclass(klass) ⇒ Object
Can’t use APIObject directly.
-
.xml_list(array, content = :name) ⇒ REXML::Element
Convert an Array of Hashes of API object data to a REXML element.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
COMPARABLE APIobjects are == if all of their lookup key values are the same.
-
#add_object_history_entry(user: nil, notes: nil, details: nil) ⇒ void
Make an entry in this object’s Object History.
-
#categorizable? ⇒ Boolean
See Categorizable.
-
#creatable? ⇒ Boolean
See Creatable.
-
#create ⇒ Object
@deprecated, use #save.
-
#criterable? ⇒ Boolean
See Criteriable.
-
#delete ⇒ void
Delete this item from the JSS.
-
#extendable? ⇒ Boolean
See extendable.
- #idents_combined ⇒ Object
-
#initialize(**args) ⇒ APIObject
constructor
The args hash must include :id, :name, or :data.
-
#locatable? ⇒ Boolean
See Locatable.
-
#matchable? ⇒ Boolean
See Matchable.
-
#object_history ⇒ Array<Hash>
the object history for this object, an array of hashes one per history entry, in order of creation.
-
#ppx ⇒ void
Print the rest_xml value of the object to stdout, with indentation.
-
#pretty_print_instance_variables ⇒ Array
Remove the init_data and api object from the instance_variables used to create pretty-print (pp) output.
-
#purchasable? ⇒ Boolean
See Purchasable.
-
#save ⇒ Integer
Either Create or Update this object in the JSS.
-
#scopable? ⇒ Boolean
See Scopable.
-
#self_servable? ⇒ Boolean
See SelfServable.
-
#sitable? ⇒ Boolean
See Sitable.
-
#to_s ⇒ String
A meaningful string representation of this object.
-
#updatable? ⇒ Boolean
See Updatable.
-
#update ⇒ Object
@deprecated, use #save.
-
#uploadable? ⇒ Boolean
See Uploadable.
-
#vppable? ⇒ Boolean
See VPPable.
Constructor Details
#initialize(**args) ⇒ APIObject
The args hash must include :id, :name, or :data.
-
:id or :name will be looked up via the API
-
if the subclass includes Jamf::Creatable, :id can be :new, to create a new object in the JSS. and :name is required
-
-
:data must be the JSON output of a separate Connection query (a Hash of valid object data)
Some subclasses can accept other options, by pasing their keys in a final Array
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1271 def initialize(**args) @cnx = args[:cnx] @cnx ||= args[:api] @cnx ||= Jamf.cnx # we're making a new one in the JSS if args[:id] == :new validate_init_for_creation(args) setup_object_for_creation(args) @need_to_update = true # we're instantiating an existing one in the jss else @init_data = look_up_object_data(args) @need_to_update = false end ## end arg parsing parse_init_data end |
Instance Attribute Details
#cnx ⇒ Jamf::Connection (readonly) Also known as: api
Returns the API connection thru which we deal with this object.
1225 1226 1227 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1225 def cnx @cnx end |
#id ⇒ Integer (readonly)
Returns the JSS id number.
1234 1235 1236 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1234 def id @id end |
#in_jss ⇒ Boolean (readonly) Also known as: in_jss?
Returns is it in the JSS?.
1240 1241 1242 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1240 def in_jss @in_jss end |
#init_data ⇒ Object (readonly)
Returns the parsed JSON data retrieved from the API when this object was fetched.
1231 1232 1233 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1231 def init_data @init_data end |
#name ⇒ String (readonly)
Returns the name.
1237 1238 1239 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1237 def name @name end |
#rest_rsrc ⇒ String (readonly)
Returns the Rest resource for API access (the part after “JSSResource/” ).
1243 1244 1245 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1243 def rest_rsrc @rest_rsrc end |
Class Method Details
.all(refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Array<Hash{:name=>String, :id=> Integer}>
Return an Array of Hashes for all objects of this subclass in the JSS.
This method is only valid in subclasses of Jamf::APIObject, and is the parsed JSON output of an API query for the resource defined in the subclass’s RSRC_BASE
e.g. for Jamf::Computer, with the RSRC_BASE of :computers, This method retuens the output of the ‘JSSResource/computers’ resource, which is a list of all computers in the JSS.
Each item in the Array is a Hash with at least two keys, :id and :name. The class methods .all_ids and .all_names provide easier access to those dataas mapped Arrays.
Some API classes provide other keys in each Hash, e.g. :udid (for computers and mobile devices) or :is_smart (for groups).
For those keys that are listed in a subclass’s lookup_keys method, there are matching methods ‘.all_(key)s` which return an array just of those values, from the values of this hash. For example, `.all_udids` will use the .all array to return an array of just udids, if the subclass defines :udid in its OTHER_LOOKUP_KEYS (See ’Lookup Keys’ in the class comments/docs above)
Subclasses should provide appropriate .all_xxx class methods for accessing any other other values as Arrays, e.g. Jamf::Computer.all_managed
– Caching
The results of the first call to .all for each subclass is cached in the .c_object_list_cache of the given Connection and that cache is used for all future calls, so as to not requery the server every time.
To force requerying to get updated data, provided a truthy argument. I usually use :refresh, so that it’s obvious what I’m doing, but true, 1, or anything besides false or nil will work.
The various methods that use the output of this method also take the refresh parameter which will be passed here as needed.
– Alternate API connections
To query an APIConnection other than the currently active one, provide one via the cnx: named parameter.
510 511 512 513 514 515 516 517 518 519 520 521 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 510 def self.all(refresh = false, api: nil, cnx: Jamf.cnx) cnx = api if api (self) cache = cnx.c_object_list_cache cache_key = self::RSRC_LIST_KEY cnx.flushcache(cache_key) if refresh return cache[cache_key] if cache[cache_key] cache[cache_key] = cnx.c_get(self::RSRC_BASE)[cache_key] end |
.all_objects(refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Array<APIObject>
Return an Array of Jamf::APIObject subclass instances e.g when called on Jamf::Package, return a hash of Jamf::Package instancesa for every package in the JSS.
WARNING: This may be slow as it has to look up each object individually! use it wisely.
650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 650 def self.all_objects(refresh = false, api: nil, cnx: Jamf.cnx) cnx = api if api objects_cache_key ||= "#{self::RSRC_LIST_KEY}_objects".to_sym api_cache = cnx.c_object_list_cache api_cache[objects_cache_key] = nil if refresh return api_cache[objects_cache_key] if api_cache[objects_cache_key] all_result = all(refresh, cnx: cnx) api_cache[objects_cache_key] = all_result.map do |o| fetch id: o[:id], cnx: cnx, refresh: false end end |
.create(**args) ⇒ APIObject
Make a ruby instance of a not-yet-existing APIObject.
This is how to create new objects in the JSS. A name: must be provided, and different subclasses can take other named parameters.
For retrieving existing objects in the JSS, use fetch
After calling this you’ll have a local instance, which will be created in the JSS when you call #create on it. see #create
1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1139 def self.create(**args) (self) unless constants.include?(:CREATABLE) raise Jamf::UnsupportedError, "Creating #{self::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." end raise ArgumentError, "Use '#{self.class}.fetch id: xx' to retrieve existing JSS objects" if args[:id] args[:cnx] ||= args[:api] # deprecated args[:cnx] ||= Jamf.cnx args[:id] = :new new(**args) end |
.define_identifier_list_methods ⇒ Object
Loop through the defined lookup keys and make .all_<key>s methods for each one, with alises as needed.
This is called automatically when subclasses are loaded by zeitwerk
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 297 def self.define_identifier_list_methods Jamf.load_msg "Defining list-methods for APIObject subclass #{self}" lookup_keys.each do |als, key| meth_name = key.to_s.end_with?('s') ? "all_#{key}es" : "all_#{key}s" if als == key # the all_ method - skip if defined in the class next if singleton_methods.include? meth_name.to_sym define_singleton_method meth_name do |refresh = false, cached_list: nil, api: nil, cnx: Jamf.cnx| cnx = api if api list = cached_list || all(refresh, cnx: cnx) list.map { |i| i[key] } end Jamf.load_msg "Defined method #{self}##{meth_name}" else # an alias - skip if defined in the class als_name = als.to_s.end_with?('s') ? "all_#{als}es" : "all_#{als}s" next if singleton_methods.include? als_name.to_sym define_singleton_method als_name do |refresh = false, api: nil, cnx: Jamf.cnx| cnx = api if api send meth_name, refresh, cnx: cnx end Jamf.load_msg "Defined alias '#{als_name}' of #{self}##{meth_name}" end # if end # lookup_keys.each true end |
.delete(victims, refresh = true, api: nil, cnx: Jamf.cnx) ⇒ Array<Integer>
Delete one or more API objects by jss_id without instantiating them. Non-existent id’s are skipped and an array of skipped ids is returned.
If an Array is provided, it is passed through #uniq! before being processed.
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1183 def self.delete(victims, refresh = true, api: nil, cnx: Jamf.cnx) cnx = api if api (self) raise Jamf::InvalidDataError, 'Parameter must be an Integer ID or an Array of them' unless victims.is_a?(Integer) || victims.is_a?(Array) case victims when Integer victims = [victims] when Array victims.uniq! end skipped = [] current_ids = all_ids refresh, cnx: cnx victims.each do |vid| if current_ids.include? vid cnx.c_delete "#{self::RSRC_BASE}/id/#{vid}" else skipped << vid end # if current_ids include vid end # each victim # clear any cached all-lists or id-maps for this class # so they'll re-cache as needed cnx.flushcache self::RSRC_LIST_KEY # all :refresh, cnx: cnx skipped end |
.duplicate_names(refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Hash {String => Integer}
Returns name => number of occurances.
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 525 def self.duplicate_names(refresh = false, api: nil, cnx: Jamf.cnx) cnx = api if api return {} unless defined? self::NON_UNIQUE_NAMES dups = {} all(refresh, cnx: cnx).each do |obj| if dups[obj[:name]] dups[obj[:name]] += 1 else dups[obj[:name]] = 1 end # if end # all(refresh, cnx: cnx).each dups.delete_if { |_k, v| v == 1 } dups end |
.exist?(identifier, refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Boolean
Return true or false if an object of this subclass with the given Identifier exists on the server
one of the available lookup_keys
831 832 833 834 835 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 831 def self.exist?(identifier, refresh = false, api: nil, cnx: Jamf.cnx) cnx = api if api !valid_id(identifier, refresh, cnx: cnx).nil? end |
.fetch(searchterm = nil, **args) ⇒ APIObject
Retrieve an object from the API and return an instance of this APIObject subclass.
Fetching is faster when specifying a lookup key, and that key has a fetch_rsrc_key defined in its OTHER_LOOKUP_KEYS constant, as in the second example above.
When no lookup key is given, as in the first example above, or when that key doesn’t have a defined fetch_rsrc_key, ruby-jss uses the currently cached list resource data to find the id matching the value given, and that id is used to fetch the object. (see ‘List Resources and Lookup Keys’ in the APIObject comments/docs above)
Since that cached list data may be out of date, you can provide the param ‘refrsh: true`, to reload the list from the server. This will cause the fetch to be slower still, so use with caution.
For creating new objects in the JSS, use make
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 961 def self.fetch(searchterm = nil, **args) (self) # which connection? cnx = args.delete :cnx cnx ||= args.delete :api # backward compatibility, deprecated cnx ||= Jamf.cnx # refresh the .all list if needed if args.delete(:refresh) || searchterm == :random all(:refresh, cnx: cnx) just_refreshed = true else just_refreshed = false end # a random object? if searchterm == :random || args[:random] rnd_thing = all(cnx: cnx).sample raise Jamf::NoSuchItemError, "No #{self::RSRC_LIST_KEY} found" unless rnd_thing return new id: rnd_thing[:id], cnx: cnx end # get the lookup key and value, if given fetch_key, fetch_val = args.to_a.first fetch_rsrc_key = fetch_rsrc_key(fetch_key) # names should raise an error if more than one exists, # so we always have to do id_for_identifier, which will do so. if fetch_rsrc_key == :name id = id_for_identifier fetch_key, fetch_val, !just_refreshed, cnx: cnx fetch_rsrc = id ? "#{self::RSRC_BASE}/name/#{CGI.escape fetch_val.to_s}" : nil # if the fetch rsrc key exists, it can be used directly in an endpoint path # so, use it directly, rather than looking up the id first. elsif fetch_rsrc_key fetch_rsrc = "#{self::RSRC_BASE}/#{fetch_rsrc_key}/#{CGI.escape fetch_val.to_s}" # it has an OTHER_LOOKUP_KEY but that key doesn't have a fetch_rsrc # so we look in the .map_all_ids_to_* hash for it. elsif fetch_key id = id_for_identifier fetch_key, fetch_val, !just_refreshed, cnx: cnx fetch_rsrc = id ? "#{self::RSRC_BASE}/id/#{id}" : nil # no fetch key was given in the args, so try a search term elsif searchterm id = valid_id searchterm, cnx: cnx fetch_rsrc = id ? "#{self::RSRC_BASE}/id/#{id}" : nil else raise ArgumentError, 'Missing searchterm or fetch key' end new fetch_rsrc: fetch_rsrc, cnx: cnx end |
.fetch_rsrc_key(lookup_key) ⇒ Symbol?
Given a lookup key, or an alias of one, return the matching fetch_rsrc_key for building a fetch/GET resource URL, or nil if no fetch_rsrc_key is defined.
See OTHER_LOOKUP_KEYS in the APIObject class comments/docs above for details.
418 419 420 421 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 418 def self.fetch_rsrc_key(lookup_key) parse_lookup_keys unless @fetch_rsrc_keys @fetch_rsrc_keys[lookup_key] end |
.get_name(a_thing) ⇒ String
Some API objects contain references to other API objects. Usually those references are a Hash containing the :id and :name of the target. Sometimes, however the reference is just the name of the target.
A Script has a property :category, which comes from the API as a String, the name of the category for that script. e.g. “GoodStuff”
A Policy also has a property :category, but it comes from the API as a Hash with both the name and id, e.g. {:id => 8, :name => “GoodStuff”}
When that reference is to a single thing (like the category to which something belongs) APIObject subclasses usually store only the name, and use the name when returning data to the API.
When an object references a list of related objects (like the computers assigned to a user) that list will be and Array of Hashes as above, with both the :id and :name
This method is just a handy way to extract the name regardless of how it comes from the API. Most APIObject subclasses use it in their #initialize method
908 909 910 911 912 913 914 915 916 917 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 908 def self.get_name(a_thing) case a_thing when String a_thing when Hash a_thing[:name] when nil nil end end |
.get_raw(id, format: :json, as_string: false, api: nil, cnx: Jamf.cnx) ⇒ Hash, ...
Fetch the mostly- or fully-raw JSON or XML data for an object of this subclass.
By default, returns the JSON data parsed into a Hash.
When format: is anything but :json, returns the XML data parsed into a REXML::Document
When as_string: is truthy, returns an unparsed JSON String (or XML String if format: is not :json) as it comes directly from the API.
When fetching raw JSON, the returned Hash will have its keys symbolized.
This can be substantialy faster than instantiating, especially when you don’t need all the ruby goodness of a full instance, but just want a few values for an object that aren’t available in the ‘all` data
This is really just a wrapper around Connection.c_get that automatically fills in the RSRC::BASE value for you.
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1050 def self.get_raw(id, format: :json, as_string: false, api: nil, cnx: Jamf.cnx) cnx = api if api (self) rsrc = "#{self::RSRC_BASE}/id/#{id}" data = cnx.c_get rsrc, format, raw_json: as_string return data if format == :json || as_string REXML::Document.new(**data) end |
.id_for_identifier(key, val, refresh = false, api: nil, cnx: Jamf.cnx) ⇒ Integer?
Return the id of the object of this subclass with the given lookup key == a given identifier.
Return nil if no object has that value in that key
Raises a Jamf::Ambiguous error if there’s more than one matching value for any key, which might be true of names for Computers and Devices
This is similar to .valid_id, except only one key is searched
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 797 def self.id_for_identifier(key, val, refresh = false, api: nil, cnx: Jamf.cnx) cnx = api if api # refresh if needed all(refresh, cnx: cnx) if refresh # get the real key if an alias was used key = real_lookup_key key # do id's expicitly, they are integers return all_ids(cnx: cnx).include?(val) ? val : nil if key == :id mapped_ids = map_all_ids_to key, cnx: cnx matches = mapped_ids.select { |_id, map_val| val.casecmp? map_val } raise Jamf::AmbiguousError, "Key #{key}: value '#{val}' is not unique for #{self}" if matches.size > 1 return nil if matches.size.zero? matches.keys.first end |
.lookup_keys(no_aliases: false, fetch_rsrc_keys: false) ⇒ Hash {Symbol: Symbol}, Array<Symbol>
What are all the lookup keys available for this class, with all their aliases (or optionally not) or with their fetch_rsrc_keys
This method combines the DEFAULT_LOOOKUP_KEYS defined above, with the optional OTHER_LOOKUP_KEYS from a subclass (See ‘Lookup Keys’ in the class comments/docs above)
The hash returned flattens and inverts the two source hashes, so that all possible lookup keys (the keys and their aliases) are hash keys and the non-aliased lookup key is the value.
For example, when
OTHER_LOOKUP_KEYS = {
serial_number: { aliases: [:serialnumber, :sn], fetch_rsrc_key: :serialnumber },
udid: { fetch_rsrc_key: :udid },
wifi_mac_address: { aliases: [:macaddress, :macaddr], fetch_rsrc_key: :macaddress }
}
It is combined with DEFAULT_LOOKUP_KEYS to produce:
{
id: :id,
name: :name,
serial_number: :serial_number,
serialnumber: :serial_number,
sn: :serial_number,
udid: :udid,
wifi_mac_address: :wifi_mac_address,
macaddress: :wifi_mac_address,
macaddr: :wifi_mac_address
}
If the optional parameter no_aliases: is truthy, only the real keynames are returned in an array, so the above would become
[:id, :name, :serial_number, :udid, :wifi_mac_address]
403 404 405 406 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 403 def self.lookup_keys(no_aliases: false, fetch_rsrc_keys: false) parse_lookup_keys unless @lookup_keys no_aliases ? @lookup_keys.values.uniq : @lookup_keys end |
.make(**args) ⇒ Object
use .create instead
backward compatability
1154 1155 1156 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1154 def self.make(**args) create(**args) end |
.map_all(ident, to:, cnx: Jamf.cnx, refresh: false, cached_list: nil) ⇒ Hash {Symbol: Object}
A Hash of all members of this collection where the keys are some identifier and values are any other attribute.
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 559 def self.map_all(ident, to:, cnx: Jamf.cnx, refresh: false, cached_list: nil) orig_ident = ident ident = lookup_keys[ident] raise Jamf::InvalidDataError, "No identifier :#{orig_ident} for class #{self}" unless ident list = cached_list || all(refresh, cnx: cnx) mapped = list.map do |i| [ i[ident], i[to] ] end # do i mapped.to_h end |
.map_all_ids_to(other_key, refresh = false, cached_list: nil, api: nil, cnx: Jamf.cnx) ⇒ Hash{Integer => Oject}
Return a hash of all objects of this subclass in the JSS where the key is the id, and the value is some other key in the data items returned by the Jamf::APIObject.all.
If the other key doesn’t exist in the API summary data from .all (eg :udid for Jamf::Department) the values will be nil.
Use this method to map ID numbers to other identifiers returned by the API list resources. Invert its result to map the other identfier to ids.
These hashes are cached separately from the .all data, and when the refresh parameter is truthy, both will be refreshed.
WARNING: Some values in the output of .all are not guaranteed to be unique in Jamf Pro. This is fine in the direct output of this method, each id will be the key for some value and many ids might have the same value. However if you invert that hash, the values become keys, and the ids become the values, and there can be only one id per each new key. Which id becomes associated with a value is undefined, and data about the others is lost. This is especially important if you ‘.map_all_ids_to :name`, since, for some objects, names are not unique.
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 616 def self.map_all_ids_to(other_key, refresh = false, cached_list: nil, api: nil, cnx: Jamf.cnx) cnx = api if api map_all :id, to: other_key, refresh: refresh, cnx: cnx, cached_list: cached_list # # we will accept any key, it'll just return nil if not in the # # .all hashes. However if we're given an alias of a lookup key # # we need to convert it to its real name. # other_key = lookup_keys[other_key] if lookup_keys[other_key] # # cache_key = "#{self::RSRC_LIST_KEY}_map_#{other_key}".to_sym # cache = cnx.c_object_list_cache # cache[cache_key] = nil if refresh # return cache[cache_key] if cache[cache_key] # # map = {} # all(refresh, cnx: cnx).each { |i| map[i[:id]] = i[other_key] } # cache[cache_key] = map end |
.new(**args) ⇒ Object
Disallow direct use of ruby’s .new class method for creating instances. Require use of .fetch or .make
1160 1161 1162 1163 1164 1165 1166 1167 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1160 def self.new(**args) (self) calling_method = caller_locations(1..1).first.label raise Jamf::UnsupportedError, 'Use .fetch or .create to instantiate APIObject classes' unless OK_INSTANTIATORS.include? calling_method super end |
.post_raw(xml, api: nil, cnx: Jamf.cnx) ⇒ REXML::Document
POST some raw XML to the API for a given id in this subclass.
WARNING: You must create or acquire the XML to be sent, and no validation will be performed on it. It must be a String, or something that returns an XML string with #to_s, such as a REXML::Document, or a REXML::Element.
This probably isn’t as much of a speed gain as get_raw or put_raw, as opposed to instantiating a ruby object, but might still be useful.
This is really just a wrapper around Connection.c_post that automatically fills in the RSRC::BASE value for you.
1111 1112 1113 1114 1115 1116 1117 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1111 def self.post_raw(xml, api: nil, cnx: Jamf.cnx) cnx = api if api (self) rsrc = "#{self::RSRC_BASE}/id/-1" REXML::Document.new(cnx.c_post(rsrc, xml.to_s)) end |
.put_raw(id, xml, api: nil, cnx: Jamf.cnx) ⇒ REXML::Document
PUT some raw XML to the API for a given id in this subclass.
WARNING: You must create or acquire the XML to be sent, and no validation will be performed on it. It must be a String, or something that returns an XML string with #to_s, such as a REXML::Document, or a REXML::Element.
In some cases, where you’re making simple changes to simple XML, this can be faster than fetching a full instance and the re-saving it.
This is really just a wrapper around Connection.c_put that automatically fills in the RSRC::BASE value for you.
1083 1084 1085 1086 1087 1088 1089 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1083 def self.put_raw(id, xml, api: nil, cnx: Jamf.cnx) cnx = api if api (self) rsrc = "#{self::RSRC_BASE}/id/#{id}" REXML::Document.new(cnx.c_put(rsrc, xml.to_s)) end |
.real_lookup_key(key) ⇒ Symbol
get the real lookup key frm a given alias
451 452 453 454 455 456 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 451 def self.real_lookup_key(key) real_key = lookup_keys[key] raise ArgumentError, "Unknown lookup key '#{key}' for #{self}" unless real_key real_key end |
.valid_id(identifier = nil, refresh = false, api: nil, cnx: Jamf.cnx, **ident_and_val) ⇒ Integer?
Return the id of the object of this subclass with the given identifier.
Return nil if no object has an identifier that matches.
For all objects the ‘name’ is an identifier. Some objects have more, e.g. udid, mac_address & serial_number. Matches are case-insensitive.
NOTE: while name is an identifier, for Computers and MobileDevices, it need not be unique in Jamf. If name is matched, which one gets returned is undefined. In short - dont’ use names here unless you know they are unique.
NOTE: Integers passed in as strings, e.g. ‘12345’ will be converted to integers and return the matching integer id if it exists.
This means that if you have names that might match ‘12345’ and you use
valid_id '12345'
you will get back the id 12345, if such an id exists, even if it is not the object with the name ‘12345’
To explicitly look for ‘12345’ as a name, use:
valid_id name: '12345'
See the ident_and_val param below.
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 711 def self.valid_id(identifier = nil, refresh = false, api: nil, cnx: Jamf.cnx, **ident_and_val) cnx = api if api # refresh the cache if needed all(refresh, cnx: cnx) if refresh # Were we given an explict identifier key, like name: or id:? # If so, just look for that. unless ident_and_val.empty? # only the first k/v pair of the ident_and_val hash is used key = ident_and_val.keys.first val = ident_and_val[key] # if we are explicitly looking for an id, ensure we use an integer # even if we were given an integer in a string. if key == :id val = val.to_i if val.is_a?(String) && val.j_integer? return all_ids(cnx: cnx).include?(val) ? val : nil end # map the identifiers to ids, and return the id if there's # a case-insensitive matching identifire map_all(key, to: :id).each do |ident_val, id| return id if ident_val.to_s.casecmp? val.to_s end nil end # If we are here, we need to seach all available identifier keys # Start by looking for it as an id. # it its a valid integer id, return it return identifier if all_ids(cnx: cnx).include? identifier # if its a valid integer-in-a-string id, return it if identifier.is_a?(String) && identifier.j_integer? int_id = identifier.to_i return int_id if all_ids(cnx: cnx).include? int_id end # Now go through all the other identifier keys keys_to_check = lookup_keys(no_aliases: true) keys_to_check.delete :id # we've already checked :id # loop thru looking for a match keys_to_check.each do |key| mapped_ids = map_all_ids_to key, cnx: cnx matches = mapped_ids.select { |_id, ident| ident.casecmp? identifier } # If exactly one match, return the id return matches.keys.first if matches.size == 1 end nil end |
.validate_not_metaclass(klass) ⇒ Object
Can’t use APIObject directly.
1216 1217 1218 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1216 def self.(klass) raise Jamf::UnsupportedError, 'Jamf::APIObject is a metaclass. Do not use it directly' if klass == Jamf::APIObject end |
.xml_list(array, content = :name) ⇒ REXML::Element
Convert an Array of Hashes of API object data to a REXML element.
Given an Array of Hashes of items in the subclass where each Hash has at least an :id or a :name key, (as what comes from the .all class method) return a REXML <classes> element with one <class> element per Hash member.
879 880 881 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 879 def self.xml_list(array, content = :name) JSS.item_list_to_rexml_list self::RSRC_LIST_KEY, self::RSRC_OBJECT_KEY, array, content end |
Instance Method Details
#<=>(other) ⇒ Object
COMPARABLE APIobjects are == if all of their lookup key values are the same
280 281 282 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 280 def <=>(other) idents_combined <=> other.idents_combined end |
#add_object_history_entry(user: nil, notes: nil, details: nil) ⇒ void
This method returns an undefined value.
Make an entry in this object’s Object History. For this to work, the APIObject subclass must define OBJECT_HISTORY_OBJECT_TYPE, an integer indicating the object type in the OBJECT_HISTORY_TABLE in the database (e.g. for computers, the object type is 1)
NOTE: Object history is not available via the Classic API,
so access is only available through direct MySQL
connections
Also: the ‘details’ column in the table shows up in the
'notes' column of the Web UI. and the 'object_description'
column of the table shows up in the 'details' column of
the UI, under the 'details' button.
The params below reflect the UI, not the table.
1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1482 def add_object_history_entry(user: nil, notes: nil, details: nil) validate_object_history_available raise Jamf::MissingDataError, 'A user: must be provided to make the entry' unless user raise Jamf::MissingDataError, 'notes: must be provided to make the entry' unless notes user = "'#{Mysql.quote user.to_s}'" notes = "'#{Mysql.quote notes.to_s}'" obj_type = self.class::OBJECT_HISTORY_OBJECT_TYPE field_list = 'object_type, object_id, username, details, timestamp_epoch' value_list = "#{obj_type}, #{@id}, #{user}, #{notes}, #{Time.now.to_jss_epoch}" if details field_list << ', object_description' value_list << ", '#{Mysql.quote details.to_s}'" end # if details q = "INSERT INTO #{OBJECT_HISTORY_TABLE} (#{field_list}) VALUES (#{value_list})" Jamf::DB_CNX.db.query q end |
#categorizable? ⇒ Boolean
Returns See Categorizable.
1352 1353 1354 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1352 def categorizable? defined? self.class::CATEGORIZABLE end |
#creatable? ⇒ Boolean
Returns See Creatable.
1342 1343 1344 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1342 def creatable? defined? self.class::CREATABLE end |
#create ⇒ Object
@deprecated, use #save
1322 1323 1324 1325 1326 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1322 def create raise Jamf::UnsupportedError, 'Creating this object in the JSS is currently not supported by ruby-jss' unless creatable? create_in_jamf end |
#criterable? ⇒ Boolean
Returns See Criteriable.
1367 1368 1369 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1367 def criterable? defined? self.class::CRITERIABLE end |
#delete ⇒ void
This method returns an undefined value.
Delete this item from the JSS.
one or more objects by id without needing to instantiate
Subclasses may want to redefine this method, first calling super, then setting other attributes to nil, false, empty, etc..
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1417 def delete return unless @in_jss @cnx.c_delete @rest_rsrc @rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name.to_s}" @id = nil @in_jss = false @need_to_update = false # clear any cached all-lists or id-maps for this class # so they'll re-cache as needed @cnx.flushcache self.class::RSRC_LIST_KEY # self.class.all :refresh, cnx: @cnx :deleted end |
#extendable? ⇒ Boolean
Returns See extendable.
1377 1378 1379 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1377 def extendable? defined? self.class::EXTENDABLE end |
#idents_combined ⇒ Object
284 285 286 287 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 284 def idents_combined my_keys = self.class.lookup_keys.values.uniq my_keys.map { |k| send(k).to_s }.sort.join end |
#locatable? ⇒ Boolean
Returns See Locatable.
1387 1388 1389 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1387 def locatable? defined? self.class::LOCATABLE end |
#matchable? ⇒ Boolean
Returns See Matchable.
1382 1383 1384 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1382 def matchable? defined? self.class::MATCHABLE end |
#object_history ⇒ Array<Hash>
the object history for this object, an array of hashes one per history entry, in order of creation. Each hash contains:
user: String, the username that created the entry
notes: String, the notes for the entry
date: Time, the timestamp for the entry
details: String or nil, any details provided for the entry
1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1519 def object_history validate_object_history_available q = "SELECT username, details, timestamp_epoch, object_description FROM #{OBJECT_HISTORY_TABLE} WHERE object_type = #{self.class::OBJECT_HISTORY_OBJECT_TYPE} AND object_id = #{@id} ORDER BY object_history_id ASC" result = Jamf::DB_CNX.db.query q history = [] result.each do |entry| history << { user: entry[0], notes: entry[1], date: JSS.epoch_to_time(entry[2]), details: entry[3] } end # each do entry history end |
#ppx ⇒ void
This method returns an undefined value.
Print the rest_xml value of the object to stdout, with indentation. Useful for debugging.
1546 1547 1548 1549 1550 1551 1552 1553 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1546 def ppx return nil unless creatable? || updatable? formatter = REXML::Formatters::Pretty.new(2) formatter.compact = true formatter.write(REXML::Document.new(rest_xml), $stdout) puts end |
#pretty_print_instance_variables ⇒ Array
Remove the init_data and api object from the instance_variables used to create pretty-print (pp) output.
1449 1450 1451 1452 1453 1454 1455 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1449 def pretty_print_instance_variables vars = instance_variables.sort vars.delete :@cnx vars.delete :@init_data vars.delete :@main_subset vars end |
#purchasable? ⇒ Boolean
Returns See Purchasable.
1392 1393 1394 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1392 def purchasable? defined? self.class::PURCHASABLE end |
#save ⇒ Integer
Either Create or Update this object in the JSS
If this item is creatable or updatable, then create it if needed, or update it if it already exists.
1313 1314 1315 1316 1317 1318 1319 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1313 def save if @in_jss update else create end end |
#scopable? ⇒ Boolean
Returns See Scopable.
1397 1398 1399 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1397 def scopable? defined? self.class::SCOPABLE end |
#self_servable? ⇒ Boolean
Returns See SelfServable.
1362 1363 1364 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1362 def self_servable? defined? self.class::SELF_SERVABLE end |
#sitable? ⇒ Boolean
Returns See Sitable.
1372 1373 1374 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1372 def sitable? defined? self.class::SITABLE end |
#to_s ⇒ String
A meaningful string representation of this object
1439 1440 1441 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1439 def to_s "#{self.class}@#{cnx.host}, id: #{@id}" end |
#updatable? ⇒ Boolean
Returns See Updatable.
1347 1348 1349 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1347 def updatable? defined? self.class::UPDATABLE end |
#update ⇒ Object
@deprecated, use #save
1329 1330 1331 1332 1333 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1329 def update raise Jamf::UnsupportedError, 'Updating this object in the JSS is currently not supported by ruby-jss' unless updatable? update_in_jamf end |
#uploadable? ⇒ Boolean
Returns See Uploadable.
1402 1403 1404 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1402 def uploadable? defined? self.class::UPLOADABLE end |
#vppable? ⇒ Boolean
Returns See VPPable.
1357 1358 1359 |
# File 'lib/jamf/api/classic/base_classes/api_object.rb', line 1357 def vppable? defined? self.class::VPPABLE end |