ruby-jss 0.6.3

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.

Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +7 -0
  3. data/CHANGES.md +112 -0
  4. data/LICENSE.txt +174 -0
  5. data/README.md +426 -0
  6. data/THANKS.md +6 -0
  7. data/bin/cgrouper +485 -0
  8. data/bin/subnet-update +400 -0
  9. data/lib/jss-api.rb +2 -0
  10. data/lib/jss.rb +190 -0
  11. data/lib/jss/api_connection.rb +410 -0
  12. data/lib/jss/api_object.rb +616 -0
  13. data/lib/jss/api_object/advanced_search.rb +389 -0
  14. data/lib/jss/api_object/advanced_search/advanced_computer_search.rb +95 -0
  15. data/lib/jss/api_object/advanced_search/advanced_mobile_device_search.rb +96 -0
  16. data/lib/jss/api_object/advanced_search/advanced_user_search.rb +95 -0
  17. data/lib/jss/api_object/building.rb +92 -0
  18. data/lib/jss/api_object/category.rb +147 -0
  19. data/lib/jss/api_object/computer.rb +852 -0
  20. data/lib/jss/api_object/creatable.rb +98 -0
  21. data/lib/jss/api_object/criteriable.rb +189 -0
  22. data/lib/jss/api_object/criteriable/criteria.rb +231 -0
  23. data/lib/jss/api_object/criteriable/criterion.rb +228 -0
  24. data/lib/jss/api_object/department.rb +93 -0
  25. data/lib/jss/api_object/distribution_point.rb +560 -0
  26. data/lib/jss/api_object/extendable.rb +221 -0
  27. data/lib/jss/api_object/extension_attribute.rb +466 -0
  28. data/lib/jss/api_object/extension_attribute/computer_extension_attribute.rb +362 -0
  29. data/lib/jss/api_object/extension_attribute/mobile_device_extension_attribute.rb +189 -0
  30. data/lib/jss/api_object/extension_attribute/user_extension_attribute.rb +117 -0
  31. data/lib/jss/api_object/group.rb +380 -0
  32. data/lib/jss/api_object/group/computer_group.rb +124 -0
  33. data/lib/jss/api_object/group/mobile_device_group.rb +139 -0
  34. data/lib/jss/api_object/group/user_group.rb +139 -0
  35. data/lib/jss/api_object/ldap_server.rb +535 -0
  36. data/lib/jss/api_object/locatable.rb +286 -0
  37. data/lib/jss/api_object/matchable.rb +97 -0
  38. data/lib/jss/api_object/mobile_device.rb +556 -0
  39. data/lib/jss/api_object/netboot_server.rb +148 -0
  40. data/lib/jss/api_object/network_segment.rb +414 -0
  41. data/lib/jss/api_object/osx_configuration_profile.rb +262 -0
  42. data/lib/jss/api_object/package.rb +839 -0
  43. data/lib/jss/api_object/peripheral.rb +335 -0
  44. data/lib/jss/api_object/peripheral_type.rb +295 -0
  45. data/lib/jss/api_object/policy.rb +898 -0
  46. data/lib/jss/api_object/purchasable.rb +316 -0
  47. data/lib/jss/api_object/removable_macaddr.rb +98 -0
  48. data/lib/jss/api_object/scopable.rb +136 -0
  49. data/lib/jss/api_object/scopable/scope.rb +621 -0
  50. data/lib/jss/api_object/script.rb +631 -0
  51. data/lib/jss/api_object/self_servable.rb +356 -0
  52. data/lib/jss/api_object/site.rb +93 -0
  53. data/lib/jss/api_object/software_update_server.rb +109 -0
  54. data/lib/jss/api_object/updatable.rb +117 -0
  55. data/lib/jss/api_object/uploadable.rb +138 -0
  56. data/lib/jss/api_object/user.rb +272 -0
  57. data/lib/jss/client.rb +504 -0
  58. data/lib/jss/compatibility.rb +66 -0
  59. data/lib/jss/composer.rb +185 -0
  60. data/lib/jss/configuration.rb +306 -0
  61. data/lib/jss/db_connection.rb +298 -0
  62. data/lib/jss/exceptions.rb +95 -0
  63. data/lib/jss/ruby_extensions.rb +35 -0
  64. data/lib/jss/ruby_extensions/filetest.rb +43 -0
  65. data/lib/jss/ruby_extensions/hash.rb +79 -0
  66. data/lib/jss/ruby_extensions/ipaddr.rb +91 -0
  67. data/lib/jss/ruby_extensions/pathname.rb +77 -0
  68. data/lib/jss/ruby_extensions/string.rb +59 -0
  69. data/lib/jss/ruby_extensions/time.rb +63 -0
  70. data/lib/jss/server.rb +108 -0
  71. data/lib/jss/utility.rb +478 -0
  72. data/lib/jss/version.rb +31 -0
  73. metadata +187 -0
@@ -0,0 +1,221 @@
1
+ ### Copyright 2016 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,466 @@
1
+ ### Copyright 2016 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
+ LAST_RECON_FIELD = 'Last Inventory Update'
114
+ LAST_RECON_FIELD_SYM = LAST_RECON_FIELD.gsub(' ', '_').to_sym
115
+
116
+ USERNAME_FIELD = "Username"
117
+ USERNAME_FIELD_SYM = USERNAME_FIELD.to_sym
118
+
119
+ ######################
120
+ ### Attributes
121
+ ######################
122
+
123
+ ### :id, :name, :in_jss, :need_to_update, and :rest_rsrc come from JSS::APIObject
124
+
125
+ ### @return [String] description of the ext attrib
126
+ attr_reader :description
127
+
128
+ ### @return [String] the type of data created by the EA. Must be one of DATA_TYPES
129
+ attr_reader :data_type
130
+
131
+ ### @return [String] where does this data come from? Must be one of the INPUT_TYPES.
132
+ attr_reader :input_type
133
+
134
+ ### @return [Array<String>] the choices available in the UI when the @input_type is "Pop-up Menu"
135
+ attr_reader :popup_choices
136
+
137
+ ### @return [String] In which part of the web UI does the data appear?
138
+ attr_reader :web_display
139
+
140
+
141
+
142
+ #####################################
143
+ ### Constructor
144
+ #####################################
145
+
146
+ ###
147
+ ### @see JSS::APIObject#initialize
148
+ ###
149
+ def initialize(args = {})
150
+
151
+ super args
152
+
153
+ ### @init_data now has the raw data
154
+ ### so fill in our attributes or set defaults
155
+
156
+ @description = @init_data[:description]
157
+ @data_type = @init_data[:data_type] || DEFAULT_DATA_TYPE
158
+ @web_display = @init_data[:inventory_display] || DEFAULT_WEB_DISPLAY_CHOICE
159
+
160
+
161
+ if @init_data[:input_type]
162
+ @input_type = @init_data[:input_type][:type] || DEFAULT_INPUT_TYPE
163
+ @popup_choices = @init_data[:input_type][:popup_choices]
164
+ else
165
+ @input_type = DEFAULT_INPUT_TYPE
166
+ end
167
+
168
+ ### the name of the EA might have spaces and caps, which the will come to us as symbols with the spaces
169
+ ### as underscores, like this.
170
+ @symbolized_name = @name.gsub(' ','_').to_sym
171
+
172
+ end # init
173
+
174
+ #####################################
175
+ ### Public Instance Methods
176
+ #####################################
177
+
178
+ ###
179
+ ### @see JSS::Creatable#create
180
+ ###
181
+ def create
182
+ if @input_type == "Pop-up Menu"
183
+ raise MissingDataError, "No popup_choices set for Pop-up Menu input_type." unless @popup_choices.kind_of? Array and (not @popup_choices.empty?)
184
+ end
185
+ super
186
+ end
187
+
188
+ ###
189
+ ### @see JSS::Updatable#update
190
+ ###
191
+ def update
192
+ if @input_type == "Pop-up Menu"
193
+ raise MissingDataError, "No popup_choices set for Pop-up Menu input_type." unless @popup_choices.kind_of? Array and (not @popup_choices.empty?)
194
+ end
195
+ super
196
+ end
197
+
198
+
199
+ ###
200
+ ### @see JSS::APIObject#delete
201
+ ###
202
+ def delete
203
+ orig_open_timeout = JSS::API.cnx.options[:open_timeout]
204
+ orig_timeout = JSS::API.cnx.options[:timeout]
205
+ JSS::API.timeout = orig_timeout + 1800
206
+ JSS::API.open_timeout = orig_open_timeout + 1800
207
+ begin
208
+ super
209
+ ensure
210
+ JSS::API.timeout = orig_timeout
211
+ JSS::API.open_timeout = orig_open_timeout
212
+ end
213
+ end
214
+
215
+ ###
216
+ ### Change the description of this EA
217
+ ###
218
+ ### @param new_val[String] the new value
219
+ ###
220
+ ### @return [void]
221
+ ###
222
+ def description= (new_val)
223
+ return nil if @description == new_val
224
+ @description = new_val
225
+ @need_to_update = true
226
+ end # name=(newname)
227
+
228
+ ###
229
+ ### Change the data type of this EA
230
+ ###
231
+ ### @param new_val[String] the new value, which must be a member of DATA_TYPES
232
+ ###
233
+ ### @return [void]
234
+ ###
235
+ def data_type= (new_val)
236
+ return nil if @data_type == new_val
237
+ raise JSS::InvalidDataError, "data_type must be a string, one of: #{DATA_TYPES.join(", ")}" unless DATA_TYPES.include? new_val
238
+ @data_type = new_val
239
+ @need_to_update = true
240
+ end #
241
+
242
+
243
+ ###
244
+ ### Change the inventory_display of this EA
245
+ ###
246
+ ### @param new_val[String] the new value, which must be a member of INVENTORY_DISPLAY_CHOICES
247
+ ###
248
+ ### @return [void]
249
+ ###
250
+ def web_display= (new_val)
251
+ return nil if @web_display == new_val
252
+ raise JSS::InvalidDataError, "inventory_display must be a string, one of: #{INVENTORY_DISPLAY_CHOICES.join(", ")}" unless WEB_DISPLAY_CHOICES.include? new_val
253
+ @web_display = new_val
254
+ @need_to_update = true
255
+ end #
256
+
257
+
258
+ ###
259
+ ### Change the input type of this EA
260
+ ###
261
+ ### @param new_val[String] the new value, which must be a member of INPUT_TYPES
262
+ ###
263
+ ### @return [void]
264
+ ###
265
+ def input_type= (new_val)
266
+ return nil if @input_type == new_val
267
+ raise JSS::InvalidDataError, "input_type must be a string, one of: #{INPUT_TYPES.join(", ")}" unless INPUT_TYPES.include? new_val
268
+ @input_type = new_val
269
+ @popup_choices = nil if @input_type == "Text Field"
270
+ @need_to_update = true
271
+ end #
272
+
273
+ ###
274
+ ### Change the Popup Choices of this EA
275
+ ### New value must be an Array, the items will be converted to Strings.
276
+ ###
277
+ ### This automatically sets input_type to "Pop-up Menu"
278
+ ###
279
+ ### Values are checked to ensure they match the @data_type
280
+ ### Note, Dates must be in the format "YYYY-MM-DD hh:mm:ss"
281
+ ###
282
+ ### @param new_val[Array<#to_s>] the new values
283
+ ###
284
+ ### @return [void]
285
+ ###
286
+ def popup_choices= (new_val)
287
+ return nil if @popup_choices == new_val
288
+ raise JSS::InvalidDataError, "popup_choices must be an Array" unless new_val.kind_of?(Array)
289
+
290
+ ### convert each one to a String,
291
+ ### and check that it matches the @data_type
292
+ new_val.map! do |v|
293
+ v = v.to_s.strip
294
+ case @data_type
295
+ when "Date"
296
+ 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$/
297
+ when "Integer"
298
+ raise JSS::InvalidDataError, "data_type is Integer, but '#{v}' is not one" unless v =~ /^\d+$/
299
+ end
300
+ v
301
+ end
302
+ self.input_type = "Pop-up Menu"
303
+ @popup_choices = new_val
304
+ @need_to_update = true
305
+ end #
306
+
307
+
308
+ ###
309
+ ### Get an Array of Hashes for all inventory objects
310
+ ### with a desired result in their latest report for this EA.
311
+ ###
312
+ ### Each Hash is one inventory object (computer, mobile device, user), with these keys:
313
+ ### :id - the computer id
314
+ ### :name - the computer name
315
+ ### :value - the matching ext attr value for the objects latest report.
316
+ ###
317
+ ### This is done by creating a temprary {AdvancedSearch} for objects with matching
318
+ ### values in the EA field, then getting the #search_results hash from it.
319
+ ###
320
+ ### The AdvancedSearch is then deleted.
321
+ ###
322
+ ### @param search_type[String] how are we comparing the stored value with the desired value.
323
+ ### must be a member of JSS::Criterion::SEARCH_TYPES
324
+ ###
325
+ ### @param desired_value[String] the value to compare with the stored value to determine a match.
326
+ ###
327
+ ### @return [Array<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time}>] the items that match the result.
328
+ ###
329
+ def all_with_result(search_type, desired_value)
330
+ raise JSS::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss
331
+ raise JSS::InvalidDataError, "Invalid search_type, see JSS::Criteriable::Criterion::SEARCH_TYPES" unless JSS::Criteriable::Criterion::SEARCH_TYPES.include? search_type.to_s
332
+ begin
333
+
334
+ search_class = self.class::TARGET_CLASS::SEARCH_CLASS
335
+ acs = search_class.new :id => :new, :name => "JSSgem-EA-#{Time.now.to_jss_epoch}-result-search"
336
+ acs.display_fields = [@name]
337
+ crit_list = [JSS::Criteriable::Criterion.new(:and_or => "and", :name => @name, :search_type => search_type.to_s, :value => desired_value)]
338
+ acs.criteria = JSS::Criteriable::Criteria.new crit_list
339
+
340
+ acs.create :get_results
341
+
342
+ results = []
343
+
344
+ acs.search_results.each{ |i|
345
+ value = case @data_type
346
+ when "Date" then JSS.parse_datetime i[@symbolized_name]
347
+ when "Integer" then i[@symbolized_name].to_i
348
+ else i[@symbolized_name]
349
+ end # case
350
+ results << {:id => i[:id], :name => i[:name], :value => value}
351
+ }
352
+
353
+ ensure
354
+ acs.delete
355
+ end
356
+ results
357
+ end
358
+
359
+
360
+
361
+ ### Return an Array of Hashes showing the most recent value
362
+ ### for this EA on all inventory objects in the JSS.
363
+ ###
364
+ ### Each Hash is one inventory object (computer, mobile device, user), with these keys:
365
+ ### :id - the jss id
366
+ ### :name - the object (computer, user, mobiledevice) name
367
+ ### :value - the most recent ext attr value for the object.
368
+ ### :as_of - the timestamp of when the value was collected (nil for User EAs)
369
+ ### :username - the username associated with the object
370
+ ###
371
+ ### This is done by creating a temporary {AdvancedSearch}
372
+ ### for all objects, with the EA as a display field. The #search_result
373
+ ### then contains the desired data.
374
+ ###
375
+ ### The AdvancedSearch is then deleted.
376
+ ###
377
+ ### @return [Array<Hash{:id=>Integer,:name=>String,:value=>String,Integer,Time,:as_of=>Time}>]
378
+ ###
379
+ ### @see JSS::AdvancedSearch
380
+ ###
381
+ ### @see JSS::AdvancedComputerSearch
382
+ ###
383
+ ### @see JSS::AdvancedMobileDeviceSearch
384
+ ###
385
+ ### @see JSS::AdvancedUserSearch
386
+ ###
387
+ def latest_values
388
+ raise JSS::NoSuchItemError, "EA Not In JSS! Use #create to create this #{self.class::RSRC_OBJECT_KEY}." unless @in_jss
389
+ tmp_advsrch = "JSSgem-EA-#{Time.now.to_jss_epoch}-latest-search"
390
+
391
+ begin
392
+ search_class = self.class::TARGET_CLASS::SEARCH_CLASS
393
+ acs = search_class.new :id => :new, :name => tmp_advsrch
394
+ acs.display_fields = self.class::TARGET_CLASS == JSS::User ? [@name, USERNAME_FIELD] : [@name, USERNAME_FIELD, LAST_RECON_FIELD]
395
+
396
+ # search for 'Username like "" ' because all searchable object classes have a "Username" value
397
+ crit = JSS::Criteriable::Criterion.new(:and_or => "and", :name => "Username", :search_type => "like", :value => '')
398
+ # crit = self.class::ALL_TARGETS_CRITERION
399
+ acs.criteria = JSS::Criteriable::Criteria.new [crit]
400
+ acs.create :get_results
401
+
402
+ results = []
403
+
404
+ acs.search_results.each do |i|
405
+ value = case @data_type
406
+ when "Date" then JSS.parse_datetime i[@symbolized_name]
407
+ when "Integer" then i[@symbolized_name].to_i
408
+ else i[@symbolized_name]
409
+ end # case
410
+
411
+ as_of = Time.parse(i[LAST_RECON_FIELD_SYM]) if i[LAST_RECON_FIELD_SYM]
412
+
413
+ results << {:id => i[:id], :name => i[:name], :username => i[USERNAME_FIELD_SYM] , :value => value, :as_of => as_of }
414
+ end #acs.search_results.each
415
+
416
+ ensure
417
+ acs.delete
418
+ self.class::TARGET_CLASS::SEARCH_CLASS.new(:name => tmp_advsrch).delete if self.class::TARGET_CLASS::SEARCH_CLASS.all_names(:refresh).include? tmp_advsrch
419
+ end
420
+
421
+ results
422
+
423
+ end
424
+
425
+
426
+ ### aliases
427
+
428
+ alias desc description
429
+
430
+
431
+
432
+ ######################
433
+ ### Private Instance Methods
434
+ #####################
435
+
436
+ private
437
+
438
+ ###
439
+ ### Return a REXML object for this ext attr, with the current values.
440
+ ### Subclasses should augment this in their rest_xml methods
441
+ ### then return it .to_s, for saving or updating
442
+ ###
443
+ def rest_rexml
444
+ ea = REXML::Element.new self.class::RSRC_OBJECT_KEY.to_s
445
+ ea.add_element('name').text = @name
446
+ ea.add_element('description').text = @description
447
+ ea.add_element('data_type').text = @data_type
448
+ ea.add_element('inventory_display').text = @web_display
449
+
450
+ it = ea.add_element('input_type')
451
+ it.add_element('type').text = @input_type
452
+ if @input_type == "Pop-up Menu"
453
+ pcs = it.add_element('popup_choices')
454
+ @popup_choices.each{|pc| pcs.add_element('choice').text = pc}
455
+ end
456
+ return ea
457
+ end # rest xml
458
+
459
+
460
+ end # class ExtAttrib
461
+
462
+ end # module JSS
463
+
464
+ require "jss/api_object/extension_attribute/computer_extension_attribute"
465
+ require "jss/api_object/extension_attribute/mobile_device_extension_attribute"
466
+ require "jss/api_object/extension_attribute/user_extension_attribute"