Class: Jamf::CollectionResource Abstract
- Inherits:
-
Resource
- Object
- JSONObject
- Resource
- Jamf::CollectionResource
- Extended by:
- Abstract
- Includes:
- Comparable
- Defined in:
- lib/jamf/api/abstract_classes/collection_resource.rb
Overview
A Collection Resource in Jamf Pro
See Resource for general info about API resources.
Collection resources have more than one resource within them, and those can (usually) be created and deleted as well as fetched and updated. The entire collection (or a part of it) can also be fetched as an Array. When the whole collection is fetched, the result is cached for future use.
# Subclassing
## Creatability, & Deletability
Sometimes the API doesn’t support creation of new members of the collection. If that’s the case, just extend the subclass with Jamf::UnCreatable and the ‘.create’ class method will raise an error.
Similarly for deletion of members: if the API doesn’t have a way to delete them, extend the subclass with Jamf::UnDeletable
See also Jamf::JSONObject, which talks about extending subclasses with Jamf::Immutable
## Bulk Deletion
Some collection resources have a resource for bulk deletion, passing in a JSON array of ids to delete.
If so, just define a BULK_DELETE_RSRC, and the .delete class method will use it, rather than making multiple calls to delete individual items. See Jamf::Category::BULK_DELETE_RSRC for an example
Direct Known Subclasses
AdvancedSearch, Building, Category, Computer, Department, DeviceEnrollment, ExtensionAttribute, InventoryPreloadRecord, MobileDevice, Prestage, Script, Site, TimeZone
Class Method Summary collapse
-
.all(refresh = false, cnx: Jamf.cnx, instantiate: false) ⇒ Array<Object>
The Collection members Array for this class, retrieved from the RSRC_PATH as Parsed JSON, but not instantiated into instances unless instantiate: is truthy.
-
.all_ids(refresh = false, cnx: Jamf.cnx) ⇒ Array<Integer>
An array of the ids for all collection members.
-
.creatable? ⇒ Boolean
Bu default, subclasses are creatable, i.e.
-
.create(**params) ⇒ Object
Make a new thing to be added to the API.
-
.deletable? ⇒ Boolean
By default, CollectionResource subclass instances are deletable.
-
.delete(*idents, cnx: Jamf.cnx) ⇒ Array
Delete one or more objects by identifier Any valid identifier for the class can be used (id, name, udid, etc) Identifiers can be provided as an array or as separate parameters.
-
.fetch(ident_value = nil, cnx: Jamf.cnx, **ident_hash) ⇒ CollectionResource
Retrieve a member of a CollectionResource from the API.
-
.identifiers ⇒ Array<Symbol>
The attribute names that are marked as identifiers.
-
.map_all(ident, to:, cnx: Jamf.cnx, refresh: false) ⇒ Hash {Symbol: Object}
A Hash of all members of this collection where the keys are some identifier and values are any other attribute.
-
.new(*args, &block) ⇒ Object
extended
from Abstract
when any extended class or subclass of an extended class is instntiated check that it isn’t in the abstract list.
-
.valid_id(value = nil, refresh: true, cnx: Jamf.cnx, **ident_hash) ⇒ Object?
Given any identfier value for this collection, return the id of the object that has such an identifier.
Instance Method Summary collapse
-
#<=>(other) ⇒ Object
Two collection resource objects are the same if their id’s are the same.
- #delete ⇒ Object
-
#exist? ⇒ Boolean
Instance Methods.
- #rsrc_path ⇒ Object
Constructor Details
This class inherits a constructor from Jamf::JSONObject
Class Method Details
.all(refresh = false, cnx: Jamf.cnx, instantiate: false) ⇒ Array<Object>
The Collection members Array for this class, retrieved from the RSRC_PATH as Parsed JSON, but not instantiated into instances unless instantiate: is truthy.
E.g. for Settings::Building, this would be the Array of Hashes returned by GETing the resource …/settings/obj/building
This Array is cached in the Jamf::Connection instance used to retrieve it, and future calls to .all will return the cached Array unless refresh is truthy.
TODO: Investigate www.rubydoc.info/github/mloughran/api_cache
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 100 def self.all(refresh = false, cnx: Jamf.cnx, instantiate: false) validate_not_abstract cnx.collection_cache[self] = nil if refresh if cnx.collection_cache[self] return cnx.collection_cache[self] unless instantiate return cnx.collection_cache[self].map { |m| new m } end # TODO: make sure all collection resources use this format # for paging. Also -ask Jamf about a url that returns # ALL objects in one query, regardless of number. page = 0 raw = cnx.get "#{rsrc_path}?page=#{page}&size=1000000&sort=id%3Aasc" results = raw[:results] until results.size >= raw[:totalCount] page += 1 raw = cnx.get "#{rsrc_path}?page=#{page}&size=1000000&sort=id%3Aasc" results += raw[:results] end cnx.collection_cache[self] = results return cnx.collection_cache[self] unless instantiate cnx.collection_cache[self].map { |m| new m } end |
.all_ids(refresh = false, cnx: Jamf.cnx) ⇒ Array<Integer>
An array of the ids for all collection members. According to the specs ALL collection resources must have an ID, which is used in the resource path.
140 141 142 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 140 def self.all_ids(refresh = false, cnx: Jamf.cnx) all(refresh, cnx: cnx).map { |m| m[:id] } end |
.creatable? ⇒ Boolean
Bu default, subclasses are creatable, i.e. new instances can be created with .create, and added to the JSS with .save If a subclass is NOT creatble for any reason, just add
extend Jamf::UnCreatable
and this method will return false
247 248 249 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 247 def self.creatable? true end |
.create(**params) ⇒ Object
Make a new thing to be added to the API
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 252 def self.create(**params) validate_not_abstract raise Jamf::UnsupportedError, "#{self}'s are not currently creatable via the API" unless creatable? cnx = params.delete :cnx cnx ||= Jamf.cnx params.delete :id # no such animal when .creating params.keys.each do |param| raise ArgumentError, "Unknown parameter: #{param}" unless self::OBJECT_MODEL.key? param params[param] = validate_attr param, params[param], cnx: cnx end params[:creating_from_create] = true new params, cnx: cnx end |
.deletable? ⇒ Boolean
By default, CollectionResource subclass instances are deletable. If not, just extend the subclass with Jamf::UnDeletable, and this will return false, and .delete & #delete will raise errors
317 318 319 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 317 def self.deletable? true end |
.delete(*idents, cnx: Jamf.cnx) ⇒ Array
Delete one or more objects by identifier Any valid identifier for the class can be used (id, name, udid, etc) Identifiers can be provided as an array or as separate parameters
e.g. .delete [1,3, 34, 4] or .delete ‘myComputer’, ‘that-computer’, ‘OtherComputer’
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 334 def self.delete(*idents, cnx: Jamf.cnx) raise Jamf::UnsupportedError, "Deleting #{self} objects is not currently supported" unless deletable? idents.flatten! no_valid_ids = [] idents.map do |ident| id = valid_id ident no_valid_ids << ident unless id id end idents.compact! # TODO: some rsrcs have a 'bulk delete' version... idents.each { |id| cnx.delete "#{rsrc_path}/#{id}" } no_valid_ids end |
.fetch(ident_value = nil, cnx: Jamf.cnx, **ident_hash) ⇒ CollectionResource
Retrieve a member of a CollectionResource from the API
To create new members to be added to the JSS, use create
If you know the specific identifier attribute you’re looking up, e.g. :id or :name or :udid, (or an aliase thereof) then you can specify it like ‘.fetch name: ’somename’‘, or `.fetch udid: ’someudid’‘
If you don’t know if (or don’t want to type it) you can just use ‘.fetch ’somename’‘, or `.fetch ’someudid’‘ and all identifiers will be searched for a match.
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 293 def self.fetch(ident_value = nil, cnx: Jamf.cnx, **ident_hash) validate_not_abstract id = if ident_value == :random all_ids.sample elsif ident_value valid_id ident_value, cnx: cnx elsif ident_hash.empty? nil else ident, lookup_value = ident_hash.first valid_id ident => lookup_value, cnx: cnx end raise Jamf::NoSuchItemError, "No matching #{self}" unless id data = cnx.get "#{rsrc_path}/#{id}" new data, cnx: cnx end |
.identifiers ⇒ Array<Symbol>
Returns the attribute names that are marked as identifiers.
73 74 75 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 73 def self.identifiers self::OBJECT_MODEL.select { |_attr, deets| deets[:identifier] }.keys end |
.map_all(ident, to:, cnx: Jamf.cnx, refresh: false) ⇒ Hash {Symbol: Object}
A Hash of all members of this collection where the keys are some identifier and values are any other attribute.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 161 def self.map_all(ident, to:, cnx: Jamf.cnx, refresh: false) real_ident = attr_key_for_alias ident raise Jamf::InvalidDataError, "No identifier #{ident} for class #{self}" unless identifiers.include? real_ident real_to = attr_key_for_alias to raise Jamf::NoSuchItemError, "No attribute #{to} for class #{self}" unless self::OBJECT_MODEL.key? real_to ident = real_ident to = real_to list = all refresh, cnx: cnx to_class = self::OBJECT_MODEL[to][:class] mapped = list.map do |i| [ i[ident], to_class.is_a?(Symbol) ? i[to] : to_class.new(i[to]) ] end # do i mapped.to_h end |
.new(*args, &block) ⇒ Object Originally defined in module Abstract
when any extended class or subclass of an extended class is instntiated check that it isn’t in the abstract list.
.valid_id(value = nil, refresh: true, cnx: Jamf.cnx, **ident_hash) ⇒ Object?
Given any identfier value for this collection, return the id of the object that has such an identifier.
Return nil if there’s no match for the given value.
If you know the value is a certain identifier, e.g. a serialNumber, then you can specify the identifier for a faster search:
valid_id serialNumber: 'AB12DE34' # => Int or nil
If you don’t know wich identifier you have, just pass the value and all identifiers are searched
valid_id 'AB12DE34' # => Int or nil
valid_id 'SomeComputerName' # => Int or nil
When the value is a string, the seach is case-insensitive
TODO: When ‘Searchability’ is more dialed in via the searchable mixin, which implements enpoints like ‘POST /v1/search-mobile-devices’ then use that before using the ‘all’ list.
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 218 def self.valid_id(value = nil, refresh: true, cnx: Jamf.cnx, **ident_hash) unless ident_hash.empty? ident, value = ident_hash.first return id_from_other_ident ident, value, refresh, cnx: cnx end # check the id itself first return value if all_ids(refresh, cnx: cnx).include? value idents = identifiers - [:id] val_is_str = value.is_a? String idents.each do |ident| match = all(refresh, cnx: cnx).select do |m| val_is_str ? m[ident].to_s.casecmp?(value) : m[ident] == value end.first return match[:id] if match end # identifiers.each do |ident| nil end |
Instance Method Details
#<=>(other) ⇒ Object
Two collection resource objects are the same if their id’s are the same
418 419 420 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 418 def <=>(other) id <=> other.id end |
#delete ⇒ Object
412 413 414 415 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 412 def delete raise Jamf::UnsupportedError, "Deleting #{self} objects is not currently supported" unless self.class.deletable? @cnx.delete rsrc_path end |
#exist? ⇒ Boolean
Instance Methods
403 404 405 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 403 def exist? !@id.nil? end |
#rsrc_path ⇒ Object
407 408 409 410 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 407 def rsrc_path return unless exist? "#{self.class.rsrc_path}/#{@id}" end |