ruby-jss 0.7.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ruby-jss might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGES.md +29 -22
- data/README.md +66 -86
- data/bin/jamfHelperBackgrounder +148 -0
- data/bin/netseg-update +0 -1
- data/lib/jss.rb +20 -9
- data/lib/jss/api_connection.rb +369 -295
- data/lib/jss/api_object.rb +651 -418
- data/lib/jss/api_object/account.rb +69 -77
- data/lib/jss/api_object/advanced_search.rb +201 -236
- data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +42 -42
- data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +33 -43
- data/lib/jss/api_object/advanced_search/advanced_user_search.rb +33 -43
- data/lib/jss/api_object/building.rb +39 -52
- data/lib/jss/api_object/categorizable.rb +221 -0
- data/lib/jss/api_object/category.rb +81 -89
- data/lib/jss/api_object/computer.rb +486 -525
- data/lib/jss/api_object/computer_invitation.rb +73 -86
- data/lib/jss/api_object/criteriable.rb +6 -7
- data/lib/jss/api_object/ebook.rb +21 -0
- data/lib/jss/api_object/extendable.rb +6 -8
- data/lib/jss/api_object/group.rb +0 -3
- data/lib/jss/api_object/locatable.rb +19 -20
- data/lib/jss/api_object/mac_application.rb +21 -0
- data/lib/jss/api_object/mobile_device.rb +30 -21
- data/lib/jss/api_object/mobile_device_application.rb +447 -0
- data/lib/jss/api_object/mobile_device_configuration_profile.rb +21 -0
- data/lib/jss/api_object/osx_configuration_profile.rb +0 -3
- data/lib/jss/api_object/package.rb +21 -34
- data/lib/jss/api_object/peripheral.rb +16 -18
- data/lib/jss/api_object/policy.rb +5 -83
- data/lib/jss/api_object/purchasable.rb +11 -13
- data/lib/jss/api_object/scopable.rb +11 -12
- data/lib/jss/api_object/script.rb +3 -17
- data/lib/jss/api_object/self_servable.rb +419 -205
- data/lib/jss/api_object/self_servable/icon.rb +179 -0
- data/lib/jss/api_object/updatable.rb +35 -34
- data/lib/jss/api_object/uploadable.rb +72 -70
- data/lib/jss/api_object/user.rb +6 -7
- data/lib/jss/api_object/vppable.rb +117 -0
- data/lib/jss/client.rb +264 -225
- data/lib/jss/db_connection.rb +7 -5
- data/lib/jss/exceptions.rb +50 -42
- data/lib/jss/ruby_extensions.rb +8 -7
- data/lib/jss/ruby_extensions/object.rb +19 -0
- data/lib/jss/utility.rb +82 -40
- data/lib/jss/version.rb +1 -1
- metadata +37 -68
- data/bin/jss-webhook-server +0 -3
- data/lib/jss/webhooks.rb +0 -53
- data/lib/jss/webhooks/README.md +0 -269
- data/lib/jss/webhooks/configuration.rb +0 -213
- data/lib/jss/webhooks/data/sample_handlers/RestAPIOperation-executable +0 -91
- data/lib/jss/webhooks/data/sample_handlers/RestAPIOperation.rb +0 -45
- data/lib/jss/webhooks/data/sample_jsons/ComputerAdded.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerCheckIn.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerInventoryCompleted.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerPolicyFinished.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/ComputerPushCapabilityChanged.json +0 -27
- data/lib/jss/webhooks/data/sample_jsons/JSSShutdown.json +0 -14
- data/lib/jss/webhooks/data/sample_jsons/JSSStartup.json +0 -14
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceCheckIn.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceCommandCompleted.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceEnrolled.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDevicePushSent.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/MobileDeviceUnEnrolled.json +0 -26
- data/lib/jss/webhooks/data/sample_jsons/PatchSoftwareTitleUpdated.json +0 -14
- data/lib/jss/webhooks/data/sample_jsons/PushSent.json +0 -11
- data/lib/jss/webhooks/data/sample_jsons/RestAPIOperation.json +0 -15
- data/lib/jss/webhooks/data/sample_jsons/SCEPChallenge.json +0 -10
- data/lib/jss/webhooks/data/sample_jsons/SmartGroupComputerMembershipChange.json +0 -13
- data/lib/jss/webhooks/data/sample_jsons/SmartGroupMobileDeviceMembershipChange.json +0 -13
- data/lib/jss/webhooks/event.rb +0 -139
- data/lib/jss/webhooks/event/computer_added.rb +0 -38
- data/lib/jss/webhooks/event/computer_check_in.rb +0 -38
- data/lib/jss/webhooks/event/computer_inventory_completed.rb +0 -38
- data/lib/jss/webhooks/event/computer_policy_finished.rb +0 -38
- data/lib/jss/webhooks/event/computer_push_capability_changed.rb +0 -38
- data/lib/jss/webhooks/event/handlers.rb +0 -192
- data/lib/jss/webhooks/event/jss_shutdown.rb +0 -38
- data/lib/jss/webhooks/event/jss_startup.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_check_in.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_command_completed.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_enrolled.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_push_sent.rb +0 -38
- data/lib/jss/webhooks/event/mobile_device_unenrolled.rb +0 -38
- data/lib/jss/webhooks/event/patch_software_title_updated.rb +0 -38
- data/lib/jss/webhooks/event/push_sent.rb +0 -38
- data/lib/jss/webhooks/event/rest_api_operation.rb +0 -38
- data/lib/jss/webhooks/event/scep_challenge.rb +0 -38
- data/lib/jss/webhooks/event/smart_group_computer_membership_change.rb +0 -38
- data/lib/jss/webhooks/event/smart_group_mobile_device_membership_change.rb +0 -38
- data/lib/jss/webhooks/event/webhook.rb +0 -40
- data/lib/jss/webhooks/event_objects.rb +0 -112
- data/lib/jss/webhooks/event_objects/computer.rb +0 -49
- data/lib/jss/webhooks/event_objects/jss.rb +0 -36
- data/lib/jss/webhooks/event_objects/mobile_device.rb +0 -48
- data/lib/jss/webhooks/event_objects/patch_software_title_update.rb +0 -38
- data/lib/jss/webhooks/event_objects/push.rb +0 -33
- data/lib/jss/webhooks/event_objects/rest_api_operation.rb +0 -37
- data/lib/jss/webhooks/event_objects/scep_challenge.rb +0 -32
- data/lib/jss/webhooks/event_objects/smart_group.rb +0 -35
- data/lib/jss/webhooks/server_app.rb +0 -37
- data/lib/jss/webhooks/server_app/routes.rb +0 -27
- data/lib/jss/webhooks/server_app/routes/handle_webhook_event.rb +0 -39
- data/lib/jss/webhooks/server_app/routes/home.rb +0 -37
- data/lib/jss/webhooks/server_app/self_signed_cert.rb +0 -65
- data/lib/jss/webhooks/server_app/server.rb +0 -60
- data/lib/jss/webhooks/version.rb +0 -32
data/lib/jss/api_object.rb
CHANGED
@@ -26,139 +26,139 @@
|
|
26
26
|
###
|
27
27
|
module JSS
|
28
28
|
|
29
|
-
|
29
|
+
# Module Variables
|
30
30
|
#####################################
|
31
31
|
|
32
|
-
|
32
|
+
# Module Methods
|
33
33
|
#####################################
|
34
34
|
|
35
|
-
|
35
|
+
# Classes
|
36
36
|
#####################################
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
38
|
+
# This class is the parent to all JSS API objects. It provides standard methods and structures
|
39
|
+
# that apply to all API resouces.
|
40
|
+
#
|
41
|
+
# See the README.md file for general info about using subclasses of JSS::APIObject
|
42
|
+
#
|
43
|
+
# == Subclassing
|
44
|
+
#
|
45
|
+
# === Constructor
|
46
|
+
#
|
47
|
+
# In general, subclasses should do any class-specific argument checking before
|
48
|
+
# calling super, and then afterwards, use the contents of @init_data to populate
|
49
|
+
# any class-specific attributes. @id, @name, @rest_rsrc, and @in_jss are handled here.
|
50
|
+
#
|
51
|
+
# If a subclass can be looked up by some key other than :name or :id, the subclass must
|
52
|
+
# pass the keys as an Array in the second argument when calling super from #initialize.
|
53
|
+
# See {JSS::Computer#initialize} for an example of how to implement this feature.
|
54
|
+
#
|
55
|
+
# === Object Creation
|
56
|
+
#
|
57
|
+
# If a subclass should be able to be created in the JSS be sure to include {JSS::Creatable}
|
58
|
+
#
|
59
|
+
# The constructor should verify any extra required data (aside from :name) in the args before or after
|
60
|
+
# calling super.
|
61
|
+
#
|
62
|
+
# See {JSS::Creatable} for more details.
|
63
|
+
#
|
64
|
+
# === Object Modification
|
65
|
+
#
|
66
|
+
# If a subclass should be modifiable in the JSS, include {JSS::Updatable}, q.v. for details.
|
67
|
+
#
|
68
|
+
# === Object Deletion
|
69
|
+
#
|
70
|
+
# All subclasses can be deleted in the JSS.
|
71
|
+
#
|
72
|
+
# === Required Constants
|
73
|
+
#
|
74
|
+
# Subclasses *must* provide certain Constants in order to correctly interpret API data and
|
75
|
+
# communicate with the API.
|
76
|
+
#
|
77
|
+
# ==== RSRC_BASE = [String], The base for REST resources of this class
|
78
|
+
#
|
79
|
+
# e.g. 'computergroups' in "https://casper.mycompany.com:8443/JSSResource/computergroups/id/12"
|
80
|
+
#
|
81
|
+
# ==== RSRC_LIST_KEY = [Symbol] The Hash key for the JSON list output of all objects of this class in the JSS.
|
82
|
+
#
|
83
|
+
# e.g. the JSON output of resource "JSSResource/computergroups" is a hash
|
84
|
+
# with one item (an Array of computergroups). That item's key is the Symbol :computer_groups
|
85
|
+
#
|
86
|
+
# ==== RSRC_OBJECT_KEY = [Symbol] The Hash key used for individual JSON object output.
|
87
|
+
# It's also used in various error messages
|
88
|
+
#
|
89
|
+
# e.g. the JSON output of the resource "JSSResource/computergroups/id/436" is
|
90
|
+
# a hash with one item (another hash with details of one computergroup).
|
91
|
+
# That item's key is the Symbol :computer_group
|
92
|
+
#
|
93
|
+
# ==== VALID_DATA_KEYS = [Array<Symbol>] The Hash keys used to verify validity of :data
|
94
|
+
# When instantiating a subclass using :data => somehash, some minimal checks are performed
|
95
|
+
# to ensure the data is valid for the subclass
|
96
|
+
#
|
97
|
+
# The Symbols in this Array are compared to the keys of the hash provided.
|
98
|
+
# If any of these don't exist in the hash's keys, then the :data is
|
99
|
+
# not valid and an exception is raised.
|
100
|
+
#
|
101
|
+
# The keys :id and :name must always exist in the hash.
|
102
|
+
# If only :id and :name are valid, VALID_DATA_KEYS should be an empty array.
|
103
|
+
#
|
104
|
+
# e.g. for a department, only :id and :name are valid, so VALID_DATA_KEYS is an empty Array ([])
|
105
|
+
# but for a computer group, the keys :computers and :is_smart must be present as well.
|
106
|
+
# so VALID_DATA_KEYS will be [:computers, :is_smart]
|
107
|
+
#
|
108
|
+
# *NOTE* Some API objects have data broken into subsections, in which case the
|
109
|
+
# VALID_DATA_KEYS are expected in the section :general.
|
110
|
+
#
|
111
111
|
class APIObject
|
112
112
|
|
113
|
-
|
113
|
+
# Mix-Ins
|
114
114
|
#####################################
|
115
115
|
|
116
|
-
|
116
|
+
# Class Variables
|
117
117
|
#####################################
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
119
|
+
# This Hash holds the most recent API query for a list of all items in any subclass,
|
120
|
+
# keyed by the subclass's RSRC_LIST_KEY. See the self.all class method.
|
121
|
+
#
|
122
|
+
# When the .all method is called without an argument, and this hash has
|
123
|
+
# a matching value, the value is returned, rather than requerying the
|
124
|
+
# API. The first time a class calls .all, or whnever refresh is
|
125
|
+
# not false, the API is queried and the value in this hash is updated.
|
126
|
+
#
|
127
127
|
@@all_items = {}
|
128
128
|
|
129
|
-
|
129
|
+
# Class Methods
|
130
130
|
#####################################
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
132
|
+
# Return an Array of Hashes for all objects of this subclass in the JSS.
|
133
|
+
#
|
134
|
+
# This method is only valid in subclasses of JSS::APIObject, and is
|
135
|
+
# the parsed JSON output of an API query for the resource defined in the subclass's RSRC_BASE,
|
136
|
+
# e.g. for JSS::Computer, with the RSRC_BASE of :computers,
|
137
|
+
# This method retuens the output of the 'JSSResource/computers' resource,
|
138
|
+
# which is a list of all computers in the JSS.
|
139
|
+
#
|
140
|
+
# Each item in the Array is a Hash with at least two keys, :id and :name.
|
141
|
+
# The class methods .all_ids and .all_names provide easier access to those data
|
142
|
+
# as mapped Arrays.
|
143
|
+
#
|
144
|
+
# Some API classes provide other data in each Hash, e.g. :udid (for computers
|
145
|
+
# and mobile devices) or :is_smart (for groups).
|
146
|
+
#
|
147
|
+
# Subclasses implementing those API classes should provide .all_xxx
|
148
|
+
# class methods for accessing those other values as mapped Arrays,
|
149
|
+
# e.g. JSS::Computer.all_udids
|
150
|
+
#
|
151
|
+
# The results of the first query for each subclass is stored in @@all_items
|
152
|
+
# and returned at every future call, so as to not requery the server every time.
|
153
|
+
#
|
154
|
+
# To force requerying to get updated data, provided a non-false argument.
|
155
|
+
# I usually use :refresh, so that it's obvious what I'm doing, but true, 1,
|
156
|
+
# or anything besides false or nil will work.
|
157
|
+
#
|
158
|
+
# @param refresh[Boolean] should the data be re-queried from the API?
|
159
|
+
#
|
160
|
+
# @return [Array<Hash{:name=>String, :id=> Integer}>]
|
161
|
+
#
|
162
162
|
def self.all(refresh = false)
|
163
163
|
raise JSS::UnsupportedError, '.all can only be called on subclasses of JSS::APIObject' if self == JSS::APIObject
|
164
164
|
@@all_items[self::RSRC_LIST_KEY] = nil if refresh
|
@@ -166,92 +166,92 @@ module JSS
|
|
166
166
|
@@all_items[self::RSRC_LIST_KEY] = JSS::API.get_rsrc(self::RSRC_BASE)[self::RSRC_LIST_KEY]
|
167
167
|
end
|
168
168
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
169
|
+
# Returns an Array of the JSS id numbers of all the members
|
170
|
+
# of the subclass.
|
171
|
+
#
|
172
|
+
# e.g. When called from subclass JSS::Computer,
|
173
|
+
# returns the id's of all computers in the JSS
|
174
|
+
#
|
175
|
+
# @param refresh[Boolean] should the data be re-queried from the API?
|
176
|
+
#
|
177
|
+
# @return [Array<Integer>] the ids of all items of this subclass in the JSS
|
178
|
+
#
|
179
179
|
def self.all_ids(refresh = false)
|
180
180
|
all(refresh).map { |i| i[:id] }
|
181
181
|
end
|
182
182
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
183
|
+
# Returns an Array of the JSS names of all the members
|
184
|
+
# of the subclass.
|
185
|
+
#
|
186
|
+
# e.g. When called from subclass JSS::Computer,
|
187
|
+
# returns the names of all computers in the JSS
|
188
|
+
#
|
189
|
+
# @param refresh[Boolean] should the data be re-queried from the API?
|
190
|
+
#
|
191
|
+
# @return [Array<String>] the names of all item of this subclass in the JSS
|
192
|
+
#
|
193
193
|
def self.all_names(refresh = false)
|
194
194
|
all(refresh).map { |i| i[:name] }
|
195
195
|
end
|
196
196
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
197
|
+
# Return a hash of all objects of this subclass
|
198
|
+
# in the JSS where the key is the id, and the value
|
199
|
+
# is some other key in the data items returned by the JSS::APIObject.all.
|
200
|
+
#
|
201
|
+
# If the other key doesn't exist in the API
|
202
|
+
# data, (eg :udid for JSS::Department) the values will be nil.
|
203
|
+
#
|
204
|
+
# Use this method to map ID numbers to other identifiers returned
|
205
|
+
# by the API list resources. Invert its result to map the other
|
206
|
+
# identfier to ids.
|
207
|
+
#
|
208
|
+
# @example
|
209
|
+
# JSS::Computer.map_all_ids_to(:name)
|
210
|
+
#
|
211
|
+
# # Returns, eg {2 => "kimchi", 5 => "mantis"}
|
212
|
+
#
|
213
|
+
# JSS::Computer.map_all_ids_to(:name).invert
|
214
|
+
#
|
215
|
+
# # Returns, eg {"kimchi" => 2, "mantis" => 5}
|
216
|
+
#
|
217
|
+
# @param other_key[Symbol] the other data key with which to associate each id
|
218
|
+
#
|
219
|
+
# @param refresh[Boolean] should the data re-queried from the API?
|
220
|
+
#
|
221
|
+
# @return [Hash{Integer => Oject}] the associated ids and data
|
222
|
+
#
|
223
223
|
def self.map_all_ids_to(other_key, refresh = false)
|
224
224
|
h = {}
|
225
225
|
all(refresh).each { |i| h[i[:id]] = i[other_key] }
|
226
226
|
h
|
227
227
|
end
|
228
228
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
229
|
+
# Return an Array of JSS::APIObject subclass instances
|
230
|
+
# e.g when called on JSS::Package, return all JSS::Package
|
231
|
+
# objects in the JSS.
|
232
|
+
#
|
233
|
+
# NOTE: This may be slow as it has to look up each object individually!
|
234
|
+
# use it wisely.
|
235
|
+
#
|
236
|
+
# @param refresh[Boolean] should the data re-queried from the API?
|
237
|
+
#
|
238
|
+
# @return [Hash{Integer => Object}] the objects requested
|
239
239
|
def self.all_objects(refresh = false)
|
240
240
|
objects_key = "#{self::RSRC_LIST_KEY}_objects".to_sym
|
241
241
|
@@all_items[objects_key] = nil if refresh
|
242
242
|
return @@all_items[objects_key] if @@all_items[objects_key]
|
243
|
-
@@all_items[objects_key] = all(refresh
|
244
|
-
end
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
243
|
+
@@all_items[objects_key] = all(refresh).map { |o| new id: o[:id] }
|
244
|
+
end
|
245
|
+
|
246
|
+
# Return true or false if an object of this subclass
|
247
|
+
# with the given name or id exists on the server
|
248
|
+
#
|
249
|
+
# @param identfier [String,Integer] The name or id of object to check for
|
250
|
+
#
|
251
|
+
# @param refresh [Boolean] Should the data be re-read from the server
|
252
|
+
#
|
253
|
+
# @return [Boolean] does an object with the given name or id exist?
|
254
|
+
#
|
255
255
|
def self.exist?(identfier, refresh = false)
|
256
256
|
case identfier
|
257
257
|
when Integer
|
@@ -263,18 +263,18 @@ module JSS
|
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
266
|
+
# Return an id or nil if an object of this subclass
|
267
|
+
# with the given name or id exists on the server
|
268
|
+
#
|
269
|
+
# Subclasses may want to override this method to support more
|
270
|
+
# identifiers than name and id.
|
271
|
+
#
|
272
|
+
# @param identfier [String,Integer] The name or id of object to check for
|
273
|
+
#
|
274
|
+
# @param refresh [Boolean] Should the data be re-read from the server
|
275
|
+
#
|
276
|
+
# @return [Integer, nil] the id of the matching object, or nil if it doesn't exist
|
277
|
+
#
|
278
278
|
def self.valid_id(identfier, refresh = false)
|
279
279
|
case identfier
|
280
280
|
when Integer
|
@@ -286,78 +286,77 @@ module JSS
|
|
286
286
|
end
|
287
287
|
end
|
288
288
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
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
|
-
|
330
|
-
|
289
|
+
# Convert an Array of Hashes of API object data to a
|
290
|
+
# REXML element.
|
291
|
+
#
|
292
|
+
# Given an Array of Hashes of items in the subclass
|
293
|
+
# where each Hash has at least an :id or a :name key,
|
294
|
+
# (as what comes from the .all class method)
|
295
|
+
# return a REXML <classes> element
|
296
|
+
# with one <class> element per Hash member.
|
297
|
+
#
|
298
|
+
# @example
|
299
|
+
# # for class JSS::Computer
|
300
|
+
# some_comps = [{:id=>2, :name=>"kimchi"},{:id=>5, :name=>"mantis"}]
|
301
|
+
# xml_names = JSS::Computer.xml_list some_comps
|
302
|
+
# puts xml_names # output manually formatted for clarity, xml.to_s has no newlines between elements
|
303
|
+
#
|
304
|
+
# <computers>
|
305
|
+
# <computer>
|
306
|
+
# <name>kimchi</name>
|
307
|
+
# </computer>
|
308
|
+
# <computer>
|
309
|
+
# <name>mantis</name>
|
310
|
+
# </computer>
|
311
|
+
# </computers>
|
312
|
+
#
|
313
|
+
# xml_ids = JSS::Computer.xml_list some_comps, :id
|
314
|
+
# puts xml_names # output manually formatted for clarity, xml.to_s has no newlines between elements
|
315
|
+
#
|
316
|
+
# <computers>
|
317
|
+
# <computer>
|
318
|
+
# <id>2</id>
|
319
|
+
# </computer>
|
320
|
+
# <computer>
|
321
|
+
# <id>5</id>
|
322
|
+
# </computer>
|
323
|
+
# </computers>
|
324
|
+
#
|
325
|
+
# @param array[Array<Hash{:name=>String, :id =>Integer, Symbol=>#to_s}>] the Array of subclass data to convert
|
326
|
+
#
|
327
|
+
# @param content[Symbol] the Hash key to use as the inner element for each member of the Array
|
328
|
+
#
|
329
|
+
# @return [REXML::Element] the XML element representing the data
|
330
|
+
#
|
331
331
|
def self.xml_list(array, content = :name)
|
332
332
|
JSS.item_list_to_rexml_list self::RSRC_LIST_KEY, self::RSRC_OBJECT_KEY, array, content
|
333
333
|
end
|
334
334
|
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
###
|
335
|
+
# Some API objects contain references to other API objects. Usually those
|
336
|
+
# references are a Hash containing the :id and :name of the target. Sometimes,
|
337
|
+
# however the reference is just the name of the target.
|
338
|
+
#
|
339
|
+
# A Script has a property :category, which comes from the API as
|
340
|
+
# a String, the name of the category for that script. e.g. "GoodStuff"
|
341
|
+
#
|
342
|
+
# A Policy also has a property :category, but it comes from the API as a Hash
|
343
|
+
# with both the name and id, e.g. !{:id => 8, :name => "GoodStuff"}
|
344
|
+
#
|
345
|
+
# When that reference is to a single thing (like the category to which something belongs)
|
346
|
+
# APIObject subclasses usually store only the name, and use the name when
|
347
|
+
# returning data to the API.
|
348
|
+
#
|
349
|
+
# When an object references a list of related objects
|
350
|
+
# (like the computers assigned to a user) that list will be and Array of Hashes
|
351
|
+
# as above, with both the :id and :name
|
352
|
+
#
|
353
|
+
# This method is just a handy way to extract the name regardless of how it comes
|
354
|
+
# from the API. Most APIObject subclasses use it in their #initialize method
|
355
|
+
#
|
356
|
+
# @param a_thing[String,Array] the api data from which we're extracting the name
|
357
|
+
#
|
358
|
+
# @return [String] the name extracted from a_thing
|
359
|
+
#
|
361
360
|
def self.get_name(a_thing)
|
362
361
|
case a_thing
|
363
362
|
when String
|
@@ -369,194 +368,232 @@ module JSS
|
|
369
368
|
end
|
370
369
|
end
|
371
370
|
|
371
|
+
# Retrieve an object from the API.
|
372
|
+
#
|
373
|
+
# This is the preferred way to retrieve existing objects from the JSS.
|
374
|
+
# It's a wrapper for using APIObject.new
|
375
|
+
# and avoids the confusion of using ruby's .new class method when you're not
|
376
|
+
# creating a new object.
|
377
|
+
#
|
378
|
+
# For creating new objects in the JSS, use {APIObject.make}
|
379
|
+
#
|
380
|
+
# @param args[Hash] The data for fetching an object, such as id: or name:
|
381
|
+
# See {APIObject#initialize}
|
382
|
+
#
|
383
|
+
# @return [APIObject] The ruby-instance of a JSS object
|
384
|
+
#
|
385
|
+
def self.fetch(**args)
|
386
|
+
raise JSS::UnsupportedError, 'JSS::APIObject cannot be instantiated' if self.class == JSS::APIObject
|
387
|
+
raise ArgumentError, 'Use .create to create new JSS objects' if args[:id] == :new
|
388
|
+
new args
|
389
|
+
end
|
390
|
+
|
391
|
+
# Make a ruby instance of a not-yet-existing APIObject.
|
392
|
+
#
|
393
|
+
# This is the preferred way to create new objects in the JSS.
|
394
|
+
# It's a wrapper for using APIObject.new with the 'id: :new' parameter.
|
395
|
+
# and helps avoid the confusion of using ruby's .new class method for making
|
396
|
+
# ruby instances.
|
397
|
+
#
|
398
|
+
# For retrieving existing objects in the JSS, use {APIObject.fetch}
|
399
|
+
#
|
400
|
+
# For actually creating the object in the JSS, see {APIObject#create}
|
401
|
+
#
|
402
|
+
# @param args[Hash] The data for creating an object, such as name:
|
403
|
+
# See {APIObject#initialize}
|
404
|
+
#
|
405
|
+
# @return [APIObject] The un-created ruby-instance of a JSS object
|
406
|
+
#
|
407
|
+
def self.make(**args)
|
408
|
+
raise JSS::UnsupportedError, 'JSS::APIObject cannot be instantiated' if self.class == JSS::APIObject
|
409
|
+
raise ArgumentError, "Use '#{self.class}.fetch id: xx' to retrieve existing JSS objects" if args[:id]
|
410
|
+
args[:id] = :new
|
411
|
+
new args
|
412
|
+
end
|
413
|
+
|
414
|
+
|
372
415
|
### Class Constants
|
373
416
|
#####################################
|
374
417
|
|
375
|
-
|
376
|
-
|
377
|
-
|
418
|
+
# These Symbols are added to VALID_DATA_KEYS for performing the
|
419
|
+
# :data validity test described above.
|
420
|
+
#
|
378
421
|
REQUIRED_DATA_KEYS = [:id, :name].freeze
|
379
422
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
423
|
+
# By default, these keys are available for object lookups
|
424
|
+
# Others can be added by subclasses using an array of them
|
425
|
+
# as the second argument to super(initialize)
|
426
|
+
# The keys must be Symbols that match the keyname in the resource url.
|
427
|
+
# e.g. :serialnumber for JSSResource/computers/serialnumber/xxxxx
|
428
|
+
#
|
386
429
|
DEFAULT_LOOKUP_KEYS = [:id, :name].freeze
|
387
430
|
|
388
|
-
|
431
|
+
# Attributes
|
389
432
|
#####################################
|
390
433
|
|
391
|
-
|
434
|
+
# @return [Integer] the JSS id number
|
392
435
|
attr_reader :id
|
393
436
|
|
394
|
-
|
437
|
+
# @return [String] the name
|
395
438
|
attr_reader :name
|
396
439
|
|
397
|
-
|
440
|
+
# @return [Boolean] is it in the JSS?
|
398
441
|
attr_reader :in_jss
|
399
442
|
|
400
|
-
|
443
|
+
# @return [String] the Rest resource for API access (the part after "JSSResource/" )
|
401
444
|
attr_reader :rest_rsrc
|
402
445
|
|
403
|
-
|
446
|
+
# Constructor
|
404
447
|
#####################################
|
405
448
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
449
|
+
# The args hash must include :id, :name, or :data.
|
450
|
+
# * :id or :name will be looked up via the API
|
451
|
+
# * * if the subclass includes JSS::Creatable, :id can be :new, to create a new object in the JSS.
|
452
|
+
# and :name is required
|
453
|
+
# * :data must be the JSON output of a separate {JSS::APIConnection} query (a Hash of valid object data)
|
454
|
+
#
|
455
|
+
# Some subclasses can accept other options, by pasing their keys in a final Array
|
456
|
+
#
|
457
|
+
# @param args[Hash] the data for looking up, or constructing, a new object.
|
458
|
+
#
|
459
|
+
# @option args :id[Integer] the jss id to look up
|
460
|
+
#
|
461
|
+
# @option args :name[String] the name to look up
|
462
|
+
#
|
463
|
+
# @option args :data[Hash] the JSON output of a separate {JSS::APIConnection} query
|
464
|
+
#
|
465
|
+
# @param other_lookup_keys[Array<Symbol>] Hash keys other than :id and :name, by which an API
|
466
|
+
# lookup may be performed.
|
467
|
+
#
|
425
468
|
def initialize(args = {}, other_lookup_keys = [])
|
469
|
+
args[:other_lookup_keys] ||= other_lookup_keys
|
470
|
+
|
471
|
+
raise JSS::UnsupportedError, 'JSS::APIObject cannot be instantiated' if self.class == JSS::APIObject
|
472
|
+
|
473
|
+
### what lookup key are we using, if any?
|
474
|
+
lookup_keys = DEFAULT_LOOKUP_KEYS
|
475
|
+
lookup_keys += self.class::OTHER_LOOKUP_KEYS if defined? self.class::OTHER_LOOKUP_KEYS
|
476
|
+
lookup_key = (lookup_keys & args.keys)[0]
|
426
477
|
|
427
478
|
####### Previously looked-up JSON data
|
479
|
+
# DEPRECATED: pre-lookedup data is never used
|
480
|
+
# and support for it will be going away.
|
428
481
|
if args[:data]
|
429
482
|
|
430
483
|
@init_data = args[:data]
|
431
484
|
|
432
|
-
|
433
|
-
@got_subsets = @init_data[:general].is_a?(Hash)
|
434
|
-
|
435
|
-
### data must include all they keys in REQUIRED_DATA_KEYS + VALID_DATA_KEYS
|
436
|
-
### in either the main hash keys or the :general sub-hash, if it exists
|
437
|
-
hash_to_check = @got_subsets ? @init_data[:general] : @init_data
|
438
|
-
combined_valid_keys = self.class::REQUIRED_DATA_KEYS + self.class::VALID_DATA_KEYS
|
439
|
-
keys_ok = (hash_to_check.keys & combined_valid_keys).count == combined_valid_keys.count
|
440
|
-
unless keys_ok
|
441
|
-
raise(
|
442
|
-
JSS::InvalidDataError,
|
443
|
-
":data is not valid JSON for a #{self.class::RSRC_OBJECT_KEY} from the API. It needs at least the keys :#{combined_valid_keys.join ', :'}"
|
444
|
-
)
|
445
|
-
end
|
446
|
-
|
447
|
-
### and the id must be in the jss
|
448
|
-
raise NoSuchItemError, "No #{self.class::RSRC_OBJECT_KEY} with JSS id: #{@init_data[:id]}" unless \
|
449
|
-
self.class.all_ids.include? hash_to_check[:id]
|
485
|
+
validate_external_init_data
|
450
486
|
|
451
487
|
###### Make a new one in the JSS, but only if we've included the Creatable module
|
452
488
|
elsif args[:id] == :new
|
453
489
|
|
454
|
-
|
455
|
-
|
490
|
+
validate_init_for_creation(args)
|
491
|
+
setup_object_for_creation(args)
|
492
|
+
return
|
456
493
|
|
457
|
-
|
458
|
-
|
494
|
+
###### Look up the data via the API
|
495
|
+
else
|
496
|
+
@init_data = look_up_object_data(args)
|
497
|
+
end ## end arg parsing
|
459
498
|
|
460
|
-
|
461
|
-
|
499
|
+
parse_init_data
|
500
|
+
@need_to_update = false
|
501
|
+
end # init
|
462
502
|
|
463
|
-
|
464
|
-
|
465
|
-
@name = args[:name]
|
466
|
-
@init_data = { name: args[:name] }
|
467
|
-
@in_jss = false
|
468
|
-
@rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name}"
|
469
|
-
@need_to_update = true
|
470
|
-
return
|
503
|
+
# Public Instance Methods
|
504
|
+
#####################################
|
471
505
|
|
472
|
-
|
506
|
+
# Either Create or Update this object in the JSS
|
507
|
+
#
|
508
|
+
# If this item is creatable or updatable, then
|
509
|
+
# create it if needed, or update it if it already exists.
|
510
|
+
#
|
511
|
+
# @return [Integer] the id of the item created or updated
|
512
|
+
#
|
513
|
+
def save
|
514
|
+
if @in_jss
|
515
|
+
raise JSS::UnsupportedError, 'Updating this object in the JSS is currently not supported' unless updatable?
|
516
|
+
update
|
473
517
|
else
|
474
|
-
|
475
|
-
|
476
|
-
|
518
|
+
raise JSS::UnsupportedError, 'Creating this object in the JSS is currently not supported' unless creatable?
|
519
|
+
create
|
520
|
+
end
|
521
|
+
end
|
477
522
|
|
478
|
-
|
523
|
+
# Mix-in Modules.
|
524
|
+
# Each module made for mixing in to APIObject subclasses
|
525
|
+
# sets an appropriate constant to true.
|
526
|
+
# These methods provide a simple way to programattically determine
|
527
|
+
# if an object has one of the mixed-in modules available.
|
479
528
|
|
480
|
-
|
529
|
+
# @return [Boolean] See {JSS::Creatable}
|
530
|
+
def creatable?
|
531
|
+
defined? self.class::CREATABLE
|
532
|
+
end
|
481
533
|
|
482
|
-
|
483
|
-
|
534
|
+
# @return [Boolean] See {JSS::Updatable}
|
535
|
+
def updatable?
|
536
|
+
defined? self.class::UPDATABLE
|
537
|
+
end
|
484
538
|
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
@name = lookup_key == :name ? args[lookup_key] : @init_data[:name]
|
539
|
+
# @return [Boolean] See {JSS::Categorizable}
|
540
|
+
def categorizable?
|
541
|
+
defined? self.class::CATEGORIZABLE
|
542
|
+
end
|
490
543
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
544
|
+
# @return [Boolean] See {JSS::VPPable}
|
545
|
+
def vppable?
|
546
|
+
defined? self.class::VPPABLE
|
547
|
+
end
|
495
548
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
# like ldap servers, which have them in :connection
|
501
|
-
# Whereever both :id and :name are, that's the main subset
|
502
|
-
|
503
|
-
@init_data.keys.each do |subset|
|
504
|
-
@main_subset = @init_data[subset] if @init_data[subset].is_a?(Hash) && @init_data[subset][:id] && @init_data[subset][:name]
|
505
|
-
break if @main_subset
|
506
|
-
end
|
507
|
-
@main_subset ||= @init_data
|
549
|
+
# @return [Boolean] See {JSS::SelfServable}
|
550
|
+
def self_servable?
|
551
|
+
defined? self.class::SELF_SERVABLE
|
552
|
+
end
|
508
553
|
|
509
|
-
|
510
|
-
|
554
|
+
# @return [Boolean] See {JSS::criteriable}
|
555
|
+
def criterable?
|
556
|
+
defined? self.class::CRITERIABLE
|
557
|
+
end
|
511
558
|
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
559
|
+
# @return [Boolean] See {JSS::extendable}
|
560
|
+
def extendable?
|
561
|
+
defined? self.class::EXTENDABLE
|
562
|
+
end
|
516
563
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
564
|
+
# @return [Boolean] See {JSS::Matchable}
|
565
|
+
def matchable?
|
566
|
+
defined? self.class::MATCHABLE
|
567
|
+
end
|
521
568
|
|
522
|
-
|
523
|
-
|
569
|
+
# @return [Boolean] See {JSS::Locatable}
|
570
|
+
def locatable?
|
571
|
+
defined? self.class::LOCATABLE
|
572
|
+
end
|
524
573
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
end
|
574
|
+
# @return [Boolean] See {JSS::Purchasable}
|
575
|
+
def purchasable?
|
576
|
+
defined? self.class::PURCHASABLE
|
577
|
+
end
|
529
578
|
|
530
|
-
|
531
|
-
|
579
|
+
# @return [Boolean] See {JSS::Scopable}
|
580
|
+
def scopable?
|
581
|
+
defined? self.class::SCOPABLE
|
582
|
+
end
|
532
583
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
### create it if needed, or update it if it already exists.
|
537
|
-
###
|
538
|
-
### @return [Integer] the id of the item created or updated
|
539
|
-
###
|
540
|
-
def save
|
541
|
-
if @in_jss
|
542
|
-
raise JSS::UnsupportedError, 'Updating this object in the JSS is currently not supported' \
|
543
|
-
unless defined? self.class::UPDATABLE
|
544
|
-
update
|
545
|
-
else
|
546
|
-
raise JSS::UnsupportedError, 'Creating this object in the JSS is currently not supported' \
|
547
|
-
unless defined? self.class::CREATABLE
|
548
|
-
create
|
549
|
-
end
|
584
|
+
# @return [Boolean] See {JSS::Uploadable}
|
585
|
+
def uploadable?
|
586
|
+
defined? self.class::UPLOADABLE
|
550
587
|
end
|
551
588
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
589
|
+
# Delete this item from the JSS.
|
590
|
+
#
|
591
|
+
# Subclasses may want to redefine this method,
|
592
|
+
# first calling super, then setting other attributes to
|
593
|
+
# nil, false, empty, etc..
|
594
|
+
#
|
595
|
+
# @return [void]
|
596
|
+
#
|
560
597
|
def delete
|
561
598
|
return nil unless @in_jss
|
562
599
|
JSS::API.delete_rsrc @rest_rsrc
|
@@ -567,34 +604,224 @@ module JSS
|
|
567
604
|
:deleted
|
568
605
|
end # delete
|
569
606
|
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
###
|
607
|
+
# A meaningful string representation of this object
|
608
|
+
#
|
609
|
+
# @return [String]
|
610
|
+
#
|
575
611
|
def to_s
|
576
612
|
"#{self.class}, name: #{@name}, id: #{@id}"
|
577
613
|
end
|
578
614
|
|
579
|
-
|
580
|
-
### Private Instance Methods
|
615
|
+
# Private Instance Methods
|
581
616
|
#####################################
|
582
617
|
private
|
583
618
|
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
619
|
+
# If we were passed pre-lookedup API data, validate it,
|
620
|
+
# raising exceptions if not valid.
|
621
|
+
#
|
622
|
+
# DEPRECATED: pre-lookedup data is never used
|
623
|
+
# and support for it will be going away.
|
624
|
+
#
|
625
|
+
# @return [void]
|
626
|
+
#
|
627
|
+
def validate_external_init_data
|
628
|
+
# data must include all they keys in REQUIRED_DATA_KEYS + VALID_DATA_KEYS
|
629
|
+
# in either the main hash keys or the :general sub-hash, if it exists
|
630
|
+
hash_to_check = @init_data[:general] ? @init_data[:general] : @init_data
|
631
|
+
combined_valid_keys = self.class::REQUIRED_DATA_KEYS + self.class::VALID_DATA_KEYS
|
632
|
+
keys_ok = (hash_to_check.keys & combined_valid_keys).count == combined_valid_keys.count
|
633
|
+
unless keys_ok
|
634
|
+
raise(
|
635
|
+
JSS::InvalidDataError,
|
636
|
+
":data is not valid JSON for a #{self.class::RSRC_OBJECT_KEY} from the API. It needs at least the keys :#{combined_valid_keys.join ', :'}"
|
637
|
+
)
|
638
|
+
end
|
639
|
+
# and the id must be in the jss
|
640
|
+
raise NoSuchItemError, "No #{self.class::RSRC_OBJECT_KEY} with JSS id: #{@init_data[:id]}" unless \
|
641
|
+
self.class.all_ids.include? hash_to_check[:id]
|
642
|
+
end # validate_init_data
|
643
|
+
|
644
|
+
# If we're making a new object in the JSS, make sure we were given
|
645
|
+
# valid data to do so, raise exceptions otherwise.
|
646
|
+
#
|
647
|
+
# NOTE: some subclasses may do further validation.
|
648
|
+
#
|
649
|
+
# TODO: support for objects that can have duplicate names.
|
650
|
+
#
|
651
|
+
# @param args[Hash] The args passed to #initialize
|
652
|
+
#
|
653
|
+
# @return [void]
|
654
|
+
#
|
655
|
+
def validate_init_for_creation(args)
|
656
|
+
raise JSS::UnsupportedError, "Creating #{self.class::RSRC_LIST_KEY} isn't yet supported. Please use other Casper workflows." unless creatable?
|
657
|
+
|
658
|
+
raise JSS::MissingDataError, "You must provide a :name to create a #{self.class::RSRC_OBJECT_KEY}." unless args[:name]
|
659
|
+
|
660
|
+
raise JSS::AlreadyExistsError, "A #{self.class::RSRC_OBJECT_KEY} already exists with the name '#{args[:name]}'" if self.class.all_names.include? args[:name]
|
661
|
+
end
|
662
|
+
|
663
|
+
# Given initialization args, perform an API lookup for an object.
|
664
|
+
#
|
665
|
+
# @param args[Hash] The args passed to #initialize
|
666
|
+
#
|
667
|
+
# @return [Hash] The parsed JSON data for the object from the API
|
668
|
+
#
|
669
|
+
def look_up_object_data(args)
|
670
|
+
# what lookup key are we using?
|
671
|
+
combined_lookup_keys = self.class::DEFAULT_LOOKUP_KEYS + args[:other_lookup_keys]
|
672
|
+
lookup_key = (combined_lookup_keys & args.keys)[0]
|
673
|
+
|
674
|
+
raise JSS::MissingDataError, "Args must include a lookup key, one of: :#{combined_lookup_keys.join(', :')}" unless lookup_key
|
675
|
+
|
676
|
+
rsrc = "#{self.class::RSRC_BASE}/#{lookup_key}/#{args[lookup_key]}"
|
677
|
+
|
678
|
+
return JSS::API.get_rsrc(rsrc)[self.class::RSRC_OBJECT_KEY]
|
679
|
+
rescue RestClient::ResourceNotFound
|
680
|
+
raise NoSuchItemError, "No #{self.class::RSRC_OBJECT_KEY} found matching: #{lookup_key}/#{args[lookup_key]}"
|
681
|
+
end
|
682
|
+
|
683
|
+
# Start examining the @init_data recieved from the API
|
684
|
+
#
|
685
|
+
# @return [void]
|
686
|
+
#
|
687
|
+
def parse_init_data
|
688
|
+
# set empty strings to nil
|
689
|
+
@init_data.jss_nillify! '', :recurse
|
690
|
+
|
691
|
+
# Find the "main" subset which contains :id and :name
|
692
|
+
@main_subset = find_main_subset
|
693
|
+
|
694
|
+
@id = @main_subset[:id]
|
695
|
+
@name = @main_subset[:name]
|
696
|
+
@in_jss = true
|
697
|
+
@rest_rsrc = "#{self.class::RSRC_BASE}/id/#{@id}"
|
698
|
+
|
699
|
+
# many things have a :site
|
700
|
+
# TODO: Implement a Sitable mixin module
|
701
|
+
@site = JSS::APIObject.get_name(@main_subset[:site]) if @main_subset[:site]
|
702
|
+
|
703
|
+
##### Handle Mix-ins
|
704
|
+
initialize_category
|
705
|
+
initialize_location
|
706
|
+
initialize_purchasing
|
707
|
+
initialize_scope
|
708
|
+
initialize_criteria
|
709
|
+
initialize_ext_attrs
|
710
|
+
initialize_vpp
|
711
|
+
initialize_self_service
|
712
|
+
end
|
713
|
+
|
714
|
+
# Find which part of the @init_data contains the :id and :name
|
715
|
+
#
|
716
|
+
# If they aren't at the top-level of the init hash they are in a subset hash,
|
717
|
+
# usually :general, but sometimes someething else,
|
718
|
+
# like ldap servers, which have them in :connection
|
719
|
+
# Whereever both :id and :name are, that's the main subset
|
720
|
+
#
|
721
|
+
# @return [Hash] The part of the @init_data containg the :id and :name
|
722
|
+
#
|
723
|
+
def find_main_subset
|
724
|
+
@init_data.each do |key, value|
|
725
|
+
next unless value.is_a? Hash
|
726
|
+
return value if value.keys.include?(:id) && value.keys.include?(:name)
|
727
|
+
end
|
728
|
+
@init_data
|
729
|
+
end
|
730
|
+
|
731
|
+
# parse category data during initialization
|
732
|
+
#
|
733
|
+
# @return [void]
|
734
|
+
#
|
735
|
+
def initialize_category
|
736
|
+
parse_category if categorizable?
|
737
|
+
end
|
738
|
+
|
739
|
+
# parse location data during initialization
|
740
|
+
#
|
741
|
+
# @return [void]
|
742
|
+
#
|
743
|
+
def initialize_location
|
744
|
+
parse_location if locatable?
|
745
|
+
end
|
746
|
+
|
747
|
+
# parse purchasing data during initialization
|
748
|
+
#
|
749
|
+
# @return [void]
|
750
|
+
#
|
751
|
+
def initialize_purchasing
|
752
|
+
parse_purchasing if purchasable?
|
753
|
+
end
|
754
|
+
|
755
|
+
# parse scope data during initialization
|
756
|
+
#
|
757
|
+
# @return [void]
|
758
|
+
#
|
759
|
+
def initialize_scope
|
760
|
+
parse_scope if scopable?
|
761
|
+
end
|
762
|
+
|
763
|
+
# parse criteria data during initialization
|
764
|
+
#
|
765
|
+
# @return [void]
|
766
|
+
#
|
767
|
+
def initialize_criteria
|
768
|
+
parse_criteria if criterable?
|
769
|
+
end
|
770
|
+
|
771
|
+
# parse ext_attrs data during initialization
|
772
|
+
#
|
773
|
+
# @return [void]
|
774
|
+
#
|
775
|
+
def initialize_ext_attrs
|
776
|
+
parse_ext_attrs if extendable?
|
777
|
+
end
|
778
|
+
|
779
|
+
# parse vpp data during initialization
|
780
|
+
#
|
781
|
+
# @return [void]
|
782
|
+
#
|
783
|
+
def initialize_vpp
|
784
|
+
parse_vpp if vppable?
|
785
|
+
end
|
786
|
+
|
787
|
+
# parse self_service data during initialization
|
788
|
+
#
|
789
|
+
# @return [void]
|
790
|
+
#
|
791
|
+
def initialize_self_service
|
792
|
+
parse_self_service if self_servable?
|
793
|
+
end
|
794
|
+
|
795
|
+
# Set the basics for creating a new object in the JSS
|
796
|
+
#
|
797
|
+
# @param args[Type] describe_args
|
798
|
+
#
|
799
|
+
# @return [Type] description_of_returned_object
|
800
|
+
#
|
801
|
+
def setup_object_for_creation(args)
|
802
|
+
# NOTE: subclasses may want to pre-populate more keys in @init_data when :id == :new
|
803
|
+
# then parse them into attributes later.
|
804
|
+
@init_data = { name: args[:name] }
|
805
|
+
@name = args[:name]
|
806
|
+
@in_jss = false
|
807
|
+
@rest_rsrc = "#{self.class::RSRC_BASE}/name/#{CGI.escape @name}"
|
808
|
+
@need_to_update = true
|
809
|
+
end
|
810
|
+
|
811
|
+
# Return a String with the XML Resource
|
812
|
+
# for submitting creation or changes to the JSS via
|
813
|
+
# the API via the Creatable or Updatable modules
|
814
|
+
#
|
815
|
+
# Most classes will redefine this method.
|
816
|
+
#
|
590
817
|
def rest_xml
|
591
|
-
doc = REXML::Document.new APIConnection::XML_HEADER
|
818
|
+
doc = REXML::Document.new JSS::APIConnection::XML_HEADER
|
592
819
|
tmpl = doc.add_element self.class::RSRC_OBJECT_KEY.to_s
|
593
820
|
tmpl.add_element('name').text = @name
|
594
821
|
doc.to_s
|
595
822
|
end
|
596
823
|
|
597
|
-
|
824
|
+
# Aliases
|
598
825
|
|
599
826
|
alias in_jss? in_jss
|
600
827
|
|
@@ -611,6 +838,8 @@ require 'jss/api_object/purchasable'
|
|
611
838
|
require 'jss/api_object/updatable'
|
612
839
|
require 'jss/api_object/extendable'
|
613
840
|
require 'jss/api_object/self_servable'
|
841
|
+
require 'jss/api_object/categorizable'
|
842
|
+
require 'jss/api_object/vppable'
|
614
843
|
|
615
844
|
### Mix-in Sub Modules with Classes
|
616
845
|
require 'jss/api_object/criteriable'
|
@@ -629,8 +858,12 @@ require 'jss/api_object/computer'
|
|
629
858
|
require 'jss/api_object/computer_invitation'
|
630
859
|
require 'jss/api_object/department'
|
631
860
|
require 'jss/api_object/distribution_point'
|
861
|
+
require 'jss/api_object/ebook'
|
632
862
|
require 'jss/api_object/ldap_server'
|
863
|
+
require 'jss/api_object/mac_application'
|
633
864
|
require 'jss/api_object/mobile_device'
|
865
|
+
require 'jss/api_object/mobile_device_application'
|
866
|
+
require 'jss/api_object/mobile_device_configuration_profile'
|
634
867
|
require 'jss/api_object/netboot_server'
|
635
868
|
require 'jss/api_object/network_segment'
|
636
869
|
require 'jss/api_object/osx_configuration_profile'
|