rhc 1.2.7 → 1.3.8
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rhc +6 -8
- data/bin/rhc-chk +23 -10
- data/features/domain.feature +1 -1
- data/features/lib/rhc_helper.rb +3 -2
- data/features/lib/rhc_helper/api.rb +7 -0
- data/features/lib/rhc_helper/app.rb +8 -10
- data/features/lib/rhc_helper/domain.rb +2 -1
- data/features/lib/rhc_helper/runnable.rb +2 -24
- data/features/sshkey.feature +3 -3
- data/features/step_definitions/cartridge_steps.rb +6 -6
- data/features/step_definitions/client_steps.rb +0 -1
- data/features/step_definitions/sshkey_steps.rb +2 -2
- data/features/support/before_hooks.rb +0 -1
- data/features/support/env.rb +5 -3
- data/lib/rhc-common.rb +1 -1
- data/lib/rhc.rb +9 -8
- data/lib/rhc/auth.rb +3 -0
- data/lib/rhc/auth/basic.rb +54 -0
- data/lib/rhc/cartridge_helpers.rb +11 -5
- data/lib/rhc/cli.rb +4 -2
- data/lib/rhc/command_runner.rb +35 -30
- data/lib/rhc/commands.rb +127 -18
- data/lib/rhc/commands/account.rb +24 -0
- data/lib/rhc/commands/alias.rb +1 -1
- data/lib/rhc/commands/app.rb +210 -209
- data/lib/rhc/commands/apps.rb +22 -0
- data/lib/rhc/commands/base.rb +10 -77
- data/lib/rhc/commands/cartridge.rb +35 -35
- data/lib/rhc/commands/domain.rb +20 -13
- data/lib/rhc/commands/git_clone.rb +30 -0
- data/lib/rhc/commands/{port-forward.rb → port_forward.rb} +3 -3
- data/lib/rhc/commands/server.rb +28 -16
- data/lib/rhc/commands/setup.rb +18 -1
- data/lib/rhc/commands/snapshot.rb +4 -4
- data/lib/rhc/commands/sshkey.rb +4 -18
- data/lib/rhc/commands/tail.rb +32 -9
- data/lib/rhc/config.rb +168 -99
- data/lib/rhc/context_helper.rb +22 -9
- data/lib/rhc/core_ext.rb +41 -1
- data/lib/rhc/exceptions.rb +21 -5
- data/lib/rhc/git_helpers.rb +81 -0
- data/lib/rhc/help_formatter.rb +21 -1
- data/lib/rhc/helpers.rb +222 -87
- data/lib/rhc/output_helpers.rb +94 -110
- data/lib/rhc/rest.rb +15 -198
- data/lib/rhc/rest/api.rb +88 -0
- data/lib/rhc/rest/application.rb +29 -30
- data/lib/rhc/rest/attributes.rb +27 -0
- data/lib/rhc/rest/base.rb +29 -33
- data/lib/rhc/rest/cartridge.rb +42 -20
- data/lib/rhc/rest/client.rb +351 -89
- data/lib/rhc/rest/domain.rb +7 -13
- data/lib/rhc/rest/gear_group.rb +1 -1
- data/lib/rhc/rest/key.rb +7 -2
- data/lib/rhc/rest/mock.rb +609 -0
- data/lib/rhc/rest/user.rb +6 -2
- data/lib/rhc/{ssh_key_helpers.rb → ssh_helpers.rb} +58 -28
- data/lib/rhc/{targz.rb → tar_gz.rb} +0 -0
- data/lib/rhc/usage_templates/command_help.erb +4 -1
- data/lib/rhc/usage_templates/help.erb +24 -11
- data/lib/rhc/usage_templates/options_help.erb +14 -0
- data/lib/rhc/wizard.rb +283 -213
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +3 -371
- data/spec/rhc/auth_spec.rb +226 -0
- data/spec/rhc/cli_spec.rb +41 -14
- data/spec/rhc/command_spec.rb +44 -15
- data/spec/rhc/commands/account_spec.rb +41 -0
- data/spec/rhc/commands/alias_spec.rb +16 -15
- data/spec/rhc/commands/app_spec.rb +115 -92
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/cartridge_spec.rb +134 -112
- data/spec/rhc/commands/domain_spec.rb +31 -86
- data/spec/rhc/commands/git_clone_spec.rb +56 -0
- data/spec/rhc/commands/{port-forward_spec.rb → port_forward_spec.rb} +27 -32
- data/spec/rhc/commands/server_spec.rb +28 -3
- data/spec/rhc/commands/setup_spec.rb +29 -11
- data/spec/rhc/commands/snapshot_spec.rb +4 -3
- data/spec/rhc/commands/sshkey_spec.rb +24 -56
- data/spec/rhc/commands/tail_spec.rb +26 -9
- data/spec/rhc/commands/threaddump_spec.rb +12 -11
- data/spec/rhc/config_spec.rb +211 -164
- data/spec/rhc/context_spec.rb +2 -0
- data/spec/rhc/helpers_spec.rb +242 -46
- data/spec/rhc/rest_application_spec.rb +42 -28
- data/spec/rhc/rest_client_spec.rb +110 -93
- data/spec/rhc/rest_spec.rb +220 -131
- data/spec/rhc/targz_spec.rb +1 -1
- data/spec/rhc/wizard_spec.rb +435 -624
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +140 -6
- data/spec/wizard_spec_helper.rb +326 -0
- metadata +163 -143
- data/lib/rhc/client.rb +0 -17
- data/lib/rhc/git_helper.rb +0 -59
@@ -21,6 +21,18 @@ end
|
|
21
21
|
module RHC
|
22
22
|
module Rest
|
23
23
|
describe Client do
|
24
|
+
|
25
|
+
let(:endpoint){ mock_href }
|
26
|
+
let(:username){ nil }# mock_user }
|
27
|
+
let(:password){ nil }# mock_pass }
|
28
|
+
let(:use_debug){ false }
|
29
|
+
#let(:spec_versions){ nil }
|
30
|
+
let(:client) do
|
31
|
+
respond_to?(:spec_versions) ?
|
32
|
+
RHC::Rest::Client.new(endpoint, username, password, use_debug, spec_versions) :
|
33
|
+
RHC::Rest::Client.new(endpoint, username, password, use_debug)
|
34
|
+
end
|
35
|
+
|
24
36
|
let(:client_links) { mock_response_links(mock_client_links) }
|
25
37
|
let(:domain_0_links) { mock_response_links(mock_domain_links('mock_domain_0')) }
|
26
38
|
let(:domain_1_links) { mock_response_links(mock_domain_links('mock_domain_1')) }
|
@@ -35,32 +47,29 @@ module RHC
|
|
35
47
|
:status => 200
|
36
48
|
})
|
37
49
|
stub_api_request(:get, 'api_error').
|
38
|
-
to_raise(
|
50
|
+
to_raise(HTTPClient::BadResponseError.new('API Error'))
|
39
51
|
stub_api_request(:get, 'other_error').
|
40
|
-
to_raise(
|
52
|
+
to_raise(StandardError.new('Other Error'))
|
41
53
|
end
|
42
54
|
|
43
55
|
it "returns a client object from the required arguments" do
|
44
56
|
credentials = Base64.strict_encode64(mock_user + ":" + mock_pass)
|
45
|
-
client
|
46
|
-
@@headers['Authorization'].should == "Basic #{credentials}"
|
47
|
-
client.send(:links).should == client_links
|
57
|
+
client.api.send(:links).should == client_links
|
48
58
|
end
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
55
|
-
it "raises an error message if the API cannot be connected" do
|
56
|
-
expect { MockClient.new(mock_href('api_error'), mock_user, mock_pass) }.should raise_error
|
59
|
+
context "against an endpoint that won't connect" do
|
60
|
+
let(:endpoint){ mock_href('api_error') }
|
61
|
+
it "raises an error message" do
|
62
|
+
expect{ client.api }.should raise_error
|
63
|
+
end
|
57
64
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
context "against an endpoint that has a generic error" do
|
66
|
+
let(:endpoint){ mock_href('other_error') }
|
67
|
+
it "raises a generic error for any other error condition" do
|
68
|
+
expect{ client.api }.should raise_error(RHC::Rest::ConnectionException, "An unexpected error occured: Other Error")
|
69
|
+
end
|
61
70
|
end
|
62
71
|
end
|
63
|
-
|
72
|
+
|
64
73
|
describe "#new" do
|
65
74
|
context "when server supports API versions [1.0, 1.1]" do
|
66
75
|
before :each do
|
@@ -69,44 +78,36 @@ module RHC
|
|
69
78
|
:status => 200
|
70
79
|
})
|
71
80
|
stub_api_request(:get, 'api_error').
|
72
|
-
to_raise(
|
81
|
+
to_raise(HTTPClient::BadResponseError.new('API Error'))
|
73
82
|
stub_api_request(:get, 'other_error').
|
74
|
-
to_raise(
|
83
|
+
to_raise(StandardError.new('Other Error'))
|
75
84
|
end
|
76
|
-
|
85
|
+
|
77
86
|
context "when client is instantiated with [1.0, 1.1] as the preferred API versions" do
|
78
|
-
|
79
|
-
@client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.0, 1.1])
|
80
|
-
end
|
87
|
+
let(:spec_versions){ [1.0, 1.1] }
|
81
88
|
it "settles on 1.1 as the API version" do
|
82
|
-
|
89
|
+
client.api.api_version_negotiated.should == 1.1
|
83
90
|
end
|
84
91
|
end
|
85
|
-
|
92
|
+
|
86
93
|
context "when client is instantiated with [1.1, 1.0] as the preferred API versions" do
|
87
|
-
|
88
|
-
@client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.1, 1.0])
|
89
|
-
end
|
94
|
+
let(:spec_versions){ [1.1, 1.0] }
|
90
95
|
it "settles on 1.0 as the API version" do
|
91
|
-
|
96
|
+
client.api.api_version_negotiated.should == 1.0
|
92
97
|
end
|
93
98
|
end
|
94
|
-
|
99
|
+
|
95
100
|
context "when client is instantiated with [1.2, 1.3] as the preferred API versions" do
|
96
|
-
|
97
|
-
@client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.2, 1.3])
|
98
|
-
end
|
101
|
+
let(:spec_versions){ [1.2, 1.3] }
|
99
102
|
it "fails to negotiate an agreeable API version" do
|
100
|
-
|
103
|
+
client.api.api_version_negotiated.should be_nil
|
101
104
|
end
|
102
105
|
end
|
103
|
-
|
106
|
+
|
104
107
|
context "when client is instantiated with [1.1, 1.0, 1.3] as the preferred API versions" do
|
105
|
-
|
106
|
-
@client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.1, 1.0, 1.3])
|
107
|
-
end
|
108
|
+
let(:spec_versions){ [1.1, 1.0, 1.3] }
|
108
109
|
it "settles on 1.0 as the API version" do
|
109
|
-
|
110
|
+
client.api.api_version_negotiated.should == 1.0
|
110
111
|
end
|
111
112
|
end
|
112
113
|
end
|
@@ -121,7 +122,6 @@ module RHC
|
|
121
122
|
}.to_json,
|
122
123
|
:status => 200
|
123
124
|
})
|
124
|
-
@client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass)
|
125
125
|
end
|
126
126
|
|
127
127
|
context "#add_domain" do
|
@@ -139,7 +139,7 @@ module RHC
|
|
139
139
|
})
|
140
140
|
end
|
141
141
|
it "returns a domain object" do
|
142
|
-
domain =
|
142
|
+
domain = client.add_domain('mock_domain')
|
143
143
|
domain.class.should == RHC::Rest::Domain
|
144
144
|
domain.id.should == 'mock_domain'
|
145
145
|
domain.send(:links).should ==
|
@@ -170,10 +170,10 @@ module RHC
|
|
170
170
|
})
|
171
171
|
end
|
172
172
|
it "returns a list of existing domains" do
|
173
|
-
domains =
|
173
|
+
domains = client.domains
|
174
174
|
domains.length.should equal(2)
|
175
175
|
(0..1).each do |idx|
|
176
|
-
domains[idx].class.should
|
176
|
+
domains[idx].class.should == RHC::Rest::Domain
|
177
177
|
domains[idx].id.should == "mock_domain_#{idx}"
|
178
178
|
domains[idx].send(:links).should ==
|
179
179
|
mock_response_links(mock_domain_links("mock_domain_#{idx}"))
|
@@ -181,8 +181,9 @@ module RHC
|
|
181
181
|
end
|
182
182
|
it "returns an empty list when no domains exist" do
|
183
183
|
# Disregard the first response; this is for the previous expectiation.
|
184
|
-
domains =
|
185
|
-
|
184
|
+
domains = client.domains
|
185
|
+
client.instance_variable_set(:@domains, nil)
|
186
|
+
domains = client.domains
|
186
187
|
domains.length.should equal(0)
|
187
188
|
end
|
188
189
|
end
|
@@ -205,13 +206,13 @@ module RHC
|
|
205
206
|
end
|
206
207
|
it "returns a domain object for matching domain IDs" do
|
207
208
|
match = nil
|
208
|
-
expect { match =
|
209
|
+
expect { match = client.find_domain('mock_domain_0') }.should_not raise_error
|
209
210
|
|
210
211
|
match.id.should == 'mock_domain_0'
|
211
212
|
match.class.should == RHC::Rest::Domain
|
212
213
|
end
|
213
214
|
it "raise an error when no matching domain IDs can be found" do
|
214
|
-
expect {
|
215
|
+
expect { client.find_domain('mock_domain_2') }.should raise_error(RHC::DomainNotFoundException)
|
215
216
|
end
|
216
217
|
end
|
217
218
|
|
@@ -262,10 +263,10 @@ module RHC
|
|
262
263
|
})
|
263
264
|
end
|
264
265
|
it "returns application objects for matching application IDs" do
|
265
|
-
domain =
|
266
|
+
domain = client.domains[0]
|
266
267
|
domain.applications.each do |app|
|
267
268
|
match = domain.find_application(app.name)
|
268
|
-
match.class.should
|
269
|
+
match.class.should == RHC::Rest::Application
|
269
270
|
match.name.should == 'mock_app'
|
270
271
|
match.domain_id.should == "#{domain.id}"
|
271
272
|
match.send(:links).should ==
|
@@ -273,7 +274,30 @@ module RHC
|
|
273
274
|
end
|
274
275
|
end
|
275
276
|
it "Raises an excpetion when no matching applications can be found" do
|
276
|
-
expect {
|
277
|
+
expect { client.domains[0].find_application('no_match') }.should raise_error(RHC::ApplicationNotFoundException)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
describe RHC::Rest::Cartridge do
|
282
|
+
subject do
|
283
|
+
described_class.new({
|
284
|
+
:name => 'foo',
|
285
|
+
:links => mock_response_links([
|
286
|
+
['GET', 'broker/rest/cartridge', 'get']
|
287
|
+
])}, client)
|
288
|
+
end
|
289
|
+
context "when several messages are present" do
|
290
|
+
before do
|
291
|
+
stub_api_request(:get, 'broker/rest/cartridge', true).
|
292
|
+
with(:query => {:include => :status_messages}).
|
293
|
+
to_return(:body => {
|
294
|
+
:type => 'cartridge',
|
295
|
+
:data => {
|
296
|
+
:status_messages => [{:message => 'Test'}]
|
297
|
+
}
|
298
|
+
}.to_json)
|
299
|
+
end
|
300
|
+
its(:status){ should == [{'message' => 'Test'}] }
|
277
301
|
end
|
278
302
|
end
|
279
303
|
|
@@ -302,21 +326,22 @@ module RHC
|
|
302
326
|
})
|
303
327
|
end
|
304
328
|
it "returns a list of existing cartridges" do
|
305
|
-
carts =
|
329
|
+
carts = client.cartridges
|
306
330
|
carts.length.should equal(2)
|
307
331
|
(0..1).each do |idx|
|
308
|
-
carts[idx].class.should
|
332
|
+
carts[idx].class.should == RHC::Rest::Cartridge
|
309
333
|
carts[idx].name.should == "mock_cart_#{idx}"
|
310
334
|
carts[idx].type.should == "mock_cart_#{idx}_type"
|
311
335
|
carts[idx].send(:links).should ==
|
312
336
|
mock_response_links(mock_cart_links("mock_cart_#{idx}"))
|
313
337
|
end
|
314
338
|
end
|
315
|
-
it "
|
339
|
+
it "caches cartridges on the client" do
|
316
340
|
# Disregard the first response; this is for the previous expectiation.
|
317
|
-
|
318
|
-
|
319
|
-
|
341
|
+
old = client.cartridges.length
|
342
|
+
client.cartridges.length.should equal(old)
|
343
|
+
client.instance_variable_set(:@cartridges, nil)
|
344
|
+
client.cartridges.length.should equal(0)
|
320
345
|
end
|
321
346
|
end
|
322
347
|
|
@@ -344,20 +369,20 @@ module RHC
|
|
344
369
|
})
|
345
370
|
end
|
346
371
|
it "returns a list of cartridge objects for matching cartridges" do
|
347
|
-
matches =
|
372
|
+
matches = client.find_cartridges('mock_cart_0')
|
348
373
|
matches.length.should equal(1)
|
349
|
-
matches[0].class.should
|
374
|
+
matches[0].class.should == RHC::Rest::Cartridge
|
350
375
|
matches[0].name.should == 'mock_cart_0'
|
351
376
|
matches[0].type.should == 'mock_cart_0_type'
|
352
377
|
matches[0].send(:links).should ==
|
353
378
|
mock_response_links(mock_cart_links('mock_cart_0'))
|
354
379
|
end
|
355
380
|
it "returns an empty list when no matching cartridges can be found" do
|
356
|
-
matches =
|
381
|
+
matches = client.find_cartridges('no_match')
|
357
382
|
matches.length.should equal(0)
|
358
383
|
end
|
359
384
|
it "returns multiple cartridge matches" do
|
360
|
-
matches =
|
385
|
+
matches = client.find_cartridges :regex => "mock_cart_[0-9]"
|
361
386
|
matches.length.should equal(2)
|
362
387
|
end
|
363
388
|
end
|
@@ -376,8 +401,8 @@ module RHC
|
|
376
401
|
})
|
377
402
|
end
|
378
403
|
it "returns the user object associated with this client connection" do
|
379
|
-
user =
|
380
|
-
user.class.should
|
404
|
+
user = client.user
|
405
|
+
user.class.should == RHC::Rest::User
|
381
406
|
user.login.should == mock_user
|
382
407
|
user.send(:links).should == mock_response_links(mock_user_links)
|
383
408
|
end
|
@@ -415,9 +440,9 @@ module RHC
|
|
415
440
|
end
|
416
441
|
it "returns a list of key objects for matching keys" do
|
417
442
|
key = nil
|
418
|
-
expect { key =
|
443
|
+
expect { key = client.find_key('mock_key_0') }.should_not raise_error
|
419
444
|
|
420
|
-
key.class.should
|
445
|
+
key.class.should == RHC::Rest::Key
|
421
446
|
key.name.should == 'mock_key_0'
|
422
447
|
key.type.should == 'mock_key_0_type'
|
423
448
|
key.content.should == '123456789:0'
|
@@ -425,7 +450,7 @@ module RHC
|
|
425
450
|
mock_response_links(mock_key_links('mock_key_0'))
|
426
451
|
end
|
427
452
|
it "raise an error when no matching keys can be found" do
|
428
|
-
expect {
|
453
|
+
expect { client.find_key('no_match') }.should raise_error(RHC::KeyNotFoundException)
|
429
454
|
end
|
430
455
|
end
|
431
456
|
|
@@ -437,11 +462,10 @@ module RHC
|
|
437
462
|
})
|
438
463
|
end
|
439
464
|
context "debug mode is on" do
|
465
|
+
let(:use_debug){ true }
|
440
466
|
it "writes a message to the logger" do
|
441
467
|
capture do
|
442
|
-
|
443
|
-
@client.send logout_method.to_sym
|
444
|
-
|
468
|
+
client.send logout_method.to_sym
|
445
469
|
stderr.should match(/Logout\/Close client$/)
|
446
470
|
end
|
447
471
|
end
|
@@ -449,8 +473,7 @@ module RHC
|
|
449
473
|
context "debug mode is off" do
|
450
474
|
it "does nothing" do
|
451
475
|
capture do
|
452
|
-
|
453
|
-
@client.send logout_method.to_sym
|
476
|
+
client.send logout_method.to_sym
|
454
477
|
stderr.should be_empty
|
455
478
|
end
|
456
479
|
end
|
@@ -491,20 +514,18 @@ module RHC
|
|
491
514
|
to_return({ :body => {}.to_json,
|
492
515
|
:status => 200
|
493
516
|
})
|
494
|
-
|
495
|
-
@client = MockClient.new(mock_href, mock_user, mock_pass)
|
496
517
|
end
|
497
|
-
|
518
|
+
|
498
519
|
it "should delete keys" do
|
499
|
-
expect {
|
520
|
+
expect { client.delete_key('mock_key_0') }.should be_true
|
500
521
|
end
|
501
|
-
|
522
|
+
|
502
523
|
it 'raises an error if nonexistent key is requested' do
|
503
|
-
expect {
|
524
|
+
expect { client.find_key('no_match') }.
|
504
525
|
should raise_error(RHC::KeyNotFoundException)
|
505
526
|
end
|
506
527
|
end
|
507
|
-
|
528
|
+
|
508
529
|
context "#logout" do
|
509
530
|
let(:logout_method) { :logout }
|
510
531
|
it_should_behave_like "a logout method"
|
@@ -515,7 +536,7 @@ module RHC
|
|
515
536
|
it_should_behave_like "a logout method"
|
516
537
|
end
|
517
538
|
end
|
518
|
-
|
539
|
+
|
519
540
|
context "when server supports API versions 1.0 and 1.1" do
|
520
541
|
before :each do
|
521
542
|
stub_api_request(:get, '').
|
@@ -526,36 +547,33 @@ module RHC
|
|
526
547
|
:status => 200
|
527
548
|
})
|
528
549
|
end
|
529
|
-
|
550
|
+
|
530
551
|
context "when client supports API version 1.1" do
|
531
|
-
|
532
|
-
|
533
|
-
end
|
534
|
-
|
552
|
+
let(:spec_versions){ [1.1] }
|
553
|
+
|
535
554
|
describe "#api_version_negotiated" do
|
536
555
|
it "returns 1.1" do
|
537
|
-
|
556
|
+
client.api.api_version_negotiated.to_s.should == '1.1'
|
538
557
|
end
|
539
558
|
end
|
540
559
|
end
|
541
|
-
|
560
|
+
|
542
561
|
context "when client supports only API version 1.2" do
|
543
|
-
|
544
|
-
|
545
|
-
end
|
546
|
-
|
562
|
+
let(:spec_versions){ [1.2] }
|
563
|
+
|
547
564
|
describe "#api_version_negotiated" do
|
548
565
|
it 'returns nil' do
|
549
|
-
|
566
|
+
client.api.api_version_negotiated.should be_nil
|
550
567
|
end
|
551
568
|
end
|
552
569
|
end
|
553
|
-
|
570
|
+
|
554
571
|
context "when client supports only API version 0.9" do
|
555
572
|
describe "#new" do
|
573
|
+
let(:spec_versions){ [0.9] }
|
556
574
|
it "warns user that it is outdated" do
|
557
575
|
capture do
|
558
|
-
|
576
|
+
client.api
|
559
577
|
@output.rewind
|
560
578
|
@output.read.should =~ /client version may be outdated/
|
561
579
|
end
|
@@ -563,7 +581,6 @@ module RHC
|
|
563
581
|
end
|
564
582
|
end
|
565
583
|
end
|
566
|
-
|
567
584
|
end
|
568
585
|
end
|
569
586
|
end
|
data/spec/rhc/rest_spec.rb
CHANGED
@@ -7,7 +7,7 @@ class RHCRest
|
|
7
7
|
def debug?
|
8
8
|
false
|
9
9
|
end
|
10
|
-
def debug
|
10
|
+
def debug(*args)
|
11
11
|
raise "Unchecked debug"
|
12
12
|
end
|
13
13
|
end
|
@@ -16,17 +16,53 @@ module MockRestResponse
|
|
16
16
|
attr_accessor :code, :read
|
17
17
|
end
|
18
18
|
|
19
|
+
|
20
|
+
describe RHC::Rest::Cartridge do
|
21
|
+
context 'with a name' do
|
22
|
+
before{ subject.name = 'foo' }
|
23
|
+
its(:display_name){ should == 'foo' }
|
24
|
+
|
25
|
+
context 'when display name is present' do
|
26
|
+
before{ subject.display_name = 'bar' }
|
27
|
+
its(:display_name){ should == 'bar' }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
19
32
|
module RHC
|
20
33
|
|
21
34
|
describe Rest do
|
22
|
-
subject{
|
35
|
+
subject{ RHC::Rest::Client.new }
|
23
36
|
|
24
37
|
# logger function
|
25
38
|
describe "#logger" do
|
26
39
|
it "establishes a logger" do
|
27
40
|
logger = Logger.new(STDOUT)
|
28
|
-
subject.logger.should have_same_attributes_as(logger)
|
41
|
+
subject.send(:logger).should have_same_attributes_as(logger)
|
42
|
+
end
|
43
|
+
it "reuses a logger" do
|
44
|
+
subject.send(:logger).should equal(subject.send(:logger))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "#default_verify_callback" do
|
49
|
+
def invoked_with(is_ok, ctx)
|
50
|
+
subject.send(:default_verify_callback).call(is_ok, ctx)
|
29
51
|
end
|
52
|
+
it{ invoked_with(true, nil).should be_true }
|
53
|
+
|
54
|
+
it{ expect{ invoked_with(false, nil) }.to raise_error(NoMethodError) }
|
55
|
+
|
56
|
+
context "with a self signed cert" do
|
57
|
+
it{ invoked_with(false, stub(:current_cert => stub(:issuer => '1', :subject => stub(:cmp => 0)))).should be_false }
|
58
|
+
after{ subject.send(:self_signed?).should be_true }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with an intermediate signed cert" do
|
62
|
+
it{ invoked_with(false, stub(:current_cert => stub(:issuer => '2', :subject => stub(:cmp => 1)), :error => 1, :error_string => 'a')).should be_false }
|
63
|
+
after{ subject.send(:self_signed?).should be_false }
|
64
|
+
end
|
65
|
+
|
30
66
|
end
|
31
67
|
|
32
68
|
# parse_response function
|
@@ -35,7 +71,7 @@ module RHC
|
|
35
71
|
let(:object) {{ :links => { :foo => 'bar' } }}
|
36
72
|
it "deserializes to the encapsulated data" do
|
37
73
|
json_response = { :data => object }.to_json
|
38
|
-
subject.parse_response
|
74
|
+
subject.send(:parse_response, json_response).should have_same_attributes_as(object)
|
39
75
|
end
|
40
76
|
end
|
41
77
|
|
@@ -52,7 +88,7 @@ module RHC
|
|
52
88
|
it "deserializes to an application" do
|
53
89
|
json_response = { :type => 'application', :data => object, :messages => [{'text' => 'test message'}]}.to_json
|
54
90
|
app_obj = RHC::Rest::Application.new(object)
|
55
|
-
subject.parse_response
|
91
|
+
subject.send(:parse_response, json_response).should have_same_attributes_as(app_obj)
|
56
92
|
end
|
57
93
|
end
|
58
94
|
|
@@ -78,9 +114,9 @@ module RHC
|
|
78
114
|
json_response = { :type => 'applications', :data => object }.to_json
|
79
115
|
app_obj_1 = RHC::Rest::Application.new(object[0])
|
80
116
|
app_obj_2 = RHC::Rest::Application.new(object[1])
|
81
|
-
subject.parse_response
|
82
|
-
subject.parse_response
|
83
|
-
subject.parse_response
|
117
|
+
subject.send(:parse_response, json_response).length.should equal(2)
|
118
|
+
subject.send(:parse_response, json_response)[0].should have_same_attributes_as(app_obj_1)
|
119
|
+
subject.send(:parse_response, json_response)[1].should have_same_attributes_as(app_obj_2)
|
84
120
|
end
|
85
121
|
end
|
86
122
|
|
@@ -94,7 +130,7 @@ module RHC
|
|
94
130
|
it "deserializes to a cartridge" do
|
95
131
|
json_response = { :type => 'cartridge', :data => object }.to_json
|
96
132
|
cart_obj = RHC::Rest::Cartridge.new(object)
|
97
|
-
subject.parse_response
|
133
|
+
subject.send(:parse_response, json_response).should have_same_attributes_as(cart_obj)
|
98
134
|
end
|
99
135
|
end
|
100
136
|
|
@@ -113,9 +149,9 @@ module RHC
|
|
113
149
|
json_response = { :type => 'cartridges', :data => object }.to_json
|
114
150
|
cart_obj_1 = RHC::Rest::Cartridge.new(object[0])
|
115
151
|
cart_obj_2 = RHC::Rest::Cartridge.new(object[1])
|
116
|
-
subject.parse_response
|
117
|
-
subject.parse_response
|
118
|
-
subject.parse_response
|
152
|
+
subject.send(:parse_response, json_response).length.should equal(2)
|
153
|
+
subject.send(:parse_response, json_response)[0].should have_same_attributes_as(cart_obj_1)
|
154
|
+
subject.send(:parse_response, json_response)[1].should have_same_attributes_as(cart_obj_2)
|
119
155
|
end
|
120
156
|
end
|
121
157
|
|
@@ -128,7 +164,7 @@ module RHC
|
|
128
164
|
it "deserializes to a domain" do
|
129
165
|
json_response = { :type => 'domain', :data => object }.to_json
|
130
166
|
dom_obj = RHC::Rest::Domain.new(object)
|
131
|
-
subject.parse_response
|
167
|
+
subject.send(:parse_response, json_response).should have_same_attributes_as(dom_obj)
|
132
168
|
end
|
133
169
|
end
|
134
170
|
|
@@ -145,9 +181,9 @@ module RHC
|
|
145
181
|
json_response = { :type => 'domains', :data => object }.to_json
|
146
182
|
dom_obj_1 = RHC::Rest::Domain.new(object[0])
|
147
183
|
dom_obj_2 = RHC::Rest::Domain.new(object[1])
|
148
|
-
subject.parse_response
|
149
|
-
subject.parse_response
|
150
|
-
subject.parse_response
|
184
|
+
subject.send(:parse_response, json_response).length.should equal(2)
|
185
|
+
subject.send(:parse_response, json_response)[0].should have_same_attributes_as(dom_obj_1)
|
186
|
+
subject.send(:parse_response, json_response)[1].should have_same_attributes_as(dom_obj_2)
|
151
187
|
end
|
152
188
|
end
|
153
189
|
|
@@ -162,7 +198,7 @@ module RHC
|
|
162
198
|
it "deserializes to a key" do
|
163
199
|
json_response = { :type => 'key', :data => object }.to_json
|
164
200
|
key_obj = RHC::Rest::Key.new(object)
|
165
|
-
subject.parse_response
|
201
|
+
subject.send(:parse_response, json_response).should have_same_attributes_as(key_obj)
|
166
202
|
end
|
167
203
|
end
|
168
204
|
|
@@ -183,9 +219,9 @@ module RHC
|
|
183
219
|
json_response = { :type => 'keys', :data => object }.to_json
|
184
220
|
key_obj_1 = RHC::Rest::Key.new(object[0])
|
185
221
|
key_obj_2 = RHC::Rest::Key.new(object[1])
|
186
|
-
subject.parse_response
|
187
|
-
subject.parse_response
|
188
|
-
subject.parse_response
|
222
|
+
subject.send(:parse_response, json_response).length.should equal(2)
|
223
|
+
subject.send(:parse_response, json_response)[0].should have_same_attributes_as(key_obj_1)
|
224
|
+
subject.send(:parse_response, json_response)[1].should have_same_attributes_as(key_obj_2)
|
189
225
|
end
|
190
226
|
end
|
191
227
|
|
@@ -198,13 +234,26 @@ module RHC
|
|
198
234
|
it "deserializes to a user" do
|
199
235
|
json_response = { :type => 'user', :data => object }.to_json
|
200
236
|
user_obj = RHC::Rest::User.new(object)
|
201
|
-
subject.parse_response
|
237
|
+
subject.send(:parse_response, json_response).should have_same_attributes_as(user_obj)
|
202
238
|
end
|
203
239
|
end
|
204
240
|
end
|
205
241
|
|
206
242
|
# request function
|
207
243
|
describe "#request" do
|
244
|
+
let(:response){ lambda { subject.request(request) } }
|
245
|
+
let(:request){ {:url => mock_href, :method => method, :headers => {:accept => :json} } }
|
246
|
+
let(:method){ :get }
|
247
|
+
|
248
|
+
if HTTPClient::SSLConfig.method_defined? :ssl_version
|
249
|
+
context "when an invalid ssl version is passed, OpenSSL should reject us" do
|
250
|
+
let(:request){ {:url => "https://openshift.redhat.com", :method => :get, :ssl_version => :SSLv3_server} }
|
251
|
+
before{ WebMock.allow_net_connect! }
|
252
|
+
it("fails to call openssl"){ response.should raise_error(RHC::Rest::SSLConnectionFailed, /called a function you should not call/) }
|
253
|
+
after{ WebMock.disable_net_connect! }
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
208
257
|
context "with a successful request" do
|
209
258
|
let(:object) {{
|
210
259
|
:type => 'domain',
|
@@ -223,13 +272,7 @@ module RHC
|
|
223
272
|
|
224
273
|
it "sends the response to be deserialized" do
|
225
274
|
dom_obj = RHC::Rest::Domain.new(object)
|
226
|
-
request
|
227
|
-
:method => 'get',
|
228
|
-
:headers => { :accept => :json },
|
229
|
-
:payload => {},
|
230
|
-
:timeout => 300
|
231
|
-
)
|
232
|
-
subject.request(request).should have_same_attributes_as(dom_obj)
|
275
|
+
subject.request(request.merge(:payload => {}, :timeout => 300)).should have_same_attributes_as(dom_obj)
|
233
276
|
end
|
234
277
|
end
|
235
278
|
|
@@ -243,11 +286,7 @@ module RHC
|
|
243
286
|
stub_request(:get, mock_href).to_return(return_data)
|
244
287
|
end
|
245
288
|
it "throws an error" do
|
246
|
-
|
247
|
-
:method => 'get',
|
248
|
-
:headers => {:accept => :json}
|
249
|
-
)
|
250
|
-
lambda { subject.request(request) }.should raise_error(RHC::Rest::ResourceAccessException, 'Failed to access resource: unexpected nil')
|
289
|
+
response.should raise_error(RHC::Rest::ConnectionException, 'An unexpected error occured: unexpected nil')
|
251
290
|
end
|
252
291
|
end
|
253
292
|
|
@@ -261,95 +300,103 @@ module RHC
|
|
261
300
|
stub_request(:get, mock_href).to_return(return_data)
|
262
301
|
end
|
263
302
|
it "quietly exits" do
|
264
|
-
|
265
|
-
:method => 'get',
|
266
|
-
:headers => {:accept => :json}
|
267
|
-
)
|
268
|
-
subject.request(request).should equal(nil)
|
303
|
+
response.call.should equal(nil)
|
269
304
|
end
|
270
305
|
end
|
271
306
|
|
272
307
|
context "with a 502 (Bad Gateway) error" do
|
273
308
|
before{ stub_request(method, mock_href).to_return(:status => 502) }
|
274
|
-
let(:req){ RestClient::Request.new(:url => mock_href, :method => method) }
|
275
|
-
let(:method){ :get }
|
276
309
|
|
277
|
-
|
278
|
-
|
310
|
+
context "on a GET request" do
|
311
|
+
it("repeats the call"){ response.should raise_error(RHC::Rest::ConnectionException, /communicating with the server.*temporary/i) }
|
312
|
+
after{ WebMock.should have_requested(method, mock_href).twice }
|
313
|
+
end
|
279
314
|
|
280
315
|
context "on a POST request" do
|
281
316
|
let(:method){ :post }
|
282
317
|
|
283
|
-
it("
|
284
|
-
|
318
|
+
it("does not repeat the call"){ response.should raise_error(RHC::Rest::ConnectionException, /communicating with the server.*temporary/i) }
|
319
|
+
after{ WebMock.should have_requested(method, mock_href).once }
|
285
320
|
end
|
286
321
|
end
|
287
322
|
|
288
|
-
context "with a request
|
289
|
-
|
290
|
-
stub_request(:get, mock_href).
|
323
|
+
context "with a GET request" do
|
324
|
+
it "serializes payload as query parameters" do
|
325
|
+
stub_request(:get, mock_href).with(:query => {:test => 1, :bar => 2}).to_return(:status => 204)
|
326
|
+
subject.request(request.merge(:payload => {:test => '1', :bar => 2})).should be_nil
|
291
327
|
end
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
328
|
+
end
|
329
|
+
context "with a POST request" do
|
330
|
+
let(:method){ :post }
|
331
|
+
it "serializes payload as urlencoded body parameters" do
|
332
|
+
stub_request(method, mock_href).
|
333
|
+
with(:headers => {:accept => 'application/json', :content_type => 'application/json'},
|
334
|
+
:body => {:test => '1', :bar => 2}.to_json).
|
335
|
+
to_return(:status => 204)
|
336
|
+
subject.request(request.merge(:payload => {:test => '1', :bar => 2})).should be_nil
|
298
337
|
end
|
299
338
|
end
|
300
339
|
|
340
|
+
context "with a request timeout" do
|
341
|
+
before{ stub_request(:get, mock_href).to_timeout }
|
342
|
+
it{ response.should raise_error(RHC::Rest::TimeoutException, /Connection to server timed out. It is possible/) }
|
343
|
+
end
|
344
|
+
|
301
345
|
context "with a broken server connection" do
|
346
|
+
before{ stub_request(:get, mock_href).to_raise(EOFError.new('Lost Server Connection')) }
|
347
|
+
it{ response.should raise_error(RHC::Rest::ConnectionException, 'Connection to server got interrupted: Lost Server Connection') }
|
348
|
+
end
|
349
|
+
|
350
|
+
#FIXME: the type of this exception should be a subclass of CertificateValidationFailed
|
351
|
+
context "with a potentially missing cert store" do
|
352
|
+
before{ stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError.new('unable to get local issuer certificate')) }
|
353
|
+
it{ response.should raise_error(RHC::Rest::SSLConnectionFailed, /You may need to specify your system CA certificate file/) }
|
354
|
+
end
|
355
|
+
|
356
|
+
context "with a self-signed SSL certificate" do
|
302
357
|
before do
|
303
|
-
|
304
|
-
|
305
|
-
it "raises a resource access exception error" do
|
306
|
-
request = RestClient::Request.new(:url => mock_href,
|
307
|
-
:method => 'get',
|
308
|
-
:headers => {:accept => :json}
|
309
|
-
)
|
310
|
-
lambda { subject.request(request) }.should raise_error(RHC::Rest::ConnectionException, 'Connection to server got interrupted: Lost Server Connection')
|
358
|
+
subject.should_receive(:self_signed?).and_return(true)
|
359
|
+
stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError.new('Unverified SSL Certificate'))
|
311
360
|
end
|
361
|
+
it{ response.should raise_error(RHC::Rest::CertificateVerificationFailed, /The server is using a self-signed certificate/) }
|
312
362
|
end
|
313
363
|
|
314
364
|
context "with an unverified SSL certificate" do
|
315
|
-
before
|
316
|
-
|
317
|
-
end
|
318
|
-
it "raises a resource access exception error" do
|
319
|
-
request = RestClient::Request.new(:url => mock_href,
|
320
|
-
:method => 'get',
|
321
|
-
:headers => {:accept => :json}
|
322
|
-
)
|
323
|
-
lambda { subject.request(request) }.should raise_error(RHC::Rest::ResourceAccessException, 'Failed to access resource: Unverified SSL Certificate')
|
324
|
-
end
|
365
|
+
before{ stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError.new('self signed certificate')) }
|
366
|
+
it{ response.should raise_error(RHC::Rest::CertificateVerificationFailed, /The server is using a self-signed certificate/) }
|
325
367
|
end
|
326
368
|
|
327
|
-
context "with
|
369
|
+
context "with an failed SSL certificate verification" do
|
370
|
+
before{ stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError.new('certificate verify failed')) }
|
371
|
+
it{ response.should raise_error(RHC::Rest::CertificateVerificationFailed, /The server's certificate could not be verified.*test\.domain\.com/) }
|
372
|
+
end
|
373
|
+
|
374
|
+
context "with a socket error" do
|
328
375
|
before{ stub_request(:get, mock_href).to_raise(SocketError) }
|
329
|
-
it
|
330
|
-
request = RestClient::Request.new(:url => mock_href,
|
331
|
-
:method => 'get',
|
332
|
-
:headers => {:accept => :json}
|
333
|
-
)
|
334
|
-
lambda { subject.request(request) }.should raise_error(RHC::Rest::ConnectionException, /unable to connect to the server/i)
|
335
|
-
end
|
376
|
+
it{ response.should raise_error(RHC::Rest::ConnectionException, /unable to connect to the server/i) }
|
336
377
|
end
|
337
378
|
|
338
|
-
context "with
|
339
|
-
before
|
340
|
-
|
341
|
-
|
379
|
+
context "with an SSL connection error" do
|
380
|
+
before{ stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError) }
|
381
|
+
it{ response.should raise_error(RHC::Rest::SSLConnectionFailed, /a secure connection could not be established/i) }
|
382
|
+
end
|
342
383
|
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
384
|
+
context "with an SSL certificate error" do
|
385
|
+
before{ stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError.new('certificate verify failed')) }
|
386
|
+
it{ response.should raise_error(RHC::Rest::CertificateVerificationFailed, /the server's certificate could not be verified/i) }
|
387
|
+
end
|
388
|
+
|
389
|
+
context "with an SSL version exception" do
|
390
|
+
before{ stub_request(:get, mock_href).to_raise(OpenSSL::SSL::SSLError.new('SSL_connect returned=1 errno=0 state=SSLv2/v3 read server hello A')) }
|
391
|
+
it{ response.should raise_error(RHC::Rest::SSLVersionRejected, /connection attempt with an older ssl protocol/i) }
|
350
392
|
end
|
351
393
|
|
352
|
-
context "with a
|
394
|
+
context "with a generic exception error" do
|
395
|
+
before{ stub_request(:get, mock_href).to_raise(Exception.new('Generic Error')) }
|
396
|
+
it{ response.should raise_error(RHC::Rest::ConnectionException, "An unexpected error occured: Generic Error") }
|
397
|
+
end
|
398
|
+
|
399
|
+
context "with a an unauthorized request" do
|
353
400
|
before do
|
354
401
|
return_data = {
|
355
402
|
:body => nil,
|
@@ -358,40 +405,32 @@ module RHC
|
|
358
405
|
}
|
359
406
|
stub_request(:get, mock_href).to_return(return_data)
|
360
407
|
end
|
361
|
-
|
362
|
-
it "passes the response off for interpretation" do
|
363
|
-
request = RestClient::Request.new(:url => mock_href,
|
364
|
-
:method => 'get',
|
365
|
-
:headers => {:accept => :json}
|
366
|
-
)
|
367
|
-
lambda { subject.request(request) }.should raise_error(RHC::Rest::UnAuthorizedException, 'Not authenticated')
|
368
|
-
end
|
408
|
+
it("raises not authenticated"){ response.should raise_error(RHC::Rest::UnAuthorizedException, 'Not authenticated') }
|
369
409
|
end
|
370
410
|
end
|
371
411
|
|
372
|
-
#
|
373
|
-
describe "#
|
412
|
+
# handle_error! function
|
413
|
+
describe "#handle_error!" do
|
374
414
|
let(:json){ nil }
|
375
415
|
let(:body){ "<html><body>Something failed</body></html>" }
|
376
416
|
let(:code){ nil }
|
417
|
+
let(:client){ HTTPClient.new(:proxy => proxy) }
|
418
|
+
let(:url){ "http://fake.url" }
|
419
|
+
let(:proxy){ nil }
|
377
420
|
def response
|
378
|
-
(
|
379
|
-
response.code = code
|
380
|
-
response.read = json ? RHC::Json.encode(json) : body
|
381
|
-
response
|
421
|
+
mock(:status => code, :content => json ? RHC::Json.encode(json) : body)
|
382
422
|
end
|
423
|
+
let(:method) { lambda{ subject.send(:handle_error!, response, url, client) } }
|
383
424
|
|
384
425
|
context "with a 400 response" do
|
385
426
|
let(:code){ 400 }
|
386
427
|
|
387
|
-
it
|
388
|
-
lambda { subject.process_error_response(response) }.should raise_error(RHC::Rest::ServerErrorException)
|
389
|
-
end
|
428
|
+
it{ method.should raise_error(RHC::Rest::ServerErrorException) }
|
390
429
|
|
391
430
|
context "with a formatted JSON response" do
|
392
431
|
let(:json){ {:messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
393
432
|
it "raises a client error" do
|
394
|
-
|
433
|
+
method.should raise_error(RHC::Rest::ClientErrorException, 'mock error message')
|
395
434
|
end
|
396
435
|
end
|
397
436
|
end
|
@@ -400,7 +439,7 @@ module RHC
|
|
400
439
|
let(:code){ 401 }
|
401
440
|
let(:json){ {} }
|
402
441
|
it "raises an 'unauthorized exception' error" do
|
403
|
-
|
442
|
+
method.should raise_error(RHC::Rest::UnAuthorizedException, 'Not authenticated')
|
404
443
|
end
|
405
444
|
end
|
406
445
|
|
@@ -408,13 +447,13 @@ module RHC
|
|
408
447
|
let(:code){ 403 }
|
409
448
|
|
410
449
|
it "raises a request denied error" do
|
411
|
-
|
450
|
+
method.should raise_error(RHC::Rest::RequestDeniedException)
|
412
451
|
end
|
413
452
|
|
414
453
|
context "with a formatted JSON response" do
|
415
454
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
416
455
|
it "raises a 'request denied' error" do
|
417
|
-
|
456
|
+
method.should raise_error(RHC::Rest::RequestDeniedException, 'mock error message')
|
418
457
|
end
|
419
458
|
end
|
420
459
|
end
|
@@ -423,13 +462,13 @@ module RHC
|
|
423
462
|
let(:code){ 404 }
|
424
463
|
|
425
464
|
it "raises a Not Found error" do
|
426
|
-
|
465
|
+
method.should raise_error(RHC::Rest::ResourceNotFoundException)
|
427
466
|
end
|
428
467
|
|
429
468
|
context "with a formatted JSON response" do
|
430
469
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
431
470
|
it "raises a 'resource not found' error" do
|
432
|
-
|
471
|
+
method.should raise_error(RHC::Rest::ResourceNotFoundException, 'mock error message')
|
433
472
|
end
|
434
473
|
end
|
435
474
|
end
|
@@ -438,13 +477,45 @@ module RHC
|
|
438
477
|
let(:code){ 409 }
|
439
478
|
|
440
479
|
it "raises a generic server error" do
|
441
|
-
|
480
|
+
method.should raise_error(RHC::Rest::ServerErrorException)
|
442
481
|
end
|
443
482
|
|
444
483
|
context "with a formatted JSON response" do
|
445
484
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
446
485
|
it "raises a validation error" do
|
447
|
-
|
486
|
+
method.should raise_error(RHC::Rest::ValidationException, 'mock error message')
|
487
|
+
end
|
488
|
+
end
|
489
|
+
context "with multiple JSON messages" do
|
490
|
+
let(:json){ { :messages => [{ :field => 'error', :text => 'mock error message 1' },
|
491
|
+
{ :field => 'error', :text => 'mock error message 2' }] } }
|
492
|
+
it "raises a validation error with concatenated messages" do
|
493
|
+
method.should raise_error(RHC::Rest::ValidationException, "The operation did not complete successfully, but the server returned additional information:\n* mock error message 1\n* mock error message 2")
|
494
|
+
end
|
495
|
+
end
|
496
|
+
context "with multiple errors" do
|
497
|
+
let(:json){ { :messages => [
|
498
|
+
{ :severity => 'error', :field => 'error', :text => 'mock 1' },
|
499
|
+
{ :severity => 'error', :text => 'mock 2' },
|
500
|
+
] } }
|
501
|
+
it "raises a validation error with concatenated messages" do
|
502
|
+
method.should raise_error(RHC::Rest::ValidationException, "The server reported multiple errors:\n* mock 1\n* mock 2")
|
503
|
+
end
|
504
|
+
end
|
505
|
+
context "with multiple messages and one error" do
|
506
|
+
let(:json){ { :messages => [
|
507
|
+
{ :field => 'error', :text => 'mock 1' },
|
508
|
+
{ :text => 'mock 2' },
|
509
|
+
{ :severity => 'error', :text => 'mock 3' },
|
510
|
+
] } }
|
511
|
+
it "raises a validation error with concatenated messages" do
|
512
|
+
method.should raise_error(RHC::Rest::ValidationException, "mock 3")
|
513
|
+
end
|
514
|
+
end
|
515
|
+
context "with an empty JSON response" do
|
516
|
+
let(:json){ {} }
|
517
|
+
it "raises a validation error" do
|
518
|
+
method.should raise_error(RHC::Rest::ServerErrorException)
|
448
519
|
end
|
449
520
|
end
|
450
521
|
end
|
@@ -453,20 +524,20 @@ module RHC
|
|
453
524
|
let(:code){ 422 }
|
454
525
|
|
455
526
|
it "raises a generic server error" do
|
456
|
-
|
527
|
+
method.should raise_error(RHC::Rest::ServerErrorException)
|
457
528
|
end
|
458
529
|
|
459
530
|
context "with a single JSON message" do
|
460
531
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
461
532
|
it "raises a validation error" do
|
462
|
-
|
533
|
+
method.should raise_error(RHC::Rest::ValidationException, 'mock error message')
|
463
534
|
end
|
464
535
|
end
|
465
536
|
|
466
537
|
context "with an empty JSON response" do
|
467
538
|
let(:json){ {} }
|
468
539
|
it "raises a validation error" do
|
469
|
-
|
540
|
+
method.should raise_error(RHC::Rest::ServerErrorException)
|
470
541
|
end
|
471
542
|
end
|
472
543
|
|
@@ -474,7 +545,26 @@ module RHC
|
|
474
545
|
let(:json){ { :messages => [{ :field => 'error', :text => 'mock error message 1' },
|
475
546
|
{ :field => 'error', :text => 'mock error message 2' }] } }
|
476
547
|
it "raises a validation error with concatenated messages" do
|
477
|
-
|
548
|
+
method.should raise_error(RHC::Rest::ValidationException, "The operation did not complete successfully, but the server returned additional information:\n* mock error message 1\n* mock error message 2")
|
549
|
+
end
|
550
|
+
end
|
551
|
+
context "with multiple errors" do
|
552
|
+
let(:json){ { :messages => [
|
553
|
+
{ :severity => 'error', :field => 'error', :text => 'mock 1' },
|
554
|
+
{ :severity => 'error', :text => 'mock 2' },
|
555
|
+
] } }
|
556
|
+
it "raises a validation error with concatenated messages" do
|
557
|
+
method.should raise_error(RHC::Rest::ValidationException, "The server reported multiple errors:\n* mock 1\n* mock 2")
|
558
|
+
end
|
559
|
+
end
|
560
|
+
context "with multiple messages and one error" do
|
561
|
+
let(:json){ { :messages => [
|
562
|
+
{ :field => 'error', :text => 'mock 1' },
|
563
|
+
{ :text => 'mock 2' },
|
564
|
+
{ :severity => 'error', :text => 'mock 3' },
|
565
|
+
] } }
|
566
|
+
it "raises a validation error with concatenated messages" do
|
567
|
+
method.should raise_error(RHC::Rest::ValidationException, "mock 3")
|
478
568
|
end
|
479
569
|
end
|
480
570
|
end
|
@@ -483,26 +573,27 @@ module RHC
|
|
483
573
|
let(:code){ 500 }
|
484
574
|
|
485
575
|
it "raises a generic server error" do
|
486
|
-
|
576
|
+
method.should raise_error(RHC::Rest::ServerErrorException, /server did not respond correctly.*verify that you can access the OpenShift server/i)
|
487
577
|
end
|
488
578
|
|
489
579
|
context "when proxy is set" do
|
490
|
-
|
580
|
+
let(:proxy) { 'http://foo.com' }
|
491
581
|
it "raises a generic server error with the proxy URL" do
|
492
|
-
|
582
|
+
method.should raise_error(RHC::Rest::ServerErrorException, /foo\.com/i)
|
493
583
|
end
|
494
584
|
end
|
495
585
|
|
496
586
|
context "when request url is present" do
|
587
|
+
let(:url){ 'foo.bar' }
|
497
588
|
it "raises a generic server error with the request URL" do
|
498
|
-
|
589
|
+
method.should raise_error(RHC::Rest::ServerErrorException, /foo\.bar/i)
|
499
590
|
end
|
500
591
|
end
|
501
592
|
|
502
593
|
context "with a formatted JSON response" do
|
503
594
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
504
595
|
it "raises a server error" do
|
505
|
-
|
596
|
+
method.should raise_error(RHC::Rest::ServerErrorException, 'mock error message')
|
506
597
|
end
|
507
598
|
end
|
508
599
|
end
|
@@ -511,13 +602,13 @@ module RHC
|
|
511
602
|
let(:code){ 503 }
|
512
603
|
|
513
604
|
it "raises a 'service unavailable' error" do
|
514
|
-
|
605
|
+
method.should raise_error(RHC::Rest::ServiceUnavailableException)
|
515
606
|
end
|
516
607
|
|
517
608
|
context "with a formatted JSON response" do
|
518
609
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
519
610
|
it "raises a 'service unavailable' error" do
|
520
|
-
|
611
|
+
method.should raise_error(RHC::Rest::ServiceUnavailableException, 'mock error message')
|
521
612
|
end
|
522
613
|
end
|
523
614
|
end
|
@@ -525,14 +616,12 @@ module RHC
|
|
525
616
|
context "with an unhandled response code" do
|
526
617
|
let(:code){ 999 }
|
527
618
|
|
528
|
-
it
|
529
|
-
lambda { subject.process_error_response(response) }.should raise_error(RHC::Rest::ServerErrorException)
|
530
|
-
end
|
619
|
+
it{ method.should raise_error(RHC::Rest::ServerErrorException) }
|
531
620
|
|
532
621
|
context "with a formatted JSON response" do
|
533
622
|
let(:json){ { :messages => [{ :severity => 'error', :text => 'mock error message' }] } }
|
534
623
|
it "raises a resource access error" do
|
535
|
-
|
624
|
+
method.should raise_error(RHC::Rest::ServerErrorException, 'mock error message')
|
536
625
|
end
|
537
626
|
end
|
538
627
|
end
|