ruby-jss 1.2.3 → 1.2.4a1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/jamf.rb +169 -0
- data/lib/jamf/api/abstract_classes/collection_resource.rb +422 -0
- data/lib/jamf/api/abstract_classes/generic_reference.rb +145 -0
- data/lib/jamf/api/abstract_classes/json_object.rb +1074 -0
- data/lib/jamf/api/abstract_classes/prestage.rb +219 -0
- data/lib/jamf/api/abstract_classes/prestage_skip_setup_items.rb +126 -0
- data/lib/jamf/api/abstract_classes/resource.rb +250 -0
- data/lib/jamf/api/abstract_classes/singleton_resource.rb +87 -0
- data/lib/jamf/api/attribute_classes/ip_address.rb +66 -0
- data/lib/jamf/api/attribute_classes/timestamp.rb +144 -0
- data/lib/jamf/api/connection.rb +734 -0
- data/lib/jamf/api/connection/api_error.rb +111 -0
- data/lib/jamf/api/connection/api_error_styleguide.rb +96 -0
- data/lib/jamf/api/connection/token.rb +220 -0
- data/lib/jamf/api/json_objects/account_prefs.rb +79 -0
- data/lib/jamf/api/json_objects/android_details.rb +139 -0
- data/lib/jamf/api/json_objects/appletv_details.rb +110 -0
- data/lib/jamf/api/json_objects/attachment.rb +68 -0
- data/lib/jamf/api/json_objects/cellular_network.rb +151 -0
- data/lib/jamf/api/json_objects/change_log_entry.rb +77 -0
- data/lib/jamf/api/json_objects/computer_prestage_skip_setup_items.rb +67 -0
- data/lib/jamf/api/json_objects/country.rb +51 -0
- data/lib/jamf/api/json_objects/extension_attribute_value.rb +128 -0
- data/lib/jamf/api/json_objects/installed_application.rb +59 -0
- data/lib/jamf/api/json_objects/installed_certificate.rb +53 -0
- data/lib/jamf/api/json_objects/installed_configuration_profile.rb +67 -0
- data/lib/jamf/api/json_objects/installed_ebook.rb +58 -0
- data/lib/jamf/api/json_objects/installed_provisioning_profile.rb +59 -0
- data/lib/jamf/api/json_objects/inventory_preload_extension_attribute.rb +52 -0
- data/lib/jamf/api/json_objects/ios_details.rb +244 -0
- data/lib/jamf/api/json_objects/location.rb +95 -0
- data/lib/jamf/api/json_objects/md_prestage_name.rb +57 -0
- data/lib/jamf/api/json_objects/md_prestage_names.rb +82 -0
- data/lib/jamf/api/json_objects/md_prestage_skip_setup_items.rb +165 -0
- data/lib/jamf/api/json_objects/mobile_device_details.rb +219 -0
- data/lib/jamf/api/json_objects/mobile_device_security.rb +101 -0
- data/lib/jamf/api/json_objects/prestage_assignment.rb +61 -0
- data/lib/jamf/api/json_objects/prestage_location.rb +104 -0
- data/lib/jamf/api/json_objects/prestage_purchasing_data.rb +132 -0
- data/lib/jamf/api/json_objects/prestage_scope.rb +54 -0
- data/lib/jamf/api/json_objects/prestage_sync_status.rb +63 -0
- data/lib/jamf/api/json_objects/purchasing_data.rb +125 -0
- data/lib/jamf/api/mixins/abstract.rb +58 -0
- data/lib/jamf/api/mixins/bulk_deletable.rb +39 -0
- data/lib/jamf/api/mixins/change_log.rb +136 -0
- data/lib/jamf/api/mixins/extendable.rb +75 -0
- data/lib/jamf/api/mixins/immutable.rb +39 -0
- data/lib/jamf/api/mixins/locatable.rb +124 -0
- data/lib/jamf/api/mixins/lockable.rb +48 -0
- data/lib/jamf/api/mixins/referable.rb +92 -0
- data/lib/jamf/api/mixins/searchable.rb +202 -0
- data/lib/jamf/api/mixins/uncreatable.rb +40 -0
- data/lib/jamf/api/mixins/undeletable.rb +40 -0
- data/lib/jamf/api/resources/collection_resources/account.rb +163 -0
- data/lib/jamf/api/resources/collection_resources/building.rb +114 -0
- data/lib/jamf/api/resources/collection_resources/category.rb +82 -0
- data/lib/jamf/api/resources/collection_resources/computer.rb +49 -0
- data/lib/jamf/api/resources/collection_resources/computer_prestage.rb +80 -0
- data/lib/jamf/api/resources/collection_resources/department.rb +79 -0
- data/lib/jamf/api/resources/collection_resources/extension_attribute.rb +45 -0
- data/lib/jamf/api/resources/collection_resources/inventory_preload_record.rb +274 -0
- data/lib/jamf/api/resources/collection_resources/md_prestage.rb +139 -0
- data/lib/jamf/api/resources/collection_resources/mobile_device.rb +315 -0
- data/lib/jamf/api/resources/collection_resources/script.rb +190 -0
- data/lib/jamf/api/resources/collection_resources/site.rb +77 -0
- data/lib/jamf/api/resources/singleton_resources/app_store_country_codes.rb +131 -0
- data/lib/jamf/api/resources/singleton_resources/authorization.rb +88 -0
- data/lib/jamf/api/resources/singleton_resources/client_checkin_settings.rb +139 -0
- data/lib/jamf/api/resources/singleton_resources/reenrollment_settings.rb +95 -0
- data/lib/jamf/client.rb +301 -0
- data/lib/jamf/client/jamf_binary.rb +132 -0
- data/lib/jamf/client/jamf_helper.rb +298 -0
- data/lib/jamf/client/management_action.rb +114 -0
- data/lib/jamf/compatibility.rb +88 -0
- data/lib/jamf/composer.rb +190 -0
- data/lib/jamf/configuration.rb +281 -0
- data/lib/jamf/exceptions.rb +107 -0
- data/lib/jamf/ruby_extensions.rb +36 -0
- data/lib/jamf/ruby_extensions/array.rb +35 -0
- data/lib/jamf/ruby_extensions/array/predicates.rb +46 -0
- data/lib/jamf/ruby_extensions/array/utils.rb +47 -0
- data/lib/jamf/ruby_extensions/filetest.rb +32 -0
- data/lib/jamf/ruby_extensions/filetest/predicates.rb +46 -0
- data/lib/jamf/ruby_extensions/hash.rb +33 -0
- data/lib/jamf/ruby_extensions/hash/backports.rb +92 -0
- data/lib/jamf/ruby_extensions/ipaddr.rb +37 -0
- data/lib/jamf/ruby_extensions/ipaddr/utils.rb +95 -0
- data/lib/jamf/ruby_extensions/object.rb +30 -0
- data/lib/jamf/ruby_extensions/object/predicates.rb +51 -0
- data/lib/jamf/ruby_extensions/pathname.rb +39 -0
- data/lib/jamf/ruby_extensions/pathname/predicates.rb +50 -0
- data/lib/jamf/ruby_extensions/pathname/utils.rb +75 -0
- data/lib/jamf/ruby_extensions/string.rb +35 -0
- data/lib/jamf/ruby_extensions/string/backports.rb +66 -0
- data/lib/jamf/ruby_extensions/string/conversions.rb +65 -0
- data/lib/jamf/ruby_extensions/string/predicates.rb +47 -0
- data/lib/jamf/utility.rb +423 -0
- data/lib/jamf/validate.rb +224 -0
- data/lib/jamf/version.rb +32 -0
- data/lib/jpapi.rb +26 -0
- data/lib/jss/version.rb +1 -1
- metadata +104 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25d16b4c34d2790bdf6175543f81a2125e80ddf0c2c49cbb76d340b76dd562df
|
|
4
|
+
data.tar.gz: a09cfceaaecd6c3109cafbd0d7912a1c66326c6c5ddaae479a4260816c50ede9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fb2e1e6fb575db16ade4b819bbea3cfb73ce6956c1012569f2be10d757ed05f31c4671605065a6c619667afa3a2540119af0afee5cf506d1ae8455d4aa42d4c0
|
|
7
|
+
data.tar.gz: 4af7406b1457c0c70d4873578920938b942ed7b6ea15702898f74450453720f30b24803addf8762426f617b7e223ef34ae2d51453df5cf283da35c32d27a8854
|
data/lib/jamf.rb
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Copyright 2019 Pixar
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
5
|
+
# with the following modification; you may not use this file except in
|
|
6
|
+
# compliance with the Apache License and the following modification to it:
|
|
7
|
+
# Section 6. Trademarks. is deleted and replaced with:
|
|
8
|
+
#
|
|
9
|
+
# 6. Trademarks. This License does not grant permission to use the trade
|
|
10
|
+
# names, trademarks, service marks, or product names of the Licensor
|
|
11
|
+
# and its affiliates, except as required to comply with Section 4(c) of
|
|
12
|
+
# the License and to reproduce the content of the NOTICE file.
|
|
13
|
+
#
|
|
14
|
+
# You may obtain a copy of the Apache License at
|
|
15
|
+
#
|
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
#
|
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
# distributed under the Apache License with the above modification is
|
|
20
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
21
|
+
# KIND, either express or implied. See the Apache License for the specific
|
|
22
|
+
# language governing permissions and limitations under the Apache License.
|
|
23
|
+
#
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
#
|
|
27
|
+
# JAMF, A Ruby module for interacting with a JAMF Pro Server via the JAMF API
|
|
28
|
+
#
|
|
29
|
+
|
|
30
|
+
### Standard Libraries
|
|
31
|
+
require 'English'
|
|
32
|
+
require 'json'
|
|
33
|
+
require 'yaml'
|
|
34
|
+
require 'pathname'
|
|
35
|
+
require 'time'
|
|
36
|
+
require 'singleton'
|
|
37
|
+
require 'open-uri'
|
|
38
|
+
require 'ipaddr'
|
|
39
|
+
require 'base64'
|
|
40
|
+
require 'shellwords'
|
|
41
|
+
require 'digest'
|
|
42
|
+
require 'open3'
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
### Gems
|
|
46
|
+
require 'rest-client'
|
|
47
|
+
require 'plist'
|
|
48
|
+
|
|
49
|
+
# Used, among other places, in the Connection::APIError class
|
|
50
|
+
require 'immutable-struct'
|
|
51
|
+
|
|
52
|
+
# TODO: needed?
|
|
53
|
+
# require 'recursive-open-struct'
|
|
54
|
+
|
|
55
|
+
# non-api parts of Jamf module
|
|
56
|
+
require 'jamf/configuration'
|
|
57
|
+
require 'jamf/exceptions'
|
|
58
|
+
require 'jamf/utility'
|
|
59
|
+
require 'jamf/validate'
|
|
60
|
+
require 'jamf/version'
|
|
61
|
+
|
|
62
|
+
# backports and extensions to existing Ruby classes
|
|
63
|
+
require 'jamf/compatibility'
|
|
64
|
+
require 'jamf/ruby_extensions'
|
|
65
|
+
|
|
66
|
+
# API connection
|
|
67
|
+
require 'jamf/api/connection'
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# The main module.
|
|
71
|
+
# See README.md
|
|
72
|
+
#
|
|
73
|
+
module Jamf
|
|
74
|
+
|
|
75
|
+
# The minimum Ruby version that works with this gem
|
|
76
|
+
# 2.3 allows us to start using some nice features like the safe-navigation
|
|
77
|
+
# operator and Array#dig & Hash#dig, and such.
|
|
78
|
+
#
|
|
79
|
+
# For a list of features, see https://github.com/ruby/ruby/blob/v2_3_0/NEWS
|
|
80
|
+
# and http://nithinbekal.com/posts/ruby-2-3-features/
|
|
81
|
+
#
|
|
82
|
+
MINIMUM_RUBY_VERSION = '2.3'.freeze
|
|
83
|
+
|
|
84
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new(MINIMUM_RUBY_VERSION)
|
|
85
|
+
raise "Can't use the JAMF module, ruby itself must be version #{MINIMUM_RUBY_VERSION} or greater."
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# AUTOLOADING
|
|
89
|
+
##################################
|
|
90
|
+
|
|
91
|
+
# Top-level API Abstract Classes
|
|
92
|
+
autoload :JSONObject, 'jamf/api/abstract_classes/json_object'
|
|
93
|
+
autoload :Resource, 'jamf/api/abstract_classes/resource'
|
|
94
|
+
autoload :SingletonResource, 'jamf/api/abstract_classes/singleton_resource'
|
|
95
|
+
autoload :CollectionResource, 'jamf/api/abstract_classes/collection_resource'
|
|
96
|
+
|
|
97
|
+
# Abstract Classes used for JSONObject subclasses
|
|
98
|
+
autoload :Prestage, 'jamf/api/abstract_classes/prestage'
|
|
99
|
+
autoload :PrestageSkipSetupItems, 'jamf/api/abstract_classes/prestage_skip_setup_items'
|
|
100
|
+
|
|
101
|
+
# Abstract Classes not used for JSONObject subclasses
|
|
102
|
+
autoload :GenericReference, 'jamf/api/abstract_classes/generic_reference'
|
|
103
|
+
|
|
104
|
+
# MixIn Modules
|
|
105
|
+
autoload :ChangeLog, 'jamf/api/mixins/change_log'
|
|
106
|
+
autoload :Extendable, 'jamf/api/mixins/extendable'
|
|
107
|
+
autoload :Locatable, 'jamf/api/mixins/locatable'
|
|
108
|
+
autoload :Referable, 'jamf/api/mixins/referable'
|
|
109
|
+
autoload :Searchable, 'jamf/api/mixins/searchable'
|
|
110
|
+
autoload :Lockable, 'jamf/api/mixins/lockable'
|
|
111
|
+
autoload :UnCreatable, 'jamf/api/mixins/uncreatable'
|
|
112
|
+
autoload :Immutable, 'jamf/api/mixins/immutable'
|
|
113
|
+
autoload :UnDeletable, 'jamf/api/mixins/undeletable'
|
|
114
|
+
autoload :Abstract, 'jamf/api/mixins/abstract'
|
|
115
|
+
|
|
116
|
+
# Utility modules
|
|
117
|
+
autoload :Validate, 'jamf/validate'
|
|
118
|
+
|
|
119
|
+
# Subclasses of JSONObject, but not Resource
|
|
120
|
+
autoload :AndroidDetails, 'jamf/api/json_objects/android_details'
|
|
121
|
+
autoload :AppleTVDetails, 'jamf/api/json_objects/appletv_details'
|
|
122
|
+
autoload :CellularNetwork, 'jamf/api/json_objects/cellular_network'
|
|
123
|
+
autoload :ChangeLogEntry, 'jamf/api/json_objects/change_log_entry'
|
|
124
|
+
autoload :ComputerPrestageSkipSetupItems, 'jamf/api/json_objects/computer_prestage_skip_setup_items'
|
|
125
|
+
autoload :Country, 'jamf/api/json_objects/country'
|
|
126
|
+
autoload :ExtensionAttributeValue, 'jamf/api/json_objects/extension_attribute_value'
|
|
127
|
+
autoload :InstalledApplication, 'jamf/api/json_objects/installed_application'
|
|
128
|
+
autoload :InstalledCertificate, 'jamf/api/json_objects/installed_certificate'
|
|
129
|
+
autoload :InstalledConfigurationProfile, 'jamf/api/json_objects/installed_configuration_profile'
|
|
130
|
+
autoload :InstalledEBook, 'jamf/api/json_objects/installed_ebook'
|
|
131
|
+
autoload :InstalledProvisioningProfile, 'jamf/api/json_objects/installed_provisioning_profile'
|
|
132
|
+
autoload :InventoryPreloadExtensionAttribute, 'jamf/api/json_objects/inventory_preload_extension_attribute'
|
|
133
|
+
autoload :IosDetails, 'jamf/api/json_objects/ios_details'
|
|
134
|
+
autoload :Location, 'jamf/api/json_objects/location'
|
|
135
|
+
autoload :PrestageLocation, 'jamf/api/json_objects/prestage_location'
|
|
136
|
+
autoload :PrestageSyncStatus, 'jamf/api/json_objects/prestage_sync_status'
|
|
137
|
+
autoload :MobileDeviceDetails, 'jamf/api/json_objects/mobile_device_details'
|
|
138
|
+
autoload :MobileDeviceSecurity, 'jamf/api/json_objects/mobile_device_security'
|
|
139
|
+
autoload :MobileDevicePrestageName, 'jamf/api/json_objects/md_prestage_name'
|
|
140
|
+
autoload :MobileDevicePrestageNames, 'jamf/api/json_objects/md_prestage_names'
|
|
141
|
+
autoload :MobileDevicePrestageSkipSetupItems, 'jamf/api/json_objects/md_prestage_skip_setup_items'
|
|
142
|
+
autoload :PurchasingData, 'jamf/api/json_objects/purchasing_data'
|
|
143
|
+
autoload :PrestagePurchasingData, 'jamf/api/json_objects/prestage_purchasing_data'
|
|
144
|
+
autoload :PrestageScope, 'jamf/api/json_objects/prestage_scope'
|
|
145
|
+
autoload :PrestageAssignment, 'jamf/api/json_objects/prestage_assignment'
|
|
146
|
+
|
|
147
|
+
# Subclasses of SingletonResource
|
|
148
|
+
autoload :ClientCheckInSettings, 'jamf/api/resources/singleton_resources/client_checkin_settings'
|
|
149
|
+
autoload :ReEnrollmentSettings, 'jamf/api/resources/singleton_resources/reenrollment_settings'
|
|
150
|
+
autoload :AppStoreCountryCodes, 'jamf/api/resources/singleton_resources/app_store_country_codes'
|
|
151
|
+
|
|
152
|
+
# Subclasses of CollectionResource
|
|
153
|
+
autoload :Attachment, 'jamf/api/resources/collection_resources/attachment'
|
|
154
|
+
autoload :Building, 'jamf/api/resources/collection_resources/building'
|
|
155
|
+
autoload :Computer, 'jamf/api/resources/collection_resources/computer'
|
|
156
|
+
autoload :ComputerPrestage, 'jamf/api/resources/collection_resources/computer_prestage'
|
|
157
|
+
autoload :Department, 'jamf/api/resources/collection_resources/department'
|
|
158
|
+
autoload :ExtensionAttribute, 'jamf/api/resources/collection_resources/extension_attribute'
|
|
159
|
+
autoload :InventoryPreloadRecord, 'jamf/api/resources/collection_resources/inventory_preload_record'
|
|
160
|
+
autoload :MobileDevice, 'jamf/api/resources/collection_resources/mobile_device'
|
|
161
|
+
autoload :MobileDevicePrestage, 'jamf/api/resources/collection_resources/md_prestage'
|
|
162
|
+
autoload :Site, 'jamf/api/resources/collection_resources/site'
|
|
163
|
+
autoload :Script, 'jamf/api/resources/collection_resources/script'
|
|
164
|
+
|
|
165
|
+
# other classes used as attributes inside the resource classes
|
|
166
|
+
autoload :IPAddress, 'jamf/api/attribute_classes/ip_address'
|
|
167
|
+
autoload :Timestamp, 'jamf/api/attribute_classes/timestamp'
|
|
168
|
+
|
|
169
|
+
end # module
|
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# Copyright 2019 Pixar
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "Apache License")
|
|
5
|
+
# with the following modification; you may not use this file except in
|
|
6
|
+
# compliance with the Apache License and the following modification to it:
|
|
7
|
+
# Section 6. Trademarks. is deleted and replaced with:
|
|
8
|
+
#
|
|
9
|
+
# 6. Trademarks. This License does not grant permission to use the trade
|
|
10
|
+
# names, trademarks, service marks, or product names of the Licensor
|
|
11
|
+
# and its affiliates, except as required to comply with Section 4(c) of
|
|
12
|
+
# the License and to reproduce the content of the NOTICE file.
|
|
13
|
+
#
|
|
14
|
+
# You may obtain a copy of the Apache License at
|
|
15
|
+
#
|
|
16
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
+
#
|
|
18
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
# distributed under the Apache License with the above modification is
|
|
20
|
+
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
21
|
+
# KIND, either express or implied. See the Apache License for the specific
|
|
22
|
+
# language governing permissions and limitations under the Apache License.
|
|
23
|
+
#
|
|
24
|
+
#
|
|
25
|
+
|
|
26
|
+
# The module
|
|
27
|
+
module Jamf
|
|
28
|
+
|
|
29
|
+
# A Collection Resource in Jamf Pro
|
|
30
|
+
#
|
|
31
|
+
# See {Jamf::Resource} for general info about API resources.
|
|
32
|
+
#
|
|
33
|
+
# Collection resources have more than one resource within them, and those
|
|
34
|
+
# can (usually) be created and deleted as well as fetched and updated.
|
|
35
|
+
# The entire collection (or a part of it) can also be fetched as an Array.
|
|
36
|
+
# When the whole collection is fetched, the result is cached for future use.
|
|
37
|
+
#
|
|
38
|
+
# # Subclassing
|
|
39
|
+
#
|
|
40
|
+
# ## Creatability, & Deletability
|
|
41
|
+
#
|
|
42
|
+
# Sometimes the API doesn't support creation of new members of the collection.
|
|
43
|
+
# If that's the case, just extend the subclass with Jamf::UnCreatable
|
|
44
|
+
# and the '.create' class method will raise an error.
|
|
45
|
+
#
|
|
46
|
+
# Similarly for deletion of members: if the API doesn't have a way to delete
|
|
47
|
+
# them, extend the subclass with Jamf::UnDeletable
|
|
48
|
+
#
|
|
49
|
+
# See also Jamf::JSONObject, which talks about extending subclasses
|
|
50
|
+
# with Jamf::Immutable
|
|
51
|
+
#
|
|
52
|
+
# ## Bulk Deletion
|
|
53
|
+
#
|
|
54
|
+
# Some collection resources have a resource for bulk deletion, passing in
|
|
55
|
+
# a JSON array of ids to delete.
|
|
56
|
+
#
|
|
57
|
+
# If so, just define a BULK_DELETE_RSRC, and the .delete class method
|
|
58
|
+
# will use it, rather than making multiple calls to delete individual
|
|
59
|
+
# items. See Jamf::Category::BULK_DELETE_RSRC for an example
|
|
60
|
+
#
|
|
61
|
+
# @abstract
|
|
62
|
+
#
|
|
63
|
+
class CollectionResource < Jamf::Resource
|
|
64
|
+
|
|
65
|
+
extend Jamf::Abstract
|
|
66
|
+
include Comparable
|
|
67
|
+
|
|
68
|
+
# Public Class Methods
|
|
69
|
+
#####################################
|
|
70
|
+
|
|
71
|
+
# @return [Array<Symbol>] the attribute names that are marked as identifiers
|
|
72
|
+
#
|
|
73
|
+
def self.identifiers
|
|
74
|
+
self::OBJECT_MODEL.select { |_attr, deets| deets[:identifier] }.keys
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# An array of attribute names that are required when
|
|
78
|
+
# making new CollectionResources
|
|
79
|
+
# See the OBJECT_MODEL documentation in {Jamf::JSONObject}
|
|
80
|
+
def self.required_attributes
|
|
81
|
+
self::OBJECT_MODEL.select { |_attr, deets| deets[:required] }.keys
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# The Collection members Array for this class, retrieved from
|
|
85
|
+
# the RSRC_PATH as Parsed JSON, but not instantiated into instances
|
|
86
|
+
# unless instantiate: is truthy.
|
|
87
|
+
#
|
|
88
|
+
# E.g. for {Jamf::Settings::Building}, this would be the Array of Hashes
|
|
89
|
+
# returned by GETing the resource .../settings/obj/building
|
|
90
|
+
#
|
|
91
|
+
# This Array is cached in the {Jamf::Connection} instance used to
|
|
92
|
+
# retrieve it, and future calls to .all will return the cached Array
|
|
93
|
+
# unless refresh is truthy.
|
|
94
|
+
#
|
|
95
|
+
# TODO: Investigate https://www.rubydoc.info/github/mloughran/api_cache
|
|
96
|
+
#
|
|
97
|
+
# @param refresh[Boolean] re-read the data from the API?
|
|
98
|
+
#
|
|
99
|
+
# @param cnx[Jamf::Connection] an API connection to use for the query.
|
|
100
|
+
# Defaults to the corrently active connection. See {Jamf::Connection}
|
|
101
|
+
#
|
|
102
|
+
# @param instantiate[Boolean] The Array contains instances of this class
|
|
103
|
+
# rather than the JSON Hashes from the API.
|
|
104
|
+
#
|
|
105
|
+
# @return [Array<Object>] An Array of all objects of this class in the JSS.
|
|
106
|
+
#
|
|
107
|
+
def self.all(refresh = false, cnx: Jamf.cnx, instantiate: false)
|
|
108
|
+
validate_not_abstract
|
|
109
|
+
cnx.collection_cache[self] = nil if refresh
|
|
110
|
+
return cnx.collection_cache[self] if cnx.collection_cache[self]
|
|
111
|
+
|
|
112
|
+
raw = cnx.get rsrc_path
|
|
113
|
+
cnx.collection_cache[self] =
|
|
114
|
+
if raw.is_a?(Hash) && raw[:results]
|
|
115
|
+
raw[:results]
|
|
116
|
+
else
|
|
117
|
+
raw
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
return cnx.collection_cache[self] unless instantiate
|
|
121
|
+
|
|
122
|
+
cnx.collection_cache[self].map { |m| new m }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# An array of the ids for all collection members
|
|
126
|
+
#
|
|
127
|
+
# @param refresh (see .all)
|
|
128
|
+
#
|
|
129
|
+
# @param cnx (see .all)
|
|
130
|
+
#
|
|
131
|
+
# @return [Array<Integer>]
|
|
132
|
+
#
|
|
133
|
+
def self.all_ids(refresh = false, cnx: Jamf.cnx)
|
|
134
|
+
all(refresh, cnx: cnx).map { |m| m[:id] }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# rubocop:disable Naming/UncommunicativeMethodParamName
|
|
138
|
+
|
|
139
|
+
# A Hash of all members of this collection where the keys are some
|
|
140
|
+
# identifier and values are any other attribute.
|
|
141
|
+
#
|
|
142
|
+
# @param ident [Symbol] An identifier of this Class, used as the key
|
|
143
|
+
# for the mapping Hash.
|
|
144
|
+
#
|
|
145
|
+
# @param to [Symbol] The attribute to which the ident will be mapped
|
|
146
|
+
#
|
|
147
|
+
# @param refresh (see .all)
|
|
148
|
+
#
|
|
149
|
+
# @param cnx (see .all)
|
|
150
|
+
#
|
|
151
|
+
# @return [Hash {Symbol: Object}] A Hash of identifier mapped to attribute
|
|
152
|
+
#
|
|
153
|
+
def self.map_all(ident, to:, cnx: Jamf.cnx, refresh: false)
|
|
154
|
+
raise Jamf::InvalidDataError, "No identifier #{ident} for class #{self}" unless
|
|
155
|
+
identifiers.include? ident
|
|
156
|
+
|
|
157
|
+
raise Jamf::NoSuchItemError, "No attribute #{to} for class #{self}" unless self::OBJECT_MODEL.key? to
|
|
158
|
+
|
|
159
|
+
list = all refresh, cnx: cnx
|
|
160
|
+
to_class = self::OBJECT_MODEL[to][:class]
|
|
161
|
+
mapped = list.map do |i|
|
|
162
|
+
[
|
|
163
|
+
i[ident],
|
|
164
|
+
to_class.is_a?(Symbol) ? i[to] : to_class.new(i[to])
|
|
165
|
+
]
|
|
166
|
+
end # do i
|
|
167
|
+
mapped.to_h
|
|
168
|
+
end
|
|
169
|
+
# rubocop:enable Naming/UncommunicativeMethodParamName
|
|
170
|
+
|
|
171
|
+
# Given any identfier value for this collection, return the valid
|
|
172
|
+
# id, or nil if there's no match for the given value.
|
|
173
|
+
#
|
|
174
|
+
# If you know the value is a certain identifier, e.g. a serial_number
|
|
175
|
+
# then you can specify the identifier, for a faster search:
|
|
176
|
+
#
|
|
177
|
+
# valid_id serial_number: 'AB12DE34' # => Int or nil
|
|
178
|
+
#
|
|
179
|
+
# If you don't know wich identifier you have, just pass the value and
|
|
180
|
+
# all identifiers are searched
|
|
181
|
+
#
|
|
182
|
+
# valid_id 'AB12DE34' # => Int or nil
|
|
183
|
+
# valid_id 'SomeComputerName' # => Int or nil
|
|
184
|
+
#
|
|
185
|
+
# When the value is a string, the seach is case-insensitive
|
|
186
|
+
#
|
|
187
|
+
# TODO: When 'Searchability' is more dialed in via the searchable
|
|
188
|
+
# mixin, which implements enpoints like 'POST /v1/search-mobile-devices'
|
|
189
|
+
# then use that before using the 'all' list.
|
|
190
|
+
#
|
|
191
|
+
# @param value [Object] A value to search for as an identifier.
|
|
192
|
+
#
|
|
193
|
+
# @param refresh[Boolean] Reload the list data from the API
|
|
194
|
+
#
|
|
195
|
+
# @param ident: [Symbol] Restrict the search to this identifier.
|
|
196
|
+
# E.g. if :serial_number, then the value must be
|
|
197
|
+
# a known serial number, it is not checked against other identifiers
|
|
198
|
+
#
|
|
199
|
+
# @param cnx: (see .all)
|
|
200
|
+
#
|
|
201
|
+
# @return [Object, nil] the primary identifier of the matching object,
|
|
202
|
+
# or nil if it doesn't exist
|
|
203
|
+
#
|
|
204
|
+
def self.valid_id(value = nil, refresh: true, cnx: Jamf.cnx, **ident_hash)
|
|
205
|
+
unless ident_hash.empty?
|
|
206
|
+
ident, value = ident_hash.first
|
|
207
|
+
return id_from_other_ident ident, value, refresh, cnx: cnx
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
# check the id itself first
|
|
211
|
+
return value if all_ids(refresh, cnx: cnx).include? value
|
|
212
|
+
|
|
213
|
+
idents = identifiers - [:id]
|
|
214
|
+
val_is_str = value.is_a? String
|
|
215
|
+
|
|
216
|
+
idents.each do |ident|
|
|
217
|
+
match = all(cnx: cnx).select do |m|
|
|
218
|
+
val_is_str ? m[ident].to_s.casecmp?(value) : m[ident] == value
|
|
219
|
+
end.first
|
|
220
|
+
return match[:id] if match
|
|
221
|
+
end # identifiers.each do |ident|
|
|
222
|
+
|
|
223
|
+
nil
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# Bu default, subclasses are creatable, i.e. new instances can be created
|
|
227
|
+
# with .create, and added to the JSS with .save
|
|
228
|
+
# If a subclass is NOT creatble for any reason, just add
|
|
229
|
+
# extend Jamf::UnCreatable
|
|
230
|
+
# and this method will return false
|
|
231
|
+
#
|
|
232
|
+
# @return [Boolean]
|
|
233
|
+
def self.creatable?
|
|
234
|
+
true
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
# Make a new thing to be added to the API
|
|
238
|
+
def self.create(params, cnx: Jamf.cnx)
|
|
239
|
+
raise Jamf::UnsupportedError, "#{self}'s are not currently creatable via the API" unless self.creatable?
|
|
240
|
+
|
|
241
|
+
validate_not_abstract
|
|
242
|
+
|
|
243
|
+
validate_required_attributes params
|
|
244
|
+
|
|
245
|
+
params.delete :id # no such animal when .creating
|
|
246
|
+
params[:creating_from_create] = true
|
|
247
|
+
new params, cnx: cnx
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# Retrieve a member of a CollectionResource from the API
|
|
251
|
+
#
|
|
252
|
+
# To create new members to be added to the JSS, use
|
|
253
|
+
# {Jamf::CollectionResource.create}
|
|
254
|
+
#
|
|
255
|
+
# If you know the specific identifier attribute you're looking up, e.g.
|
|
256
|
+
# :id or :name or :udid, (or an aliase thereof) then you can specify it like
|
|
257
|
+
# `.fetch name: 'somename'`, or `.fetch udid: 'someudid'`
|
|
258
|
+
#
|
|
259
|
+
# If you don't know if (or don't want to type it) you can just use
|
|
260
|
+
# `.fetch 'somename'`, or `.fetch 'someudid'` and all identifiers will be
|
|
261
|
+
# searched for a match.
|
|
262
|
+
#
|
|
263
|
+
# @param ident_value[Object] A value for any identifier for this subclass.
|
|
264
|
+
# All identifier attributes will be searched for a match.
|
|
265
|
+
#
|
|
266
|
+
# @param cnx[Jamf::Connection] the connection to use to fetch the object
|
|
267
|
+
#
|
|
268
|
+
# @param ident_hash[Hash] an identifier attribute key and a search value
|
|
269
|
+
#
|
|
270
|
+
# @return [CollectionResource] The ruby-instance of a Jamf object
|
|
271
|
+
#
|
|
272
|
+
def self.fetch(ident_value = nil, cnx: Jamf.cnx, **ident_hash)
|
|
273
|
+
validate_not_abstract
|
|
274
|
+
id =
|
|
275
|
+
if ident_value == :random
|
|
276
|
+
all_ids.sample
|
|
277
|
+
elsif ident_value
|
|
278
|
+
valid_id ident_value
|
|
279
|
+
elsif ident_hash.empty?
|
|
280
|
+
nil
|
|
281
|
+
else
|
|
282
|
+
ident, lookup_value = ident_hash.first
|
|
283
|
+
valid_id ident => lookup_value
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
raise Jamf::NoSuchItemError, "No matching #{self}" unless id
|
|
287
|
+
|
|
288
|
+
data = cnx.get "#{rsrc_path}/#{id}"
|
|
289
|
+
new data, cnx: cnx
|
|
290
|
+
end # fetch
|
|
291
|
+
|
|
292
|
+
# By default, CollectionResource subclass instances are deletable.
|
|
293
|
+
# If not, just extend the subclass with Jamf::UnDeletable, and this
|
|
294
|
+
# will return false, and .delete & #delete will raise errors
|
|
295
|
+
def self.deletable?
|
|
296
|
+
true
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Delete one or more objects by identifier
|
|
300
|
+
# Any valid identifier for the class can be used (id, name, udid, etc)
|
|
301
|
+
# Identifiers can be provided as an array or as separate parameters
|
|
302
|
+
#
|
|
303
|
+
# e.g. .delete [1,3, 34, 4]
|
|
304
|
+
# or .delete 'myComputer', 'that-computer', 'OtherComputer'
|
|
305
|
+
#
|
|
306
|
+
# @param idents[Array<integer>, Integer]
|
|
307
|
+
#
|
|
308
|
+
# @param cnx[Jamf::Connection]
|
|
309
|
+
#
|
|
310
|
+
# @return [Array] the identifiers that were not found, so couldn't be deleted
|
|
311
|
+
#
|
|
312
|
+
def self.delete(*idents, cnx: Jamf.cnx)
|
|
313
|
+
raise Jamf::UnsupportedError, "Deleting #{self} objects is not currently supported" unless deletable?
|
|
314
|
+
|
|
315
|
+
idents.flatten!
|
|
316
|
+
no_valid_ids = []
|
|
317
|
+
|
|
318
|
+
idents.map do |ident|
|
|
319
|
+
id = valid_id ident
|
|
320
|
+
no_valid_ids << ident unless id
|
|
321
|
+
id
|
|
322
|
+
end
|
|
323
|
+
idents.compact!
|
|
324
|
+
|
|
325
|
+
# TODO: some rsrcs have a 'bulk delete' version...
|
|
326
|
+
idents.each { |id| cnx.delete "#{rsrc_path}/#{id}" }
|
|
327
|
+
|
|
328
|
+
no_valid_ids
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
# Private Class Methods
|
|
332
|
+
#####################################
|
|
333
|
+
|
|
334
|
+
# TODO: better pluralizing?
|
|
335
|
+
#
|
|
336
|
+
def self.create_list_methods(attr_name, attr_def)
|
|
337
|
+
list_method_name = "all_#{attr_name}s"
|
|
338
|
+
|
|
339
|
+
define_singleton_method(list_method_name) do |refresh = false, cnx: Jamf.cnx|
|
|
340
|
+
all_list = all(refresh, cnx: cnx)
|
|
341
|
+
if attr_def[:class].is_a? Symbol
|
|
342
|
+
all_list.map { |i| i[attr_name] }.uniq
|
|
343
|
+
else
|
|
344
|
+
all_list.map { |i| attr_def[:class].new i[attr_name] }
|
|
345
|
+
end
|
|
346
|
+
end # define_singleton_method
|
|
347
|
+
|
|
348
|
+
return unless attr_def[:aliases]
|
|
349
|
+
|
|
350
|
+
# aliases - TODO: is there a more elegant way?
|
|
351
|
+
attr_def[:aliases].each do |a|
|
|
352
|
+
define_singleton_method("all_#{a}s") do |refresh = false, cnx: Jamf.cnx|
|
|
353
|
+
send list_method_name, refresh, cnx: cnx
|
|
354
|
+
end # define_singleton_method
|
|
355
|
+
end # each alias
|
|
356
|
+
end # create_list_methods
|
|
357
|
+
private_class_method :create_list_methods
|
|
358
|
+
|
|
359
|
+
# validate that our .create data has the required attribute values.
|
|
360
|
+
# They can't be nil or empty.
|
|
361
|
+
#
|
|
362
|
+
def self.validate_required_attributes(data)
|
|
363
|
+
required_attributes.each do |atr|
|
|
364
|
+
raise Jamf::MissingDataError, "Required attribute '#{atr}:' may not be nil or empty" if data[atr].to_s.empty?
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
private_class_method :validate_required_attributes
|
|
368
|
+
|
|
369
|
+
# Given an indentier attr. key, and a value,
|
|
370
|
+
# return the id where that ident has that value, or nil
|
|
371
|
+
#
|
|
372
|
+
def self.id_from_other_ident(ident, value, refresh = true, cnx: Jamf.cnx)
|
|
373
|
+
raise ArgumentError, "Unknown identifier '#{ident}' for #{self}" unless identifiers.include? ident
|
|
374
|
+
|
|
375
|
+
# check the id itself first
|
|
376
|
+
return value if ident == :id && all_ids(refresh, cnx: cnx).include?(value)
|
|
377
|
+
|
|
378
|
+
# all ident values => ids
|
|
379
|
+
ident_map = map_all(ident, to: :id, cnx: cnx, refresh: refresh)
|
|
380
|
+
|
|
381
|
+
# case-insensitivity for string values
|
|
382
|
+
value = ident_map.keys.j_ci_fetch_string(value) if value.is_a? String
|
|
383
|
+
|
|
384
|
+
ident_map[value]
|
|
385
|
+
end
|
|
386
|
+
private_class_method :id_from_other_ident
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
# Instance Methods
|
|
390
|
+
#####################################
|
|
391
|
+
|
|
392
|
+
def exist?
|
|
393
|
+
!@id.nil?
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
def rsrc_path
|
|
397
|
+
return unless exist?
|
|
398
|
+
"#{self.class.rsrc_path}/#{@id}"
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
def delete
|
|
402
|
+
raise Jamf::UnsupportedError, "Deleting #{self} objects is not currently supported" unless self.class.deletable?
|
|
403
|
+
@cnx.delete rsrc_path
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Two collection resource objects are the same if their id's are the same
|
|
407
|
+
def <=>(other)
|
|
408
|
+
id <=> other.id
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
# Private Instance Methods
|
|
412
|
+
############################################
|
|
413
|
+
private
|
|
414
|
+
|
|
415
|
+
def create_in_jamf
|
|
416
|
+
result = @cnx.post self.class.rsrc_path, to_jamf
|
|
417
|
+
@id = result[:id]
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
end # class CollectionResource
|
|
421
|
+
|
|
422
|
+
end # module JAMF
|