jss-api 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/CHANGES.md +4 -0
  2. data/LICENSE.txt +174 -0
  3. data/README.md +368 -0
  4. data/THANKS.md +6 -0
  5. data/lib/jss-api.rb +549 -0
  6. data/lib/jss-api/api_connection.rb +326 -0
  7. data/lib/jss-api/api_object.rb +590 -0
  8. data/lib/jss-api/api_object/advanced_search.rb +389 -0
  9. data/lib/jss-api/api_object/advanced_search/advanced_computer_search.rb +95 -0
  10. data/lib/jss-api/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  11. data/lib/jss-api/api_object/advanced_search/advanced_user_search.rb +95 -0
  12. data/lib/jss-api/api_object/building.rb +92 -0
  13. data/lib/jss-api/api_object/category.rb +147 -0
  14. data/lib/jss-api/api_object/computer.rb +852 -0
  15. data/lib/jss-api/api_object/creatable.rb +98 -0
  16. data/lib/jss-api/api_object/criteriable.rb +189 -0
  17. data/lib/jss-api/api_object/criteriable/criteria.rb +231 -0
  18. data/lib/jss-api/api_object/criteriable/criterion.rb +228 -0
  19. data/lib/jss-api/api_object/department.rb +93 -0
  20. data/lib/jss-api/api_object/distribution_point.rb +490 -0
  21. data/lib/jss-api/api_object/extendable.rb +221 -0
  22. data/lib/jss-api/api_object/extension_attribute.rb +457 -0
  23. data/lib/jss-api/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  24. data/lib/jss-api/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  25. data/lib/jss-api/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  26. data/lib/jss-api/api_object/group.rb +380 -0
  27. data/lib/jss-api/api_object/group/computer_group.rb +124 -0
  28. data/lib/jss-api/api_object/group/mobile_device_group.rb +139 -0
  29. data/lib/jss-api/api_object/group/user_group.rb +139 -0
  30. data/lib/jss-api/api_object/ldap_server.rb +535 -0
  31. data/lib/jss-api/api_object/locatable.rb +268 -0
  32. data/lib/jss-api/api_object/matchable.rb +97 -0
  33. data/lib/jss-api/api_object/mobile_device.rb +556 -0
  34. data/lib/jss-api/api_object/netboot_server.rb +148 -0
  35. data/lib/jss-api/api_object/network_segment.rb +414 -0
  36. data/lib/jss-api/api_object/package.rb +760 -0
  37. data/lib/jss-api/api_object/peripheral.rb +335 -0
  38. data/lib/jss-api/api_object/peripheral_type.rb +295 -0
  39. data/lib/jss-api/api_object/policy.rb +882 -0
  40. data/lib/jss-api/api_object/purchasable.rb +316 -0
  41. data/lib/jss-api/api_object/removable_macaddr.rb +98 -0
  42. data/lib/jss-api/api_object/scopable.rb +136 -0
  43. data/lib/jss-api/api_object/scopable/scope.rb +621 -0
  44. data/lib/jss-api/api_object/script.rb +631 -0
  45. data/lib/jss-api/api_object/site.rb +93 -0
  46. data/lib/jss-api/api_object/software_update_server.rb +109 -0
  47. data/lib/jss-api/api_object/updatable.rb +117 -0
  48. data/lib/jss-api/api_object/uploadable.rb +138 -0
  49. data/lib/jss-api/api_object/user.rb +272 -0
  50. data/lib/jss-api/client.rb +500 -0
  51. data/lib/jss-api/compatibility.rb +66 -0
  52. data/lib/jss-api/composer.rb +171 -0
  53. data/lib/jss-api/configuration.rb +301 -0
  54. data/lib/jss-api/db_connection.rb +243 -0
  55. data/lib/jss-api/exceptions.rb +83 -0
  56. data/lib/jss-api/ruby_extensions.rb +35 -0
  57. data/lib/jss-api/ruby_extensions/filetest.rb +43 -0
  58. data/lib/jss-api/ruby_extensions/hash.rb +79 -0
  59. data/lib/jss-api/ruby_extensions/ipaddr.rb +91 -0
  60. data/lib/jss-api/ruby_extensions/pathname.rb +77 -0
  61. data/lib/jss-api/ruby_extensions/string.rb +43 -0
  62. data/lib/jss-api/ruby_extensions/time.rb +63 -0
  63. data/lib/jss-api/server.rb +108 -0
  64. data/lib/jss-api/version.rb +31 -0
  65. metadata +219 -0
@@ -0,0 +1,221 @@
1
+ ### Copyright 2014 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+ #####################################
29
+ ### Module Variables
30
+ #####################################
31
+
32
+ #####################################
33
+ ### Module Methods
34
+ #####################################
35
+
36
+ #####################################
37
+ ### Sub-Modules
38
+ #####################################
39
+
40
+ ### A mix-in module for handling extension attribute data for objects in the JSS.
41
+ ###
42
+ ### This module provides standardized ways to deal with Extension Attribute data
43
+ ### in objects that gather that data ({JSS::Computer}s, {JSS::MobileDevice}s,
44
+ ### and {JSS::User}s). For working with the Extension Attributes themselves, see
45
+ ### {JSS::ExtensionAttribute} and its subclasses.
46
+ ###
47
+ ### API objects that have Extension Attribute data return it in an Array of Hashes,
48
+ ### one for each defined ExtensionAttribute for the class;
49
+ ### i.e. a {JSS::Computer}'s Array has one Hash for each {JSS::ComputerExtensionAttribute}
50
+ ### defined in the JSS.
51
+ ###
52
+ ### The Hash keys are:
53
+ ### * :id => the ExtAttr id
54
+ ### * :name => the ExtAttr name
55
+ ### * :type => the data type of the ExtAttr value
56
+ ### * :value => the value for the ExtAttr for this object as of the last report.
57
+ ###
58
+ ### Classes including this module must define the constant EXT_ATTRIB_CLASS
59
+ ### specifying which {JSS::ExtensionAttribute} subclass defines the relevant extension attributes.
60
+ ### For Example, {JSS::Computer} sets this:
61
+ ### EXT_ATTRIB_CLASS = JSS::ComputerExtensionAttribute
62
+ ###
63
+ ### During initialization those classes must call {#parse_ext_attrs} to populate the @extension_attributes
64
+ ### attribute from @init_data.
65
+ ###
66
+ ### Parsing also populates @ext_attrs which is a Hash of name => value for each EA.
67
+ ###
68
+ ### When updating or creating, those classes must add the REXML output of {#ext_attr_xml} to their
69
+ ### rest_xml output.
70
+ ###
71
+ module Extendable
72
+
73
+ #####################################
74
+ ### Constants
75
+ #####################################
76
+
77
+ ###
78
+ EXTENDABLE = true
79
+
80
+
81
+ ### ExtensionAttributes refer to the numeric data type as "Integer"
82
+ ### but the ext. attr values that come with extendable objects refer to
83
+ ### that data type as "Number". Here's an array with both, so we can
84
+ ### work with ether more easily.
85
+ NUMERIC_TYPES = ["Number", "Integer"]
86
+
87
+ #####################################
88
+ ### Variables
89
+ #####################################
90
+
91
+ #####################################
92
+ ### Attribtues
93
+ #####################################
94
+
95
+ ### @return [Array<Hash>] The extension attribute values for the object
96
+ attr_reader :extension_attributes
97
+
98
+ ### @return [Hash] A mapping of Ext Attrib names to their values
99
+ attr_reader :ext_attrs
100
+
101
+ #####################################
102
+ ### Mixed-in Instance Methods
103
+ #####################################
104
+
105
+
106
+
107
+ ###
108
+ ### Populate @extension_attributes (the Array of Hashes that comes from the API)
109
+ ### and @ext_attr_names, which is a Hash mapping the EA names to their
110
+ ### index in the @extension_attributes Array.
111
+ ###
112
+ ### Classes including this module should call this in #initialize
113
+ ###
114
+ ### @return [void]
115
+ ###
116
+ def parse_ext_attrs
117
+
118
+ unless @init_data[:extension_attributes]
119
+ @extension_attributes = []
120
+ @ext_attrs = {}
121
+ return
122
+ end
123
+
124
+ @extension_attributes = @init_data[:extension_attributes]
125
+ @ext_attrs = {}
126
+
127
+ @extension_attributes.each do |ea|
128
+ case ea[:type]
129
+
130
+ when "Date"
131
+ begin # if there's random non-date data, the parse will fail
132
+ ea[:value] = JSS.parse_datetime ea[:value]
133
+ rescue
134
+ end
135
+
136
+ when *NUMERIC_TYPES
137
+ ea[:value] = ea[:value].to_i unless ea[:value].to_s.empty?
138
+ end # case
139
+
140
+ @ext_attrs[ea[:name]] = ea[:value]
141
+
142
+ end # each do ea
143
+ end
144
+
145
+ ###
146
+ ### Set the value of an extension attribute
147
+ ###
148
+ ### If the extension attribute is defined as a popup menu, the value must be one of the
149
+ ### defined popup choices.
150
+ ###
151
+ ### If the ext. attrib. is defined with a data type of Integer, the value must be an Integer.
152
+ ###
153
+ ### If the ext. attrib. is defined with a data type of Date, the value will be converted to a Time
154
+ ###
155
+ ### @param name[String] the name of the extension attribute to set
156
+ ###
157
+ ### @param value[String,Time,Time,Integer] the new value for the extension attribute for this user
158
+ ###
159
+ ### @return [void]
160
+ ###
161
+ def set_ext_attr(name, value)
162
+
163
+ # this will raise an exception if the name doesn't exist
164
+ ea_def = self.class::EXT_ATTRIB_CLASS.new :name => name
165
+
166
+ unless JSS::ExtensionAttribute::EDITABLE_INPUT_TYPES.include? ea_def.input_type
167
+ raise JSS::UnsupportedError, "The value for #{name} cannot be modified. It is gathered during inventory updates."
168
+ end
169
+
170
+ if ea_def.input_type == "Pop-up Menu" and (not ea_def.popup_choices.include? value.to_s)
171
+ raise JSS::UnsupportedError, "The value for #{name} must be one of: '#{ea_def.popup_choices.join("' '")}'"
172
+ end
173
+
174
+ case ea_def.data_type
175
+ when "Date"
176
+
177
+ value = JSS.parse_datetime value
178
+
179
+ when *NUMERIC_TYPES
180
+ raise JSS::InvalidDataError, "The value for #{name} must be an integer" unless value.kind_of? Integer
181
+
182
+ end #case
183
+
184
+ @extension_attributes.each do |ea|
185
+ ea[:value] = value if ea[:name] == name
186
+ end
187
+ @ext_attrs[name] = value
188
+
189
+ @need_to_update = true
190
+ end
191
+
192
+ ###
193
+ ### @api private
194
+ ###
195
+ ### @return [REXML::Element] An <extension_attribute> element to be
196
+ ### included in the rest_xml of objects that mix-in this module.
197
+ ###
198
+ def ext_attr_xml
199
+
200
+ eaxml = REXML::Element.new('extension_attributes')
201
+
202
+ @extension_attributes.each do |ea|
203
+ ea_el = eaxml.add_element('extension_attribute')
204
+ ea_el.add_element('name').text = ea[:name]
205
+
206
+ if ea[:type] == "Date"
207
+ begin
208
+ ea_el.add_element('value').text = ea[:value].to_jss_date
209
+ rescue
210
+ ea_el.add_element('value').text = ea[:value].to_s
211
+ end
212
+ else
213
+ ea_el.add_element('value').text = ea[:value]
214
+ end # if
215
+ end # each do ea
216
+
217
+ return eaxml
218
+ end
219
+
220
+ end # module Purchasable
221
+ end # module JSS
@@ -0,0 +1,457 @@
1
+ ### Copyright 2014 Pixar
2
+ ###
3
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
4
+ ### with the following modification; you may not use this file except in
5
+ ### compliance with the Apache License and the following modification to it:
6
+ ### Section 6. Trademarks. is deleted and replaced with:
7
+ ###
8
+ ### 6. Trademarks. This License does not grant permission to use the trade
9
+ ### names, trademarks, service marks, or product names of the Licensor
10
+ ### and its affiliates, except as required to comply with Section 4(c) of
11
+ ### the License and to reproduce the content of the NOTICE file.
12
+ ###
13
+ ### You may obtain a copy of the Apache License at
14
+ ###
15
+ ### http://www.apache.org/licenses/LICENSE-2.0
16
+ ###
17
+ ### Unless required by applicable law or agreed to in writing, software
18
+ ### distributed under the Apache License with the above modification is
19
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20
+ ### KIND, either express or implied. See the Apache License for the specific
21
+ ### language governing permissions and limitations under the Apache License.
22
+ ###
23
+ ###
24
+
25
+ ###
26
+ module JSS
27
+
28
+
29
+
30
+ #####################################
31
+ ### Constants
32
+ #####################################
33
+
34
+ #####################################
35
+ ### Module Variables
36
+ #####################################
37
+
38
+ #####################################
39
+ ### Module Methods
40
+ #####################################
41
+
42
+ ####################################
43
+ ### Classes
44
+ #####################################
45
+
46
+
47
+ ###
48
+ ### The parent class of ExtensionAttribute objects in the JSS.
49
+ ###
50
+ ### The API extension attribute objects work with the definitions of extension
51
+ ### attributes, not the resulting values stored in the JSS with the inventory
52
+ ### reports.
53
+ ###
54
+ ### This superclass, however, uses the {AdvancedSearch} subclasses to provide
55
+ ### access to the reported values in two ways:
56
+ ### * A list of target objects with a certain value for the ExtensionAttribute instance.
57
+ ### See the {#all_with_result} method for details
58
+ ### * A list of the most recent value for this ExtensionAttribute in all targets in the JSS
59
+ ###
60
+ ### The {ComputerExtensionAttribute} subclass offers a {ComputerExtensionAttribute#history}
61
+ ### method providing the history of values for the EA for one computer. This requires
62
+ ### MySQL access to the JSS database since that history isn't available via the API.
63
+ ###
64
+ ### Subclasses of ExtensionAttribute must define these constants:
65
+ ### * TARGET_CLASS - the {APIObject} subclass to which the extention attribute applies.
66
+ ### e.g. {JSS::Computer}
67
+ ###
68
+ ### * ALL_TARGETS_CRITERION - a {JSS::Criteriable::Criterion} instance that will be used in
69
+ ### an {AdvancedSearch} to find all of members of the TARGET_CLASS
70
+ ###
71
+ ### @see JSS::APIObject
72
+ ###
73
+ class ExtensionAttribute < JSS::APIObject
74
+
75
+ #####################################
76
+ ### Mix-Ins
77
+ #####################################
78
+ include JSS::Creatable
79
+ include JSS::Updatable
80
+
81
+ #####################################
82
+ ### Class Methods
83
+ #####################################
84
+
85
+ #####################################
86
+ ### Class Constants
87
+ #####################################
88
+
89
+ ### What kinds of data can be created by EAs?
90
+ ### Note, Dates must be in the format "YYYY-MM-DD hh:mm:ss"
91
+ DATA_TYPES = ["String", "Date", "Integer"]
92
+ DEFAULT_DATA_TYPE = "String"
93
+
94
+ ### Where does the data come from?
95
+ INPUT_TYPES = [ "Text Field", "Pop-up Menu", "script", "LDAP Attribute Mapping"]
96
+ DEFAULT_INPUT_TYPE = "Text Field"
97
+
98
+ ### These input types can be modified, the others cannot.
99
+ EDITABLE_INPUT_TYPES = ["Text Field", "Pop-up Menu"]
100
+
101
+ ### Where can it be displayed in the WebApp?
102
+ ### subclasses can add to this list
103
+ WEB_DISPLAY_CHOICES = [
104
+ "General",
105
+ "Operating System",
106
+ "Hardware",
107
+ "User and Location",
108
+ "Purchasing",
109
+ "Extension Attributes"
110
+ ]
111
+ DEFAULT_WEB_DISPLAY_CHOICE = "Extension Attributes"
112
+
113
+
114
+ ######################
115
+ ### Attributes
116
+ ######################
117
+
118
+ ### :id, :name, :in_jss, :need_to_update, and :rest_rsrc come from JSS::APIObject
119
+
120
+ ### @return [String] description of the ext attrib
121
+ attr_reader :description
122
+
123
+ ### @return [String] the type of data created by the EA. Must be one of DATA_TYPES
124
+ attr_reader :data_type
125
+
126
+ ### @return [String] where does this data come from? Must be one of the INPUT_TYPES.
127
+ attr_reader :input_type
128
+
129
+ ### @return [Array<String>] the choices available in the UI when the @input_type is "Pop-up Menu"
130
+ attr_reader :popup_choices
131
+
132
+ ### @return [String] In which part of the web UI does the data appear?
133
+ attr_reader :web_display
134
+
135
+
136
+
137
+ #####################################
138
+ ### Constructor
139
+ #####################################
140
+
141
+ ###
142
+ ### @see JSS::APIObject#initialize
143
+ ###
144
+ def initialize(args = {})
145
+
146
+ super args
147
+
148
+ ### @init_data now has the raw data
149
+ ### so fill in our attributes or set defaults
150
+
151
+ @description = @init_data[:description]
152
+ @data_type = @init_data[:data_type] || DEFAULT_DATA_TYPE
153
+ @web_display = @init_data[:inventory_display] || DEFAULT_WEB_DISPLAY_CHOICE
154
+
155
+
156
+ if @init_data[:input_type]
157
+ @input_type = @init_data[:input_type][:type] || DEFAULT_INPUT_TYPE
158
+ @popup_choices = @init_data[:input_type][:popup_choices]
159
+ else
160
+ @input_type = DEFAULT_INPUT_TYPE
161
+ end
162
+
163
+ ### the name of the EA might have spaces and caps, which the will come to us as symbols with the spaces
164
+ ### as underscores, like this.
165
+ @symbolized_name = @name.gsub(' ','_').to_sym
166
+
167
+ end # init
168
+
169
+ #####################################
170
+ ### Public Instance Methods
171
+ #####################################
172
+
173
+ ###
174
+ ### @see JSS::Creatable#create
175
+ ###
176
+ def create
177
+ if @input_type == "Pop-up Menu"
178
+ raise MissingDataError, "No popup_choices set for Pop-up Menu input_type." unless @popup_choices.kind_of? Array and (not @popup_choices.empty?)
179
+ end
180
+ super
181
+ end
182
+
183
+ ###
184
+ ### @see JSS::Updatable#update
185
+ ###
186
+ def update
187
+ if @input_type == "Pop-up Menu"
188
+ raise MissingDataError, "No popup_choices set for Pop-up Menu input_type." unless @popup_choices.kind_of? Array and (not @popup_choices.empty?)
189
+ end
190
+ super
191
+ end
192
+
193
+
194
+ ###
195
+ ### @see JSS::APIObject#delete
196
+ ###
197
+ def delete
198
+ orig_open_timeout = JSS::API.cnx.options[:open_timeout]
199
+ orig_timeout = JSS::API.cnx.options[:timeout]
200
+ JSS::API.timeout = orig_timeout + 1800
201
+ JSS::API.open_timeout = orig_open_timeout + 1800
202
+ begin
203
+ super
204
+ ensure
205
+ JSS::API.timeout = orig_timeout
206
+ JSS::API.open_timeout = orig_open_timeout
207
+ end
208
+ end
209
+
210
+ ###
211
+ ### Change the description of this EA
212
+ ###
213
+ ### @param new_val[String] the new value
214
+ ###
215
+ ### @return [void]
216
+ ###
217
+ def description= (new_val)
218
+ return nil if @description == new_val
219
+ @description = new_val
220
+ @need_to_update = true
221
+ end # name=(newname)
222
+
223
+ ###
224
+ ### Change the data type of this EA
225
+ ###
226
+ ### @param new_val[String] the new value, which must be a member of DATA_TYPES
227
+ ###
228
+ ### @return [void]
229
+ ###
230
+ def data_type= (new_val)
231
+ return nil if @data_type == new_val
232
+ raise JSS::InvalidDataError, "data_type must be a string, one of: #{DATA_TYPES.join(", ")}" unless DATA_TYPES.include? new_val
233
+ @data_type = new_val
234
+ @need_to_update = true
235
+ end #
236
+
237
+
238
+ ###
239
+ ### Change the inventory_display of this EA
240
+ ###
241
+ ### @param new_val[String] the new value, which must be a member of INVENTORY_DISPLAY_CHOICES
242
+ ###
243
+ ### @return [void]
244
+ ###
245
+ def web_display= (new_val)
246
+ return nil if @web_display == new_val
247
+ raise JSS::InvalidDataError, "inventory_display must be a string, one of: #{INVENTORY_DISPLAY_CHOICES.join(", ")}" unless WEB_DISPLAY_CHOICES.include? new_val
248
+ @web_display = new_val
249
+ @need_to_update = true
250
+ end #
251
+
252
+
253
+ ###
254
+ ### Change the input type of this EA
255
+ ###
256
+ ### @param new_val[String] the new value, which must be a member of INPUT_TYPES
257
+ ###
258
+ ### @return [void]
259
+ ###
260
+ def input_type= (new_val)
261
+ return nil if @input_type == new_val
262
+ raise JSS::InvalidDataError, "input_type must be a string, one of: #{INPUT_TYPES.join(", ")}" unless INPUT_TYPES.include? new_val
263
+ @input_type = new_val
264
+ @popup_choices = nil if @input_type == "Text Field"
265
+ @need_to_update = true
266
+ end #
267
+
268
+ ###
269
+ ### Change the Popup Choices of this EA
270
+ ### New value must be an Array, the items will be converted to Strings.
271
+ ###
272
+ ### This automatically sets input_type to "Pop-up Menu"
273
+ ###
274
+ ### Values are checked to ensure they match the @data_type
275
+ ### Note, Dates must be in the format "YYYY-MM-DD hh:mm:ss"
276
+ ###
277
+ ### @param new_val[Array<#to_s>] the new values
278
+ ###
279
+ ### @return [void]
280
+ ###
281
+ def popup_choices= (new_val)
282
+ return nil if @popup_choices == new_val
283
+ raise JSS::InvalidDataError, "popup_choices must be an Array" unless new_val.kind_of?(Array)
284
+
285
+ ### convert each one to a String,
286
+ ### and check that it matches the @data_type
287
+ new_val.map! do |v|
288
+ v = v.to_s.strip
289
+ case @data_type
290
+ when "Date"
291
+ raise JSS::InvalidDataError, "data_type is Date, but '#{v}' is not formatted 'YYYY-MM-DD hh:mm:ss'" unless v =~ /^\d{4}(-\d\d){2} (\d\d:){2}\d\d$/
292
+ when "Integer"
293
+ raise JSS::InvalidDataError, "data_type is Integer, but '#{v}' is not one" unless v =~ /^\d+$/
294
+ end
295
+ v
296
+ end
297
+ self.input_type = "Pop-up Menu"
298
+ @popup_choices = new_val
299
+ @need_to_update = true
300
+ end #
301
+
302
+
303
+ ###
304
+ ### Get an Array of Hashes for all inventory objects
305
+ ### with a desired result in their latest report for this EA.
306
+ ###
307
+ ### Each Hash is one inventory object (computer, mobile device, user), with these keys:
308
+ ### :id - the computer id
309
+ ### :name - the computer name
310
+ ### :value - the matching ext attr value for the objects latest report.
311
+ ###
312
+ ### This is done by creating a temprary {AdvancedSearch} for objects with matching
313
+ ### values in the EA field, then getting the #search_results hash from it.
314
+ ###
315
+ ### The AdvancedSearch is then deleted.
316
+ ###
317
+ ### @param search_type[String] how are we comparing the stored value with the desired value.
318
+ ### must be a member of JSS::Criterion::SEARCH_TYPES
319
+ ###
320
+ ### @param desired_value[String] the value to compare with the stored value to determine a match.
321
+ ###
322
+ ### @return [Array<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time}>] the items that match the result.
323
+ ###
324
+ def all_with_result(search_type, desired_value)
325
+ raise JSS::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss
326
+ raise JSS::InvalidDataError, "Invalid search_type, see JSS::Criteriable::Criterion::SEARCH_TYPES" unless JSS::Criteriable::Criterion::SEARCH_TYPES.include? search_type.to_s
327
+ begin
328
+
329
+ search_class = self.class::TARGET_CLASS::SEARCH_CLASS
330
+ acs = search_class.new :id => :new, :name => "JSSgem-EA-#{Time.now.to_jss_epoch}-result-search"
331
+ acs.display_fields = [@name]
332
+ crit_list = [JSS::Criteriable::Criterion.new(:and_or => "and", :name => @name, :search_type => search_type.to_s, :value => desired_value)]
333
+ acs.criteria = JSS::Criteriable::Criteria.new crit_list
334
+
335
+ acs.create :get_results
336
+
337
+ results = []
338
+
339
+ acs.search_results.each{ |i|
340
+ value = case @data_type
341
+ when "Date" then JSS.parse_datetime i[@symbolized_name]
342
+ when "Integer" then i[@symbolized_name].to_i
343
+ else i[@symbolized_name]
344
+ end # case
345
+ results << {:id => i[:id], :name => i[:name], :value => value}
346
+ }
347
+
348
+ ensure
349
+ acs.delete
350
+ end
351
+ results
352
+ end
353
+
354
+
355
+
356
+ ###
357
+ ### Return an Array of Hashes showing the most recent value
358
+ ### for this EA on all inventory objects in the JSS.
359
+ ###
360
+ ### Each Hash is one inventory object (computer, mobile device, user), with these keys:
361
+ ### :id - the jss id
362
+ ### :name - the object name
363
+ ### :value - the most recent ext attr value for the object.
364
+ ###
365
+ ### This is done by creating a temporary {AdvancedSearch}
366
+ ### for all objects, with the EA as a display field. The #search_result
367
+ ### then contains the desired data.
368
+ ###
369
+ ### The AdvancedSearch is then deleted.
370
+ ###
371
+ ### @return [Array<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time}>]
372
+ ###
373
+ ### @see JSS::AdvancedSearch
374
+ ###
375
+ ### @see JSS::AdvancedComputerSearch
376
+ ###
377
+ ### @see JSS::AdvancedMobileDeviceSearch
378
+ ###
379
+ ### @see JSS::AdvancedUserSearch
380
+ ###
381
+ def latest_values
382
+ raise JSS::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss
383
+ tmp_advsrch = "JSSgem-EA-#{Time.now.to_jss_epoch}-latest-search"
384
+
385
+ begin
386
+ search_class = self.class::TARGET_CLASS::SEARCH_CLASS
387
+ acs = search_class.new :id => :new, :name => tmp_advsrch
388
+ acs.display_fields = [@name]
389
+
390
+ # search for 'Username like "" ' because all searchable object classes have a "Username" value
391
+ #crit_list = [JSS::Criteriable::Criterion.new(:and_or => "and", :name => "Username", :search_type => "like", :value => '')]
392
+
393
+ acs.criteria = JSS::Criteriable::Criteria.new [ self.class::ALL_TARGETS_CRITERION]
394
+ acs.create :get_results
395
+
396
+ results = []
397
+
398
+ acs.search_results.each{ |i|
399
+ value = case @data_type
400
+ when "Date" then JSS.parse_datetime i[@symbolized_name]
401
+ when "Integer" then i[@symbolized_name].to_i
402
+ else i[@symbolized_name]
403
+ end # case
404
+ results << {:id => i[:id], :name => i[:name], :value => value}
405
+ }
406
+
407
+ ensure
408
+ acs.delete
409
+ self.class::TARGET_CLASS::SEARCH_CLASS.new(:name => tmp_advsrch).delete if self.class::TARGET_CLASS::SEARCH_CLASS.all_names(:refresh).include? tmp_advsrch
410
+ end
411
+
412
+ results
413
+
414
+ end
415
+
416
+
417
+ ### aliases
418
+
419
+ alias desc description
420
+
421
+
422
+
423
+ ######################
424
+ ### Private Instance Methods
425
+ #####################
426
+
427
+ private
428
+
429
+ ###
430
+ ### Return a REXML object for this ext attr, with the current values.
431
+ ### Subclasses should augment this in their rest_xml methods
432
+ ### then return it .to_s, for saving or updating
433
+ ###
434
+ def rest_rexml
435
+ ea = REXML::Element.new self.class::RSRC_OBJECT_KEY.to_s
436
+ ea.add_element('name').text = @name
437
+ ea.add_element('description').text = @description
438
+ ea.add_element('data_type').text = @data_type
439
+ ea.add_element('inventory_display').text = @web_display
440
+
441
+ it = ea.add_element('input_type')
442
+ it.add_element('type').text = @input_type
443
+ if @input_type == "Pop-up Menu"
444
+ pcs = it.add_element('popup_choices')
445
+ @popup_choices.each{|pc| pcs.add_element('choice').text = pc}
446
+ end
447
+ return ea
448
+ end # rest xml
449
+
450
+
451
+ end # class ExtAttrib
452
+
453
+ end # module JSS
454
+
455
+ require "jss-api/api_object/extension_attribute/computer_extension_attribute"
456
+ require "jss-api/api_object/extension_attribute/mobile_device_extension_attribute"
457
+ require "jss-api/api_object/extension_attribute/user_extension_attribute"