rhc 1.2.7 → 1.3.8
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.
- 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
|