ruby-jss 1.0.0b2 → 1.0.0b6
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 +5 -5
- data/.yardopts +1 -1
- data/CHANGES.md +46 -8
- data/README.md +26 -27
- data/bin/cgrouper +2 -2
- data/bin/jamfHelperBackgrounder +0 -2
- data/bin/netseg-update +3 -4
- data/data/ruby-jss.conf.example +2 -8
- data/lib/jss/api_connection.rb +6 -3
- data/lib/jss/api_object/advanced_search.rb +1 -1
- data/lib/jss/api_object/computer_invitation.rb +1 -1
- data/lib/jss/api_object/criteriable.rb +1 -1
- data/lib/jss/api_object/ebook.rb +25 -0
- data/lib/jss/api_object/group.rb +1 -1
- data/lib/jss/api_object/mobile_device_application.rb +1 -1
- data/lib/jss/api_object/patch_title.rb +98 -46
- data/lib/jss/api_object/peripheral.rb +2 -2
- data/lib/jss/api_object/sitable.rb +1 -1
- data/lib/jss/api_object.rb +2 -2
- data/lib/jss/client/management_action.rb +2 -2
- data/lib/jss/utility.rb +1 -1
- data/lib/jss/validate.rb +32 -29
- data/lib/jss/version.rb +1 -1
- data/test/README.md +149 -0
- data/test/bin/runtests +290 -0
- data/test/lib/testhelper/auth.rb +275 -0
- data/test/lib/testhelper/patch_mgmt.rb +123 -0
- data/test/lib/testhelper.rb +69 -0
- data/test/specs/api_connection_spec.rb +57 -0
- data/test/specs/patch01_source_spec.rb +54 -0
- data/test/specs/patch02_internal_source_spec.rb +88 -0
- data/test/specs/patch03_external_source_spec.rb +120 -0
- data/test/specs/patch04_titles_spec.rb +207 -0
- data/test/specs/patch05_policies_spec.rb +119 -0
- data/test/specs/patch06_cleanup_spec.rb +52 -0
- data/test/specs/policy_spec.rb +112 -0
- metadata +16 -3
@@ -0,0 +1,275 @@
|
|
1
|
+
### Copyright 2018 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
|
+
module JSSTestHelper
|
27
|
+
|
28
|
+
# auth
|
29
|
+
module Auth
|
30
|
+
|
31
|
+
KEYCHAIN_LABEL_BASE = 'com.pixar.ruby-jss.testing'.freeze
|
32
|
+
|
33
|
+
KEYCHAIN_JSS_LABEL = KEYCHAIN_LABEL_BASE + '.api'
|
34
|
+
KEYCHAIN_DB_LABEL = KEYCHAIN_LABEL_BASE + '.db'
|
35
|
+
KEYCHAIN_DIST_LABEL = KEYCHAIN_LABEL_BASE + '.distribution'
|
36
|
+
|
37
|
+
KEYCHAIN_DIST_ACCT = 'From JSS'.freeze
|
38
|
+
|
39
|
+
KEYCHAIN_LABELS = {
|
40
|
+
jss: KEYCHAIN_JSS_LABEL,
|
41
|
+
db: KEYCHAIN_DB_LABEL,
|
42
|
+
dist: KEYCHAIN_DIST_LABEL
|
43
|
+
}.freeze
|
44
|
+
|
45
|
+
module_function
|
46
|
+
|
47
|
+
# return the user's API password, prompting for it if we don't already have
|
48
|
+
# it
|
49
|
+
#
|
50
|
+
def api_pw(server: nil, port: nil, user: nil)
|
51
|
+
return @api_pw if @api_pw
|
52
|
+
# If we're here, we need to get the pw via prompt
|
53
|
+
@api_pw = prompt_for_password prompt: "Enter the API password for #{user}@#{server}:#{port}" do |apw|
|
54
|
+
begin
|
55
|
+
JSS.api.disconnect
|
56
|
+
JSS.api.connect user: user, pw: apw, server: server, port: port
|
57
|
+
true
|
58
|
+
rescue JSS::AuthenticationError
|
59
|
+
false
|
60
|
+
end # begin
|
61
|
+
end # do apw
|
62
|
+
raise JSS::AuthenticationError, "Incorrect API password for #{user}@#{server}:#{port}" unless @api_pw
|
63
|
+
@api_pw
|
64
|
+
end
|
65
|
+
|
66
|
+
# return the server, port, and user, which we might have gotten fromthe keychain
|
67
|
+
def connect_to_api(server: nil, user: nil, port: nil, pw: nil)
|
68
|
+
return if JSS.api.connected?
|
69
|
+
|
70
|
+
JSS.api.connect server: server, port: port, user: user, pw: pw
|
71
|
+
@api_pw = pw
|
72
|
+
{ server: JSS.api.hostname, port: JSS.api.port, user: JSS.api.jss_user }
|
73
|
+
rescue JSS::AuthenticationError
|
74
|
+
# If we're here, we need to prompt for the pw
|
75
|
+
pw = api_pw server: server, port: port, user: user
|
76
|
+
ensure
|
77
|
+
# store the pw
|
78
|
+
save_rw_credentials label: KEYCHAIN_JSS_LABEL, acct: JSS.api.jss_user, server: JSS.api.hostname, port: JSS.api.port, pw: pw if JSS.api.connected?
|
79
|
+
end
|
80
|
+
|
81
|
+
# TODO: update this as API above so there's only one per keychain.
|
82
|
+
def db_pw
|
83
|
+
return @db_pw if @db_pw
|
84
|
+
|
85
|
+
# If we're here, we need to get the passwd for the user
|
86
|
+
@db_pw = prompt_for_password prompt: "Enter the MySQL password for #{@db_user}@#{@db_server}" do |apw|
|
87
|
+
begin
|
88
|
+
JSS::DB_CNX.disconnect
|
89
|
+
JSS::DB_CNX.connect server: @db_server, user: @db_user, pw: apw
|
90
|
+
true
|
91
|
+
rescue Mysql::ServerError::AccessDeniedError
|
92
|
+
false
|
93
|
+
end # begin
|
94
|
+
end # do apw
|
95
|
+
|
96
|
+
raise JSS::AuthenticationError, "Incorrect MySQL password for #{@db_user}@#{@db_server}" unless @db_pw
|
97
|
+
@db_pw
|
98
|
+
end
|
99
|
+
|
100
|
+
# TODO: update this as API above so there's only one per keychain.
|
101
|
+
def connect_to_db(server: nil, user: nil)
|
102
|
+
return if JSS::DB_CNX.connected?
|
103
|
+
@db_server = server ? server : JSS::CONFIG.api_server_name
|
104
|
+
@db_user = user
|
105
|
+
|
106
|
+
raise 'No db_server_name defined in /etc/ruby-jss.conf. Please specify with --db-server' unless @db_server
|
107
|
+
|
108
|
+
# look in the keychain
|
109
|
+
keychain_creds = rw_credentials_from_keychain(:db, @db_server, @db_user)
|
110
|
+
|
111
|
+
# did we get a user/pw? Use it
|
112
|
+
if keychain_creds
|
113
|
+
@db_user ||= keychain_creds[:user]
|
114
|
+
begin
|
115
|
+
JSS::DB_CNX.connect server: @db_server, user: @db_user, pw: keychain_creds[:password]
|
116
|
+
|
117
|
+
return
|
118
|
+
rescue Mysql::ServerError::AccessDeniedError
|
119
|
+
# re-prompt if bad pw in keychain
|
120
|
+
say "Stored MySQL password for #{@db_user}@#{@db_server} is incorrect"
|
121
|
+
end # begin
|
122
|
+
else
|
123
|
+
# Couldn't find a stored user for server, and no user given on CLI - error.
|
124
|
+
raise "No user stored for MySQL server '#{@db_server}'. Please specify with --db-user" unless @db_user
|
125
|
+
end
|
126
|
+
|
127
|
+
# If we're here, we need to get the passwd for the user
|
128
|
+
pw = db_pw
|
129
|
+
|
130
|
+
# store the pw
|
131
|
+
save_rw_credentials KEYCHAIN_DB_LABEL, @db_user, @db_server, pw
|
132
|
+
end
|
133
|
+
|
134
|
+
# TODO: pass in the API server for which we want the dist point pw
|
135
|
+
# must be connected to api
|
136
|
+
# and make it like API connection above, 1 per keychain.
|
137
|
+
def dist_point_pw
|
138
|
+
keychain_creds = rw_credentials_from_keychain(:db, @api_server, KEYCHAIN_DIST_ACCT)
|
139
|
+
if keychain_creds
|
140
|
+
@distpw = keychain_creds[:password]
|
141
|
+
return @distpw if JSS::DistributionPoint.master_distribution_point.check_pw :rw, distpw
|
142
|
+
end
|
143
|
+
|
144
|
+
# if we're here, there was no stored pw or it was incorrect
|
145
|
+
|
146
|
+
# If we're here, we need to get the passwd for the master dist point
|
147
|
+
prmpt = "Enter the RW password for the Master Distribution Point on JSS #{@api_server}"
|
148
|
+
@distpw = prompt_for_password prompt: prmpt do |apw|
|
149
|
+
JSS::DistributionPoint.master_distribution_point.check_pw :rw, apw
|
150
|
+
end # do apw
|
151
|
+
|
152
|
+
raise JSS::AuthenticationError, "Incorrect RW password for the Master Distribution Point on JSS #{@api_server}" unless @distpw
|
153
|
+
|
154
|
+
# store the pw
|
155
|
+
save_rw_credentials KEYCHAIN_DIST_LABEL, KEYCHAIN_DIST_ACCT, @api_server, @distpw
|
156
|
+
@distpw
|
157
|
+
end
|
158
|
+
|
159
|
+
# Fetch read-write credentials from the login keychain
|
160
|
+
#
|
161
|
+
# If the login keychain is locked, the user will be prompted
|
162
|
+
# to unlock it in the GUI.
|
163
|
+
#
|
164
|
+
# @param kind[Symbol] which kind of credentials? :jss, :db, or :dist
|
165
|
+
#
|
166
|
+
# @return [Hash{Symbol => String}, nil] A Hash with :server, :user and :password
|
167
|
+
# values, nil if no matching keychain item.
|
168
|
+
#
|
169
|
+
def rw_credentials_from_keychain(kind)
|
170
|
+
Keychain.user_interaction_allowed = true
|
171
|
+
unlock_keychain
|
172
|
+
label = KEYCHAIN_LABELS[kind]
|
173
|
+
raise JSS::InvalidDataError, "argument must be one of :#{RW_CREDENTIAL_KINDS.join ', :'}" unless label
|
174
|
+
|
175
|
+
pw_search = { label: label }
|
176
|
+
pw_item = Keychain.default.internet_passwords.where(pw_search).first
|
177
|
+
|
178
|
+
return nil unless pw_item
|
179
|
+
|
180
|
+
{ server: pw_item.server, user: pw_item.account, pw: pw_item.password, port: pw_item.port }
|
181
|
+
end
|
182
|
+
|
183
|
+
# Save the credentials in the login keychain
|
184
|
+
#
|
185
|
+
# @param user[String] the username to save
|
186
|
+
#
|
187
|
+
# @param pw[String] the password to save with the username
|
188
|
+
#
|
189
|
+
# @return [void]
|
190
|
+
#
|
191
|
+
def save_rw_credentials(label: nil, acct: nil, server: nil, pw: nil, port: nil)
|
192
|
+
Keychain.default.internet_passwords.where(label: label).all.each(&:delete)
|
193
|
+
item = Keychain.default.internet_passwords.create label: label, account: acct, server: server, password: pw, port: port
|
194
|
+
item.save!
|
195
|
+
end
|
196
|
+
|
197
|
+
# Prompt the user to unlock the default keychain
|
198
|
+
#
|
199
|
+
# @return [void]
|
200
|
+
#
|
201
|
+
def unlock_keychain
|
202
|
+
return true unless Keychain.default.locked?
|
203
|
+
unlocked = prompt_for_password prompt: 'Enter your keychain password' do |pw|
|
204
|
+
begin
|
205
|
+
Keychain.default.unlock! pw
|
206
|
+
true
|
207
|
+
rescue Keychain::AuthFailedError
|
208
|
+
false
|
209
|
+
end # begin
|
210
|
+
end # prompt for pass
|
211
|
+
raise JSS::AuthenticationError, 'Failed to unlock default keychain' unless unlocked
|
212
|
+
end # unlock keychain
|
213
|
+
|
214
|
+
# Prompt the user for a password in the shell
|
215
|
+
# Returns:
|
216
|
+
# - a valid password, or
|
217
|
+
# - false if no valid password after the max number of tries
|
218
|
+
#
|
219
|
+
# Displays the provided promp. Passes what the user types to the block you
|
220
|
+
# provide, which must return a Boolean indicating if the password was correct.
|
221
|
+
#
|
222
|
+
# @param prompt[String] The message asking for the password
|
223
|
+
#
|
224
|
+
# @option max_tries[Integer] The max number of times to let the
|
225
|
+
# user enter the passwd. Defaults to 3
|
226
|
+
#
|
227
|
+
# @option retry_msg[String] the text to display after a failure,
|
228
|
+
# but before :max_tries failures. Defaults to "Try again: " followed
|
229
|
+
# by the text arg.
|
230
|
+
#
|
231
|
+
# @option failed_msg[String] The message to display after :max_tries
|
232
|
+
# failures. Defaults to "Too many failed attempts"
|
233
|
+
#
|
234
|
+
# @yield The block should figure out if the user typed the correct password
|
235
|
+
#
|
236
|
+
# @yieldparam pw [String] The password typed by the user in the input field
|
237
|
+
#
|
238
|
+
# @yieldreturn [Boolean] Was the password correct?
|
239
|
+
#
|
240
|
+
# @return [String] The validated password
|
241
|
+
# @return [false] The user failed after max_tries: attempts.
|
242
|
+
#
|
243
|
+
#
|
244
|
+
def prompt_for_password(**options)
|
245
|
+
colon = ':'
|
246
|
+
# set defaults
|
247
|
+
options[:prompt] ||= 'Enter your password:'
|
248
|
+
options[:prompt] << colon unless options[:prompt].end_with? colon
|
249
|
+
options[:max_tries] ||= 3
|
250
|
+
options[:retry_msg] ||= "Try Again. #{options[:prompt]}"
|
251
|
+
options[:failed_msg] ||= 'Too many failed attempts'
|
252
|
+
|
253
|
+
tries = 0
|
254
|
+
|
255
|
+
prompt = options[:prompt]
|
256
|
+
|
257
|
+
while tries < options[:max_tries]
|
258
|
+
print "#{prompt} "
|
259
|
+
system 'stty -echo'
|
260
|
+
pw = $stdin.gets.chomp
|
261
|
+
puts
|
262
|
+
system 'stty echo'
|
263
|
+
return pw if yield pw
|
264
|
+
prompt = options[:retry_msg]
|
265
|
+
tries += 1
|
266
|
+
end
|
267
|
+
puts options[:failed_msg]
|
268
|
+
false
|
269
|
+
ensure # make sure terminal is usable at the end of this
|
270
|
+
system 'stty echo'
|
271
|
+
end # prompt_for_password
|
272
|
+
|
273
|
+
end # module auth
|
274
|
+
|
275
|
+
end # module JSSTestHelper
|
@@ -0,0 +1,123 @@
|
|
1
|
+
### Copyright 2018 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
|
+
module JSSTestHelper
|
27
|
+
|
28
|
+
# auth
|
29
|
+
module PatchMgmt
|
30
|
+
|
31
|
+
EXT_SRC_NAME = 'rubyjss-testPatchSource.company.com'.freeze
|
32
|
+
EXT_SRC_PORT = 8843
|
33
|
+
|
34
|
+
PATCH_TITLE_NAME = 'rubyjss-testPatchTitle'.freeze
|
35
|
+
PATCH_TITLE_SOURCE = 'Jamf'.freeze
|
36
|
+
|
37
|
+
PATCHCPOL_NAME = 'rubyjss-testPatchPolicy'.freeze
|
38
|
+
|
39
|
+
module_function
|
40
|
+
|
41
|
+
# Sources
|
42
|
+
|
43
|
+
def internal_src
|
44
|
+
@internal_src ||= JSS::PatchInternalSource.fetch id: 1
|
45
|
+
end
|
46
|
+
|
47
|
+
def external_src
|
48
|
+
@external_src ||= JSS::PatchExternalSource.make name: EXT_SRC_NAME
|
49
|
+
end
|
50
|
+
|
51
|
+
def refetch_external_src
|
52
|
+
@external_src = JSS::PatchExternalSource.fetch name: EXT_SRC_NAME
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete_external_src
|
56
|
+
return [] unless JSS::PatchExternalSource.all_names(:refresh).include? EXT_SRC_NAME
|
57
|
+
JSS::PatchExternalSource.delete JSS::PatchExternalSource.map_all_ids_to(:name).invert[EXT_SRC_NAME]
|
58
|
+
end
|
59
|
+
|
60
|
+
# Titles
|
61
|
+
|
62
|
+
def name_id
|
63
|
+
@name_id ||= JSS::PatchInternalSource.available_name_ids(1).sample
|
64
|
+
end
|
65
|
+
|
66
|
+
def title(refresh = false)
|
67
|
+
@title = nil if refresh
|
68
|
+
return @title if @title
|
69
|
+
@title =
|
70
|
+
if JSS::PatchTitle.all_names.include? PATCH_TITLE_NAME
|
71
|
+
JSS::PatchTitle.fetch source: PATCH_TITLE_SOURCE, name_id: name_id
|
72
|
+
else
|
73
|
+
JSS::PatchTitle.make name: PATCH_TITLE_NAME, source: PATCH_TITLE_SOURCE, name_id: name_id
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def delete_title
|
78
|
+
return [] unless JSS::PatchTitle.all_names(:refresh).include? PATCH_TITLE_NAME
|
79
|
+
JSS::PatchTitle.delete JSS::PatchTitle.map_all_ids_to(:name).invert[PATCH_TITLE_NAME]
|
80
|
+
end
|
81
|
+
|
82
|
+
# Versions
|
83
|
+
|
84
|
+
def version_key
|
85
|
+
@version_key ||= title.versions.keys.sample
|
86
|
+
end
|
87
|
+
|
88
|
+
# Patch Policies
|
89
|
+
|
90
|
+
def policy(refresh = false)
|
91
|
+
@policy = nil if refresh
|
92
|
+
return @policy if @policy
|
93
|
+
|
94
|
+
# make sure we have a title with which to create a patch pol
|
95
|
+
unless title.in_jss
|
96
|
+
title.source_id = 1 unless title.source_id
|
97
|
+
title.name_id = name_id unless title.name_id
|
98
|
+
title.save
|
99
|
+
end
|
100
|
+
|
101
|
+
# make sre the desired version has a package
|
102
|
+
unless title.versions[version_key].package_id.is_a? Integer
|
103
|
+
title.versions[version_key].package = JSS::Package.all_ids.sample
|
104
|
+
title.save
|
105
|
+
end
|
106
|
+
|
107
|
+
# if the policy exists fetch it, otherwise make it
|
108
|
+
@policy =
|
109
|
+
if JSS::PatchPolicy.all_names(:refresh).include? PATCHCPOL_NAME
|
110
|
+
JSS::PatchPolicy.fetch name: PATCHCPOL_NAME
|
111
|
+
else
|
112
|
+
JSS::PatchPolicy.make name: PATCHCPOL_NAME, patch_title: title
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def delete_policy
|
117
|
+
return [] unless JSS::PatchPolicy.all_names(:refresh).include? PATCHCPOL_NAME
|
118
|
+
JSS::PatchPolicy.delete JSS::PatchPolicy.map_all_ids_to(:name).invert[PATCHCPOL_NAME]
|
119
|
+
end
|
120
|
+
|
121
|
+
end # module PatchMgmt
|
122
|
+
|
123
|
+
end # module JSSTestHelper
|
@@ -0,0 +1,69 @@
|
|
1
|
+
### Copyright 2018 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
|
+
# Methods and constants for the tests
|
27
|
+
module JSSTestHelper
|
28
|
+
|
29
|
+
TOP_PREFIX = '>>>>>'.freeze
|
30
|
+
TEST_PREFIX = '---->'.freeze
|
31
|
+
|
32
|
+
ERROR_PREFIX1 = '****-> ERROR in :'.freeze
|
33
|
+
ERROR_PREFIX2 = '****-> '.freeze
|
34
|
+
|
35
|
+
module_function
|
36
|
+
|
37
|
+
def say(msg, from: :top)
|
38
|
+
msgs = msg.is_a?(Array) ? msg : [msg]
|
39
|
+
prefix =
|
40
|
+
if from == :top
|
41
|
+
TOP_PREFIX
|
42
|
+
else
|
43
|
+
puts # for interlacing with minitest's dots
|
44
|
+
"-- #{from} #{TEST_PREFIX}"
|
45
|
+
end
|
46
|
+
msgs.each { |m| puts "#{prefix} #{m}" }
|
47
|
+
end
|
48
|
+
|
49
|
+
def report(a_problem)
|
50
|
+
if a_problem.is_a? Exception
|
51
|
+
puts caller_locations
|
52
|
+
src = caller_locations(5..5).first
|
53
|
+
msg = a_problem.to_s
|
54
|
+
else
|
55
|
+
src = caller_locations(3..3).first
|
56
|
+
msg = a_problem
|
57
|
+
end
|
58
|
+
location = "method '#{src.label}' at line #{src.lineno} of #{File.basename src.path}"
|
59
|
+
@errors << "#{location}: #{msg}"
|
60
|
+
puts " #{ERROR_PREFIX1} #{location}"
|
61
|
+
puts " #{ERROR_PREFIX2} #{msg}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end # module JSSTestHelper
|
65
|
+
|
66
|
+
# load in the rest of the module
|
67
|
+
libdir = Pathname.new File.dirname(__FILE__)
|
68
|
+
moduledir = libdir + 'testhelper'
|
69
|
+
moduledir.children.each { |mf| load mf.to_s }
|
@@ -0,0 +1,57 @@
|
|
1
|
+
### Copyright 2018 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
|
+
describe JSS::APIConnection do
|
27
|
+
|
28
|
+
##### Constants
|
29
|
+
|
30
|
+
TEST_CONNECTION_NAME = 'testconnection'.freeze
|
31
|
+
|
32
|
+
##### Specs
|
33
|
+
|
34
|
+
# this happens before each 'it' block below.
|
35
|
+
before do
|
36
|
+
@newcon = JSS::APIConnection.new(
|
37
|
+
server: JSS.api.hostname,
|
38
|
+
user: JSS.api.jss_user,
|
39
|
+
pw: JSSTestHelper::Auth.api_pw(server: nil, port: nil, user: nil),
|
40
|
+
name: TEST_CONNECTION_NAME
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'can be created' do
|
45
|
+
@newcon.must_be_instance_of JSS::APIConnection
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'has a settable name at creation' do
|
49
|
+
@newcon.name.must_equal TEST_CONNECTION_NAME
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'can be made default' do
|
53
|
+
JSS.use_api_connection @newcon
|
54
|
+
JSS.api.name.must_equal TEST_CONNECTION_NAME
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
### Copyright 2018 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
|
+
# Patch Source MetaClass
|
27
|
+
#
|
28
|
+
describe JSS::PatchSource do
|
29
|
+
|
30
|
+
##### Specs
|
31
|
+
|
32
|
+
it 'can list all patch sources' do
|
33
|
+
JSS::PatchSource.all.must_be_instance_of Array
|
34
|
+
JSS::PatchSource.all.first.must_be_instance_of Hash
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'can be used to fetch subclass' do
|
38
|
+
JSS::PatchSource.fetch(id: 1).must_be_instance_of JSS::PatchInternalSource
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'can list available titles for a subclass from class method' do
|
42
|
+
titles = JSS::PatchSource.available_titles 1
|
43
|
+
titles.must_be_instance_of Array
|
44
|
+
titles.first.must_be_instance_of Hash
|
45
|
+
titles.first[:last_modified].must_be_instance_of Time
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'can list available name_ids for a subclass from class method' do
|
49
|
+
name_ids = JSS::PatchSource.available_name_ids 1
|
50
|
+
name_ids.must_be_instance_of Array
|
51
|
+
name_ids.first.must_be_instance_of String
|
52
|
+
end
|
53
|
+
|
54
|
+
end # describe JSS::PatchSource
|
@@ -0,0 +1,88 @@
|
|
1
|
+
### Copyright 2018 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
|
+
# Internal Sources
|
27
|
+
#
|
28
|
+
describe JSS::PatchInternalSource do
|
29
|
+
|
30
|
+
##### Class Methods
|
31
|
+
|
32
|
+
##### Instance Methods
|
33
|
+
|
34
|
+
# shortcut
|
35
|
+
def src
|
36
|
+
JSSTestHelper::PatchMgmt.internal_src
|
37
|
+
end
|
38
|
+
|
39
|
+
##### Specs
|
40
|
+
|
41
|
+
it 'cannot be created' do
|
42
|
+
proc { JSS::PatchInternalSource.make name: 'foo' }.must_raise JSS::UnsupportedError
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'cannot be modified' do
|
46
|
+
proc { src.host_name = 'foo' }.must_raise NoMethodError
|
47
|
+
proc { src.port = 'foo' }.must_raise NoMethodError
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'cannot be disabled' do
|
51
|
+
proc { src.disable }.must_raise NoMethodError
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'cannot be deleted' do
|
55
|
+
proc { src.delete }.must_raise JSS::UnsupportedError
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'tells us if it is enabled' do
|
59
|
+
JSS::TRUE_FALSE.must_include src.enabled?
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'tells us its hostname' do
|
63
|
+
src.host_name.must_be_instance_of String
|
64
|
+
src.host_name.wont_be_empty
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'tells us its port' do
|
68
|
+
src.port.must_be_kind_of Integer
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'tells us if ssl is enabled' do
|
72
|
+
JSS::TRUE_FALSE.must_include src.ssl_enabled?
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'lists its available titles' do
|
76
|
+
titles = src.available_titles
|
77
|
+
titles.must_be_instance_of Array
|
78
|
+
titles.first.must_be_instance_of Hash
|
79
|
+
titles.first[:last_modified].must_be_instance_of Time
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'lists its available name_ids' do
|
83
|
+
name_ids = src.available_name_ids
|
84
|
+
name_ids.must_be_instance_of Array
|
85
|
+
name_ids.first.must_be_instance_of String
|
86
|
+
end
|
87
|
+
|
88
|
+
end # describe JSS::PatchInternalSource
|