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 |
# 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 raw = cnx.get rsrc_path cnx.collection_cache[self] = if raw.is_a?(Hash) && raw[:results] raw[:results] else raw end 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.
132 133 134 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 132 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
239 240 241 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 239 def self.creatable? true end |
.create(**params) ⇒ Object
Make a new thing to be added to the API
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 244 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
309 310 311 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 309 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’
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 326 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.
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 285 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.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 153 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.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 210 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: 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
410 411 412 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 410 def <=>(other) id <=> other.id end |
#delete ⇒ Object
404 405 406 407 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 404 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
395 396 397 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 395 def exist? !@id.nil? end |
#rsrc_path ⇒ Object
399 400 401 402 |
# File 'lib/jamf/api/abstract_classes/collection_resource.rb', line 399 def rsrc_path return unless exist? "#{self.class.rsrc_path}/#{@id}" end |