jss-api 0.5.4

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.
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"