ruby-jss 0.8.1 → 0.8.2

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.

Potentially problematic release.


This version of ruby-jss might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4328e0cc23db07a92bfa3136ea036a84b614eb38
4
- data.tar.gz: 9ec5ef3a805471764d22061b7a15e809eb966e27
3
+ metadata.gz: ba0289a3600d2d044211e9b13ee210fb6c10b7a2
4
+ data.tar.gz: 647f502e548e3f86345ce9992e20ec26fbe1a273
5
5
  SHA512:
6
- metadata.gz: c3f80986485ec6620fc9f2b9ee45b6ce3bc68390a8db443abd1ad26362222602f09638b34600e6e378ebd2c61f771d8ba109a185013d0f9361763f18ab0fbb68
7
- data.tar.gz: 1b8ebb3ffafc7562a3f9c4ad08cc8b562b1596d9c523ce69f57820016ee8d393e3b8009d27e5fdf7e9491fee2a739652e7accf56cc27713f5da4d76c277284b6
6
+ metadata.gz: dfebb20f13d49cd7677bc9e5fbb47ab668d5a98640cfdd3a4e97852c2cd22189c563cad9759972c5932e047ab31fdeb3cad9dce84c80c67f7e9c7e33f1f8d0f8
7
+ data.tar.gz: fb8761e60f48733df1f6047a4b1b324a1ece25d6c7dad6693b2a162cdd08d981921df20efb475716996f887b43f10b4c17c5029146387ca528199da9c3583950
data/CHANGES.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Change History
2
2
 
3
+ ## v0.8.1 2017-06-07
4
+
5
+ - Fix: Some objects failed to locate their 'main subset' (the chunk of API data that contains the object name and id) correctly.
6
+ - Fix: Some versions of Gem::Version don't like dashes (which are part of SemVers).
7
+
8
+
3
9
  ## v0.8.1 2017-06-05
4
10
 
5
11
  - Improvement: Support for the new semantic versioning of Jamf products starting with Jamf Pro 9.99
@@ -721,11 +721,12 @@ module JSS
721
721
  # @return [Hash] The part of the @init_data containg the :id and :name
722
722
  #
723
723
  def find_main_subset
724
+ return @init_data if @init_data[:id] && @init_data[:name]
725
+ return @init_data[:general] if @init_data[:general] && @init_data[:general][:id] && @init_data[:general][:name]
724
726
  @init_data.each do |key, value|
725
727
  next unless value.is_a? Hash
726
728
  return value if value.keys.include?(:id) && value.keys.include?(:name)
727
729
  end
728
- @init_data
729
730
  end
730
731
 
731
732
  # parse category data during initialization
data/lib/jss/utility.rb CHANGED
@@ -1,134 +1,132 @@
1
- ### Copyright 2017 Pixar
2
-
3
- ###
4
- ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
- ### with the following modification; you may not use this file except in
6
- ### compliance with the Apache License and the following modification to it:
7
- ### Section 6. Trademarks. is deleted and replaced with:
8
- ###
9
- ### 6. Trademarks. This License does not grant permission to use the trade
10
- ### names, trademarks, service marks, or product names of the Licensor
11
- ### and its affiliates, except as required to comply with Section 4(c) of
12
- ### the License and to reproduce the content of the NOTICE file.
13
- ###
14
- ### You may obtain a copy of the Apache License at
15
- ###
16
- ### http://www.apache.org/licenses/LICENSE-2.0
17
- ###
18
- ### Unless required by applicable law or agreed to in writing, software
19
- ### distributed under the Apache License with the above modification is
20
- ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
- ### KIND, either express or implied. See the Apache License for the specific
22
- ### language governing permissions and limitations under the Apache License.
23
- ###
24
- ###
25
-
26
- ###
1
+ # Copyright 2017 Pixar
2
+
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ # with the following modification; you may not use this file except in
6
+ # compliance with the Apache License and the following modification to it:
7
+ # Section 6. Trademarks. is deleted and replaced with:
8
+ #
9
+ # 6. Trademarks. This License does not grant permission to use the trade
10
+ # names, trademarks, service marks, or product names of the Licensor
11
+ # and its affiliates, except as required to comply with Section 4(c) of
12
+ # the License and to reproduce the content of the NOTICE file.
13
+ #
14
+ # You may obtain a copy of the Apache License at
15
+ #
16
+ # http://www.apache.org/licenses/LICENSE-2.0
17
+ #
18
+ # Unless required by applicable law or agreed to in writing, software
19
+ # distributed under the Apache License with the above modification is
20
+ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ # KIND, either express or implied. See the Apache License for the specific
22
+ # language governing permissions and limitations under the Apache License.
23
+ #
24
+ #
25
+
26
+ #
27
27
  module JSS
28
28
 
29
- ### A collection of useful utility methods. Mostly for
30
- ### converting values between formats, parsing data, and
31
- ### user interaction.
32
-
33
- ### Converts an OS Version into an Array of higher OS versions.
34
- ###
35
- ### It's unlikely that this library will still be in use as-is by the release of OS X 10.19.15.
36
- ### Hopefully well before then JAMF will implement a "minimum OS" in the JSS itself.
37
- ###
38
- ### @param min_os [String] the mimimum OS version to expand, e.g. ">=10.6.7" or "10.6.7"
39
- ###
40
- ### @return [Array] Nearly all potential OS versions from the minimum to 10.19.x.
41
- ###
42
- ### @example
43
- ### JSS.expand_min_os ">=10.6.7" # => returns this array
44
- ### # ["10.6.7",
45
- ### # "10.6.8",
46
- ### # "10.6.9",
47
- ### # "10.6.10",
48
- ### # "10.6.11",
49
- ### # "10.6.12",
50
- ### # "10.6.13",
51
- ### # "10.6.14",
52
- ### # "10.6.15",
53
- ### # "10.7.x",
54
- ### # "10.8.x",
55
- ### # "10.9.x",
56
- ### # "10.10.x",
57
- ### # "10.11.x",
58
- ### # "10.12.x",
59
- ### # "10.13.x",
60
- ### # "10.14.x",
61
- ### # "10.15.x",
62
- ### # "10.16.x",
63
- ### # "10.17.x",
64
- ### # "10.18.x",
65
- ### # "10.19.x"]
66
- ###
67
- ###
68
- def self.expand_min_os (min_os)
69
-
70
- min_os = min_os.delete ">="
71
-
72
- ### split the version into major, minor and maintenance release numbers
73
- (maj,min,maint) = min_os.split(".")
74
- maint = "x" if maint.nil? or maint == "0"
75
-
76
- ### if the maint release number is an "x" just start the list of OK OS's with it
77
- if maint == "x"
78
- ok_oses = [maj + "." + min.to_s + ".x"]
79
-
80
- ### otherwise, start with it and explicitly add all maint releases up to 15
81
- ### (and hope apple doesn't do more than 15 maint releases for an OS)
29
+ # A collection of useful utility methods. Mostly for
30
+ # converting values between formats, parsing data, and
31
+ # user interaction.
32
+
33
+ # Converts an OS Version into an Array of higher OS versions.
34
+ #
35
+ # It's unlikely that this library will still be in use as-is by the release of OS X 10.19.15.
36
+ # Hopefully well before then JAMF will implement a "minimum OS" in the JSS itself.
37
+ #
38
+ # @param min_os [String] the mimimum OS version to expand, e.g. ">=10.6.7" or "10.6.7"
39
+ #
40
+ # @return [Array] Nearly all potential OS versions from the minimum to 10.19.x.
41
+ #
42
+ # @example
43
+ # JSS.expand_min_os ">=10.6.7" # => returns this array
44
+ # # ["10.6.7",
45
+ # # "10.6.8",
46
+ # # "10.6.9",
47
+ # # "10.6.10",
48
+ # # "10.6.11",
49
+ # # "10.6.12",
50
+ # # "10.6.13",
51
+ # # "10.6.14",
52
+ # # "10.6.15",
53
+ # # "10.7.x",
54
+ # # "10.8.x",
55
+ # # "10.9.x",
56
+ # # "10.10.x",
57
+ # # "10.11.x",
58
+ # # "10.12.x",
59
+ # # "10.13.x",
60
+ # # "10.14.x",
61
+ # # "10.15.x",
62
+ # # "10.16.x",
63
+ # # "10.17.x",
64
+ # # "10.18.x",
65
+ # # "10.19.x"]
66
+ #
67
+ #
68
+ def self.expand_min_os(min_os)
69
+ min_os = min_os.delete '>='
70
+
71
+ # split the version into major, minor and maintenance release numbers
72
+ (maj, min, maint) = min_os.split('.')
73
+ maint = 'x' if maint.nil? || maint == '0'
74
+
75
+ # if the maint release number is an "x" just start the list of OK OS's with it
76
+ if maint == 'x'
77
+ ok_oses = [maj + '.' + min.to_s + '.x']
78
+
79
+ # otherwise, start with it and explicitly add all maint releases up to 15
80
+ # (and hope apple doesn't do more than 15 maint releases for an OS)
82
81
  else
83
82
  ok_oses = []
84
83
  (maint.to_i..15).each do |m|
85
- ok_oses << maj + "." + min +"." + m.to_s
84
+ ok_oses << maj + '.' + min + '.' + m.to_s
86
85
  end # each m
87
86
  end
88
87
 
89
- ### now account for all OS X versions starting with 10.
90
- ### up to at least 10.19.x
88
+ # now account for all OS X versions starting with 10.
89
+ # up to at least 10.19.x
91
90
  ((min.to_i + 1)..19).each do |v|
92
- ok_oses << maj + "." + v.to_s + ".x"
91
+ ok_oses << maj + '.' + v.to_s + '.x'
93
92
  end # each v
94
- return ok_oses
93
+ ok_oses
95
94
  end
96
95
 
97
- ### Scripts and packages can have processor limitations.
98
- ### This method tests a given processor, against a requirement
99
- ### to see if the requirement is met.
100
- ###
101
- ### @param requirement[String] The processor requirement.
102
- ### either 'ppc', 'x86', or some variation on "none", nil, or empty
103
- ###
104
- ### @param processor[String] the processor to check, defaults to
105
- ### the processor of the current machine. Any flavor of intel
96
+ # Scripts and packages can have processor limitations.
97
+ # This method tests a given processor, against a requirement
98
+ # to see if the requirement is met.
99
+ #
100
+ # @param requirement[String] The processor requirement.
101
+ # either 'ppc', 'x86', or some variation on "none", nil, or empty
102
+ #
103
+ # @param processor[String] the processor to check, defaults to
104
+ # the processor of the current machine. Any flavor of intel
106
105
  ## is (i486, i386, x86-64, etc) is treated as "x86"
107
- ###
108
- ### @return [Boolean] can this pkg be installed with the processor
109
- ### given?
110
- ###
111
- def self.processor_ok? (requirement, processor = nil)
112
-
113
- return true if requirement.to_s.empty? or requirement =~ /none/i
106
+ #
107
+ # @return [Boolean] can this pkg be installed with the processor
108
+ # given?
109
+ #
110
+ def self.processor_ok?(requirement, processor = nil)
111
+ return true if requirement.to_s.empty? || requirement =~ /none/i
114
112
  processor ||= `/usr/bin/uname -p`
115
- return requirement == (processor.to_s.include?("86") ? "x86" : "ppc")
113
+ requirement == (processor.to_s.include?('86') ? 'x86' : 'ppc')
116
114
  end
117
115
 
118
- ### Scripts and packages can have OS limitations.
119
- ### This method tests a given OS, against a requirement list
120
- ### to see if the requirement is met.
121
- ###
122
- ### @param requirement[String,Array] The os requirement list, a comma-seprated string
123
- ### or array of strings of allows OSes. e.g. 10.7, 10.8.5 or 10.9.x
124
- ###
125
- ### @param processor[String] the os to check, defaults to
126
- ### the os of the current machine.
127
- ###
128
- ### @return [Boolean] can this pkg be installed with the processor
129
- ### given?
130
- ###
131
- def self.os_ok? (requirement, os_to_check = nil)
116
+ # Scripts and packages can have OS limitations.
117
+ # This method tests a given OS, against a requirement list
118
+ # to see if the requirement is met.
119
+ #
120
+ # @param requirement[String,Array] The os requirement list, a comma-seprated string
121
+ # or array of strings of allows OSes. e.g. 10.7, 10.8.5 or 10.9.x
122
+ #
123
+ # @param processor[String] the os to check, defaults to
124
+ # the os of the current machine.
125
+ #
126
+ # @return [Boolean] can this pkg be installed with the processor
127
+ # given?
128
+ #
129
+ def self.os_ok?(requirement, os_to_check = nil)
132
130
  return true if requirement.to_s =~ /none/i
133
131
  return true if requirement.to_s == 'n'
134
132
  requirement = JSS.to_s_and_a(requirement)[:arrayform]
@@ -143,164 +141,158 @@ module JSS
143
141
  # "10.8.x" /^10\.8\.?\d*$/
144
142
  req_regexps = requirement.map do |r|
145
143
  if r.end_with?('.x')
146
- /^#{r.chomp('.x').gsub('.','\.')}\.?\d*$/
144
+ /^#{r.chomp('.x').gsub('.', '\.')}\.?\d*$/
147
145
 
148
146
  elsif r =~ /^\d+\.\d+$/
149
- /^#{r.gsub('.','\.')}(.0)?$/
147
+ /^#{r.gsub('.', '\.')}(.0)?$/
150
148
 
151
149
  else
152
- /^#{r.gsub('.','\.')}$/
150
+ /^#{r.gsub('.', '\.')}$/
153
151
  end
154
152
  end
155
153
 
156
- req_regexps.each{|re| return true if os_to_check =~ re }
157
- return false
154
+ req_regexps.each { |re| return true if os_to_check =~ re }
155
+ false
158
156
  end
159
157
 
160
-
161
- ### Given a list of data as a comma-separated string, or an Array of strings,
162
- ### return a Hash with both versions.
163
- ###
164
- ### Some parts of the JSS require lists as comma-separated strings, while
165
- ### often those data are easier work with as arrays. This method is a handy way
166
- ### to get either form when given either form.
167
- ###
168
- ### @param somedata [String, Array] the data to parse, of either class,
169
- ###
170
- ### @return [Hash{:stringform => String, :arrayform => Array}] the data as both comma-separated String and Array
171
- ###
172
- ### @example
173
- ### JSS.to_s_and_a "foo, bar, baz" # Hash => {:stringform => "foo, bar, baz", :arrayform => ["foo", "bar", "baz"]}
174
- ###
175
- ### JSS.to_s_and_a ["foo", "bar", "baz"] # Hash => {:stringform => "foo, bar, baz", :arrayform => ["foo", "bar", "baz"]}
176
- ###
177
- def self.to_s_and_a (somedata)
158
+ # Given a list of data as a comma-separated string, or an Array of strings,
159
+ # return a Hash with both versions.
160
+ #
161
+ # Some parts of the JSS require lists as comma-separated strings, while
162
+ # often those data are easier work with as arrays. This method is a handy way
163
+ # to get either form when given either form.
164
+ #
165
+ # @param somedata [String, Array] the data to parse, of either class,
166
+ #
167
+ # @return [Hash{:stringform => String, :arrayform => Array}] the data as both comma-separated String and Array
168
+ #
169
+ # @example
170
+ # JSS.to_s_and_a "foo, bar, baz" # Hash => {:stringform => "foo, bar, baz", :arrayform => ["foo", "bar", "baz"]}
171
+ #
172
+ # JSS.to_s_and_a ["foo", "bar", "baz"] # Hash => {:stringform => "foo, bar, baz", :arrayform => ["foo", "bar", "baz"]}
173
+ #
174
+ def self.to_s_and_a(somedata)
178
175
  case somedata
179
- when nil
180
- valstr = ""
181
- valarr = []
182
- when String
183
- valstr = somedata
184
- valarr = somedata.split(/,\s*/)
185
- when Array
186
- valstr = somedata.join ", "
187
- valarr = somedata
188
- else
189
- raise JSS::InvalidDataError, "Input must be a comma-separated String or an Array of Strings"
176
+ when nil
177
+ valstr = ''
178
+ valarr = []
179
+ when String
180
+ valstr = somedata
181
+ valarr = somedata.split(/,\s*/)
182
+ when Array
183
+ valstr = somedata.join ', '
184
+ valarr = somedata
185
+ else
186
+ raise JSS::InvalidDataError, 'Input must be a comma-separated String or an Array of Strings'
190
187
  end # case
191
- return {:stringform => valstr, :arrayform => valarr}
188
+ { stringform: valstr, arrayform: valarr }
192
189
  end # to_s_and_a
193
190
 
194
- ### Parse a plist into a Ruby data structure.
195
- ### This enhances Plist::parse_xml taking file paths, as well as XML Strings
196
- ### and reading the files regardless of binary/XML format.
197
- ###
198
- ### @param plist[Pathname, String] the plist XML, or the path to a plist file
199
- ###
200
- ### @return [Object] the parsed plist as a ruby hash,array, etc.
201
- ###
202
- def self.parse_plist (plist)
203
-
191
+ # Parse a plist into a Ruby data structure.
192
+ # This enhances Plist::parse_xml taking file paths, as well as XML Strings
193
+ # and reading the files regardless of binary/XML format.
194
+ #
195
+ # @param plist[Pathname, String] the plist XML, or the path to a plist file
196
+ #
197
+ # @return [Object] the parsed plist as a ruby hash,array, etc.
198
+ #
199
+ def self.parse_plist(plist)
204
200
  # did we get a string of xml, or a string pathname?
205
201
  case plist
206
202
  when String
207
- if plist.include? "</plist>"
208
- return Plist.parse_xml plist
209
- else
210
- plist = Pathname.new plist
211
- end
203
+ return Plist.parse_xml plist if plist.include? '</plist>'
204
+ plist = Pathname.new plist
212
205
  when Pathname
213
206
  true
214
207
  else
215
- raise ArgumentError, "Argument must be a path (as a Pathname or String) or a String of XML"
208
+ raise ArgumentError, 'Argument must be a path (as a Pathname or String) or a String of XML'
216
209
  end # case plist
217
210
 
218
211
  # if we're here, its a Pathname
219
212
  raise JSS::MissingDataError, "No such file: #{plist}" unless plist.file?
220
213
 
221
- return Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape(plist.to_s)}`
222
-
214
+ Plist.parse_xml `/usr/libexec/PlistBuddy -x -c print #{Shellwords.escape(plist.to_s)}`
223
215
  end # parse_plist
224
216
 
225
-
226
- ### Converts anything that responds to #to_s to a Time, or nil
227
- ###
228
- ### Return nil if the item is nil, 0 or an empty String.
229
- ###
230
- ### Otherwise the item converted to a string, and parsed with DateTime.parse.
231
- ### It is then examined to see if it has a UTC offset. If not, the local offset
232
- ### is applied, then the DateTime is converted to a Time.
233
- ###
234
- ### @param a_datetime [#to_s] The thing to convert to a time.
235
- ###
236
- ### @return [Time, nil] nil is returned if a_datetime is nil, 0 or an empty String.
237
- ###
217
+ # Converts anything that responds to #to_s to a Time, or nil
218
+ #
219
+ # Return nil if the item is nil, 0 or an empty String.
220
+ #
221
+ # Otherwise the item converted to a string, and parsed with DateTime.parse.
222
+ # It is then examined to see if it has a UTC offset. If not, the local offset
223
+ # is applied, then the DateTime is converted to a Time.
224
+ #
225
+ # @param a_datetime [#to_s] The thing to convert to a time.
226
+ #
227
+ # @return [Time, nil] nil is returned if a_datetime is nil, 0 or an empty String.
228
+ #
238
229
  def self.parse_time(a_datetime)
239
230
  return nil if NIL_DATES.include? a_datetime
240
231
 
241
232
  the_dt = DateTime.parse(a_datetime.to_s)
242
233
 
243
- ### The microseconds in DateTimes are stored as a fraction of a day.
244
- ### Convert them to an integer of microseconds
234
+ # The microseconds in DateTimes are stored as a fraction of a day.
235
+ # Convert them to an integer of microseconds
245
236
  usec = (the_dt.sec_fraction * 60 * 60 * 24 * (10**6)).to_i
246
237
 
247
- ### if the UTC offset of the datetime is zero, make a new one with the correct local offset
248
- ### (which might also be zero if we happen to be in GMT)
249
- if the_dt.offset == 0
250
- the_dt = DateTime.new(the_dt.year, the_dt.month, the_dt.day, the_dt.hour, the_dt.min, the_dt.sec, JSS::TIME_ZONE_OFFSET)
238
+ # if the UTC offset of the datetime is zero, make a new one with the correct local offset
239
+ # (which might also be zero if we happen to be in GMT)
240
+ if the_dt.offset.zero?
241
+ the_dt = DateTime.new(the_dt.year, the_dt.month, the_dt.day, the_dt.hour, the_dt.min, the_dt.sec, JSS::TIME_ZONE_OFFSET)
251
242
  end
252
243
  # now convert it to a Time and return it
253
244
  Time.at the_dt.strftime('%s').to_i, usec
245
+ end # parse_time
246
+
247
+ # Deprecated - to be eventually removed in favor of
248
+ # the more-appropriately named JSS::parse_time
249
+ #
250
+ # @see JSS::parse_time
251
+ #
252
+ def self.parse_datetime(a_datetime)
253
+ parse_time(a_datetime)
254
+ end
254
255
 
255
- end #parse_time
256
-
257
- ### Deprecated - to be eventually removed in favor of
258
- ### the more-appropriately named JSS::parse_time
259
- ###
260
- ### @see JSS::parse_time
261
- ###
262
- def self.parse_datetime(a_datetime) ; self.parse_time(a_datetime) ; end
263
-
264
- ### Converts JSS epoch (unix epoch + milliseconds) to a Ruby Time object
265
- ###
266
- ### @param epoch[String, Integer, nil]
267
- ###
268
- ### @return [Time, nil] nil is returned if epoch is nil, 0 or an empty String.
269
- ###
256
+ # Converts JSS epoch (unix epoch + milliseconds) to a Ruby Time object
257
+ #
258
+ # @param epoch[String, Integer, nil]
259
+ #
260
+ # @return [Time, nil] nil is returned if epoch is nil, 0 or an empty String.
261
+ #
270
262
  def self.epoch_to_time(epoch)
271
263
  return nil if NIL_DATES.include? epoch
272
264
  Time.at(epoch.to_i / 1000.0)
273
- end #parse_date
274
-
275
- ### Given a string of xml element text, escape any characters that would make XML unhappy.
276
- ### * & => &amp;
277
- ### * " => &quot;
278
- ### * < => &lt;
279
- ### * > => &gt;
280
- ### * ' => &apos;
281
- ###
282
- ### @param string [String] the string to make xml-compliant.
283
- ###
284
- ### @return [String] the xml-compliant string
285
- ###
265
+ end # parse_date
266
+
267
+ # Given a string of xml element text, escape any characters that would make XML unhappy.
268
+ # * & => &amp;
269
+ # * " => &quot;
270
+ # * < => &lt;
271
+ # * > => &gt;
272
+ # * ' => &apos;
273
+ #
274
+ # @param string [String] the string to make xml-compliant.
275
+ #
276
+ # @return [String] the xml-compliant string
277
+ #
286
278
  def self.escape_xml(string)
287
279
  string.gsub(/&/, '&amp;').gsub(/\"/, '&quot;').gsub(/>/, '&gt;').gsub(/</, '&lt;').gsub(/'/, '&apos;')
288
280
  end
289
281
 
290
- ### Given an element name and an array of content, generate an Array of
291
- ### REXML::Element objects with that name, and matching content.
292
- ### The array of REXML elements would render thus:
293
- ### <foo>bar</foo>
294
- ### <foo>morefoo</foo>
295
- ###
296
- ### @param element [#to_s] an element_name like :foo
297
- ###
298
- ### @param list [Array<#to_s>] an Array of element content such as ["bar", :morefoo]
299
- ###
300
- ### @return [Array<REXML::Element>]
301
- ###
302
- def self.array_to_rexml_array(element,list)
303
- raise JSS::InvalidDataError, "Arg. must be an Array." unless list.kind_of? Array
282
+ # Given an element name and an array of content, generate an Array of
283
+ # REXML::Element objects with that name, and matching content.
284
+ # The array of REXML elements would render thus:
285
+ # <foo>bar</foo>
286
+ # <foo>morefoo</foo>
287
+ #
288
+ # @param element [#to_s] an element_name like :foo
289
+ #
290
+ # @param list [Array<#to_s>] an Array of element content such as ["bar", :morefoo]
291
+ #
292
+ # @return [Array<REXML::Element>]
293
+ #
294
+ def self.array_to_rexml_array(element, list)
295
+ raise JSS::InvalidDataError, 'Arg. must be an Array.' unless list.is_a? Array
304
296
  element = element.to_s
305
297
  list.map do |v|
306
298
  e = REXML::Element.new(element)
@@ -309,26 +301,26 @@ module JSS
309
301
  end
310
302
  end
311
303
 
312
- ### Given a simple Hash, convert it to an array of REXML Elements such that each
313
- ### key becomes an element, and its value becomes the text content of
314
- ### that element
315
- ###
316
- ### @example
317
- ### my_hash = {:foo => "bar", :baz => :morefoo}
318
- ### xml = JSS.hash_to_rexml_array(my_hash)
319
- ### xml.each{|x| puts x }
320
- ###
321
- ### <foo>bar</foo>
322
- ### <baz>morefoo</baz>
323
- ###
324
- ### @param hash [Hash{#to_s => #to_s}] the Hash to convert
325
- ###
326
- ### @return [Array<REXML::Element>] the Array of REXML elements.
327
- ###
304
+ # Given a simple Hash, convert it to an array of REXML Elements such that each
305
+ # key becomes an element, and its value becomes the text content of
306
+ # that element
307
+ #
308
+ # @example
309
+ # my_hash = {:foo => "bar", :baz => :morefoo}
310
+ # xml = JSS.hash_to_rexml_array(my_hash)
311
+ # xml.each{|x| puts x }
312
+ #
313
+ # <foo>bar</foo>
314
+ # <baz>morefoo</baz>
315
+ #
316
+ # @param hash [Hash{#to_s => #to_s}] the Hash to convert
317
+ #
318
+ # @return [Array<REXML::Element>] the Array of REXML elements.
319
+ #
328
320
  def self.hash_to_rexml_array(hash)
329
- raise InvalidDataError, "Arg. must be a Hash." unless hash.kind_of? Hash
321
+ raise InvalidDataError, 'Arg. must be a Hash.' unless hash.is_a? Hash
330
322
  ary = []
331
- hash.each_pair do |k,v|
323
+ hash.each_pair do |k, v|
332
324
  el = REXML::Element.new k.to_s
333
325
  el.text = v
334
326
  ary << el
@@ -336,39 +328,39 @@ module JSS
336
328
  ary
337
329
  end
338
330
 
339
- ### Given an Array of Hashes with :id and/or :name keys, return
340
- ### a single REXML element with a sub-element for each item,
341
- ### each of which contains a :name or :id element.
342
- ###
343
- ### @param list_element [#to_s] the name of the XML element that contains the list.
344
- ### e.g. :computers
345
- ###
346
- ### @param item_element [#to_s] the name of each XML element in the list,
347
- ### e.g. :computer
348
- ###
349
- ### @param item_list [Array<Hash>] an Array of Hashes each with a :name or :id key.
350
- ###
351
- ### @param content [Symbol] which hash key should be used as the content of if list item? Defaults to :name
352
- ###
353
- ### @return [REXML::Element] the item list as REXML
354
- ###
355
- ### @example
356
- ### comps = [{:id=>2,:name=>'kimchi'},{:id=>5,:name=>'mantis'}]
357
- ### xml = JSS.item_list_to_rexml_list(:computers, :computer , comps, :name)
358
- ### puts xml
359
- ### # output manually formatted for clarity. No newlines in the real xml string
360
- ### <computers>
361
- ### <computer>
362
- ### <name>kimchi</name>
363
- ### </computer>
364
- ### <computer>
365
- ### <name>mantis</name>
366
- ### </computer>
367
- ### </computers>
368
- ###
369
- ### # if content is :id, then, eg. <name>kimchi</name> would be <id>2</id>
370
- ###
371
- def self.item_list_to_rexml_list(list_element, item_element , item_list, content = :name)
331
+ # Given an Array of Hashes with :id and/or :name keys, return
332
+ # a single REXML element with a sub-element for each item,
333
+ # each of which contains a :name or :id element.
334
+ #
335
+ # @param list_element [#to_s] the name of the XML element that contains the list.
336
+ # e.g. :computers
337
+ #
338
+ # @param item_element [#to_s] the name of each XML element in the list,
339
+ # e.g. :computer
340
+ #
341
+ # @param item_list [Array<Hash>] an Array of Hashes each with a :name or :id key.
342
+ #
343
+ # @param content [Symbol] which hash key should be used as the content of if list item? Defaults to :name
344
+ #
345
+ # @return [REXML::Element] the item list as REXML
346
+ #
347
+ # @example
348
+ # comps = [{:id=>2,:name=>'kimchi'},{:id=>5,:name=>'mantis'}]
349
+ # xml = JSS.item_list_to_rexml_list(:computers, :computer , comps, :name)
350
+ # puts xml
351
+ # # output manually formatted for clarity. No newlines in the real xml string
352
+ # <computers>
353
+ # <computer>
354
+ # <name>kimchi</name>
355
+ # </computer>
356
+ # <computer>
357
+ # <name>mantis</name>
358
+ # </computer>
359
+ # </computers>
360
+ #
361
+ # # if content is :id, then, eg. <name>kimchi</name> would be <id>2</id>
362
+ #
363
+ def self.item_list_to_rexml_list(list_element, item_element, item_list, content = :name)
372
364
  xml_list = REXML::Element.new list_element.to_s
373
365
  item_list.each do |i|
374
366
  xml_list.add_element(item_element.to_s).add_element(content.to_s).text = i[content]
@@ -376,41 +368,41 @@ module JSS
376
368
  xml_list
377
369
  end
378
370
 
379
- ### Parse a JSS Version number into something comparable.
380
- ###
381
- ### With Jamf Pro 9.99, "Semantic Versioning" is used, see http://semver.org/
382
- ###
383
- ### For versions less than 9.99 parsing is like this:
384
- ### - Digits before the first dot are the Major Version
385
- ### - The first digit after the first dot is the Minor Version
386
- ### - Any other digits after the first dot but before a non-digit
387
- ### are the Revision
388
- ### - Anything after a second dot is the build identifier
389
- ### - Any non-digit anywhere means that it and everything after it
390
- ### are the build identifier
391
- ###
392
- ### So 9.32 becomes major-9, minor-3, rev-2, build-''
393
- ### and 9.32.3764 becomes major-9, minor-3, rev-2, build-3764
394
- ### and 9.32a3764 becomes major-9, minor-3, rev-2, build-a3764
395
- ### and 9.32a1234.t234 becomes major-9, minor-3, rev-2, build-a1234.t234
396
- ###
397
- ### This old style method of parsing will break if digits between the first
398
- ### dot and the second (or the end) ever gets above 99, since '100' will
399
- ### become minor-1, rev-0
400
- ###
401
- ### This method returns a Hash with these keys:
402
- ### * :major => the major version, Integer
403
- ### * :minor => the minor version, Integor
404
- ### * :maint => the revision, Integer
405
- ### (this is also available with the keys :patch and :revision)
406
- ### * :build => the revision, String
407
- ### * :version => a Gem::Version object built from :major, :minor, :revision
408
- ### which can be easily compared with other Gem::Version objects.
409
- ###
410
- ### @param version[String] a JSS version number from the API
411
- ###
412
- ### @return [Hash{Symbol => String, Gem::Version}] the parsed version data.
413
- ###
371
+ # Parse a JSS Version number into something comparable.
372
+ #
373
+ # With Jamf Pro 9.99, "Semantic Versioning" is used, see http://semver.org/
374
+ #
375
+ # For versions less than 9.99 parsing is like this:
376
+ # - Digits before the first dot are the Major Version
377
+ # - The first digit after the first dot is the Minor Version
378
+ # - Any other digits after the first dot but before a non-digit
379
+ # are the Revision
380
+ # - Anything after a second dot is the build identifier
381
+ # - Any non-digit anywhere means that it and everything after it
382
+ # are the build identifier
383
+ #
384
+ # So 9.32 becomes major-9, minor-3, rev-2, build-''
385
+ # and 9.32.3764 becomes major-9, minor-3, rev-2, build-3764
386
+ # and 9.32a3764 becomes major-9, minor-3, rev-2, build-a3764
387
+ # and 9.32a1234.t234 becomes major-9, minor-3, rev-2, build-a1234.t234
388
+ #
389
+ # This old style method of parsing will break if digits between the first
390
+ # dot and the second (or the end) ever gets above 99, since '100' will
391
+ # become minor-1, rev-0
392
+ #
393
+ # This method returns a Hash with these keys:
394
+ # * :major => the major version, Integer
395
+ # * :minor => the minor version, Integor
396
+ # * :maint => the revision, Integer
397
+ # (this is also available with the keys :patch and :revision)
398
+ # * :build => the revision, String
399
+ # * :version => a Gem::Version object built from :major, :minor, :revision
400
+ # which can be easily compared with other Gem::Version objects.
401
+ #
402
+ # @param version[String] a JSS version number from the API
403
+ #
404
+ # @return [Hash{Symbol => String, Gem::Version}] the parsed version data.
405
+ #
414
406
  def self.parse_jss_version(version)
415
407
  major, second_part, *_rest = version.split('.')
416
408
  raise JSS::InvalidDataError, 'JSS Versions must start with "x.x" where x is one or more digits' unless major =~ /\d$/ && second_part =~ /^\d/
@@ -434,11 +426,11 @@ module JSS
434
426
  maint: revision.to_i,
435
427
  patch: revision.to_i,
436
428
  build: build,
437
- version: Gem::Version.new(version)
429
+ # version: Gem::Version.new(version)
430
+ version: Gem::Version.new("#{major}.#{minor}.#{revision}#{build}")
438
431
  }
439
432
  end # parse_jss_version_oldstyle
440
433
 
441
-
442
434
  # (see parse_jss_version)
443
435
  def self.parse_jss_version_oldstyle(version)
444
436
  version =~ /^(\d+?)\.(.*)$/
@@ -475,49 +467,47 @@ module JSS
475
467
  }
476
468
  end # parse_jss_version_oldstyle
477
469
 
478
- ### @return [Boolean] is this code running as root?
479
- ###
470
+ # @return [Boolean] is this code running as root?
471
+ #
480
472
  def self.superuser?
481
- Process.euid == 0
473
+ Process.euid.zero?
482
474
  end
483
475
 
484
- ### Retrive one or all lines from whatever was piped to standard input.
485
- ###
486
- ### Standard input is read completely the first time this method is called
487
- ### and the lines are stored as an Array in the module var @@stdin_lines
488
- ###
489
- ### @param line[Integer] which line of stdin is being retrieved.
490
- ### The default is zero (0) which returns all of stdin as a single string.
491
- ###
492
- ### @return [String, nil] the requested ling of stdin, or nil if it doesn't exist.
493
- ###
476
+ # Retrive one or all lines from whatever was piped to standard input.
477
+ #
478
+ # Standard input is read completely the first time this method is called
479
+ # and the lines are stored as an Array in the module var @stdin_lines
480
+ #
481
+ # @param line[Integer] which line of stdin is being retrieved.
482
+ # The default is zero (0) which returns all of stdin as a single string.
483
+ #
484
+ # @return [String, nil] the requested ling of stdin, or nil if it doesn't exist.
485
+ #
494
486
  def self.stdin(line = 0)
495
- @@stdin_lines ||= ($stdin.tty? ? [] : $stdin.read.lines.map{|line| line.chomp("\n") })
487
+ @stdin_lines ||= ($stdin.tty? ? [] : $stdin.read.lines.map { |l| l.chomp("\n") })
496
488
 
497
- return @@stdin_lines.join("\n") if line <= 0
489
+ return @stdin_lines.join("\n") if line <= 0
498
490
  idx = line - 1
499
- return @@stdin_lines[idx]
491
+ @stdin_lines[idx]
500
492
  end
501
493
 
502
- ### Prompt for a password in a terminal.
503
- ###
504
- ### @param message [String] the prompt message to display
505
- ###
506
- ### @return [String] the text typed by the user
507
- ###
494
+ # Prompt for a password in a terminal.
495
+ #
496
+ # @param message [String] the prompt message to display
497
+ #
498
+ # @return [String] the text typed by the user
499
+ #
508
500
  def self.prompt_for_password(message)
509
-
510
501
  begin
511
502
  $stdin.reopen '/dev/tty' unless $stdin.tty?
512
503
  $stderr.print "#{message} "
513
- system "/bin/stty -echo"
504
+ system '/bin/stty -echo'
514
505
  pw = $stdin.gets.chomp("\n")
515
506
  puts
516
507
  ensure
517
- system "/bin/stty echo"
508
+ system '/bin/stty echo'
518
509
  end # begin
519
- return pw
510
+ pw
520
511
  end
521
512
 
522
-
523
513
  end # module
data/lib/jss/version.rb CHANGED
@@ -27,6 +27,6 @@
27
27
  module JSS
28
28
 
29
29
  ### The version of the JSS ruby gem
30
- VERSION = '0.8.1'.freeze
30
+ VERSION = '0.8.2'.freeze
31
31
 
32
32
  end # module
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-jss
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Lasell
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-06-06 00:00:00.000000000 Z
12
+ date: 2017-06-07 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: plist