rhc 0.94.8 → 0.95.13

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.
Files changed (59) hide show
  1. data/README.md +27 -1
  2. data/bin/rhc +15 -23
  3. data/bin/rhc-app +4 -1
  4. data/bin/rhc-chk +3 -0
  5. data/bin/rhc-create-app +3 -0
  6. data/bin/rhc-create-domain +3 -0
  7. data/bin/rhc-ctl-app +3 -0
  8. data/bin/rhc-ctl-domain +3 -0
  9. data/bin/rhc-domain +5 -2
  10. data/bin/rhc-domain-info +3 -0
  11. data/bin/rhc-port-forward +16 -18
  12. data/bin/rhc-snapshot +3 -0
  13. data/bin/rhc-sshkey +3 -0
  14. data/bin/rhc-tail-files +3 -0
  15. data/bin/rhc-user-info +1 -0
  16. data/features/README.md +70 -0
  17. data/features/lib/rhc_helper/app.rb +124 -0
  18. data/features/lib/rhc_helper/cartridge.rb +72 -0
  19. data/features/lib/rhc_helper/commandify.rb +154 -0
  20. data/features/lib/rhc_helper/domain.rb +50 -0
  21. data/features/lib/rhc_helper/httpify.rb +107 -0
  22. data/features/lib/rhc_helper/loggable.rb +39 -0
  23. data/features/lib/rhc_helper/persistable.rb +38 -0
  24. data/features/lib/rhc_helper/runnable.rb +41 -0
  25. data/features/lib/rhc_helper.rb +7 -0
  26. data/features/step_definitions/application_steps.rb +99 -0
  27. data/features/step_definitions/cartridge_steps.rb +42 -0
  28. data/features/step_definitions/client_steps.rb +32 -0
  29. data/features/step_definitions/domain_steps.rb +19 -0
  30. data/features/support/env.rb +99 -0
  31. data/features/verify.feature +123 -0
  32. data/lib/rhc/cli.rb +4 -1
  33. data/lib/rhc/commands/base.rb +28 -6
  34. data/lib/rhc/commands/server.rb +4 -1
  35. data/lib/rhc/commands/setup.rb +24 -0
  36. data/lib/rhc/commands.rb +10 -5
  37. data/lib/rhc/config.rb +90 -21
  38. data/lib/rhc/core_ext.rb +11 -2
  39. data/lib/rhc/coverage_helper.rb +35 -0
  40. data/lib/rhc/help_formatter.rb +30 -0
  41. data/lib/rhc/helpers.rb +41 -5
  42. data/lib/rhc/ssh_key_helpers.rb +72 -0
  43. data/lib/rhc/targz.rb +2 -8
  44. data/lib/rhc/wizard.rb +75 -58
  45. data/lib/rhc-common.rb +20 -13
  46. data/lib/rhc-rest.rb +3 -11
  47. data/spec/coverage_helper.rb +51 -0
  48. data/spec/rest_spec_helper.rb +86 -0
  49. data/spec/rhc/cli_spec.rb +19 -3
  50. data/spec/rhc/commands/server_spec.rb +2 -2
  51. data/spec/rhc/common_spec.rb +49 -0
  52. data/spec/rhc/config_spec.rb +328 -0
  53. data/spec/rhc/helpers_spec.rb +74 -1
  54. data/spec/rhc/rest_client_spec.rb +402 -0
  55. data/spec/rhc/rest_spec.rb +454 -0
  56. data/spec/rhc/targz_spec.rb +13 -0
  57. data/spec/rhc/wizard_spec.rb +305 -43
  58. data/spec/spec_helper.rb +30 -25
  59. metadata +124 -5
@@ -0,0 +1,454 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc-rest'
4
+
5
+ Spec::Runner.configure do |configuration|
6
+ include(RestSpecHelper)
7
+ end
8
+
9
+ # We have to make an object to test the Rhc::Rest module
10
+ class RhcRest
11
+ include Rhc::Rest
12
+ end
13
+
14
+ module MockRestResponse
15
+ def set_code(error_code)
16
+ @error_code = error_code
17
+ end
18
+ def code
19
+ @error_code
20
+ end
21
+ end
22
+
23
+ module Rhc
24
+ include RestSpecHelper
25
+
26
+ describe Rest do
27
+ subject = RhcRest.new
28
+
29
+ # logger function
30
+ describe "logger" do
31
+ it "establishes a logger" do
32
+ logger = Logger.new(STDOUT)
33
+ subject.logger.should have_same_attributes_as(logger)
34
+ end
35
+ end
36
+
37
+ # parse_response function
38
+ describe "parse_response" do
39
+ context "with no response type" do
40
+ let(:object) {{ :links => { :foo => 'bar' } }}
41
+ it "deserializes to the encapsualted data" do
42
+ json_response = { :data => object }.to_json
43
+ subject.parse_response(json_response).should have_same_attributes_as(object)
44
+ end
45
+ end
46
+
47
+ context "with an application" do
48
+ let(:object) {{
49
+ :domain_id => 'test_domain',
50
+ :name => 'test_app',
51
+ :creation_time => '0000-00-00 00:00:00 -0000',
52
+ :uuid => 'test_app_1234',
53
+ :aliases => ['app_alias_1', 'app_alias_2'],
54
+ :server_identity => 'test_server',
55
+ :links => { :foo => 'bar' }
56
+ }}
57
+ it "deserializes to an application" do
58
+ json_response = { :type => 'application', :data => object }.to_json
59
+ app_obj = Rhc::Rest::Application.new(object)
60
+ subject.parse_response(json_response).should have_same_attributes_as(app_obj)
61
+ end
62
+ end
63
+
64
+ context "with two applications" do
65
+ let(:object) {[{ :domain_id => 'test_domain',
66
+ :name => 'test_app',
67
+ :creation_time => '0000-00-00 00:00:00 -0000',
68
+ :uuid => 'test_app_1234',
69
+ :aliases => ['app_alias_1', 'app_alias_2'],
70
+ :server_identity => 'test_server',
71
+ :links => { :foo => 'bar' }
72
+ },
73
+ { :domain_id => 'test_domain_2',
74
+ :name => 'test_app_2',
75
+ :creation_time => '0000-00-00 00:00:00 -0000',
76
+ :uuid => 'test_app_2_1234',
77
+ :aliases => ['app_alias_3', 'app_alias_4'],
78
+ :server_identity => 'test_server_2',
79
+ :links => { :foo => 'bar' }
80
+ }]
81
+ }
82
+ it "deserializes to a list of applications" do
83
+ json_response = { :type => 'applications', :data => object }.to_json
84
+ app_obj_1 = Rhc::Rest::Application.new(object[0])
85
+ app_obj_2 = Rhc::Rest::Application.new(object[1])
86
+ subject.parse_response(json_response).length.should equal(2)
87
+ subject.parse_response(json_response)[0].should have_same_attributes_as(app_obj_1)
88
+ subject.parse_response(json_response)[1].should have_same_attributes_as(app_obj_2)
89
+ end
90
+ end
91
+
92
+ context "with a cartridge" do
93
+ let(:object) {{
94
+ :name => 'test_cartridge',
95
+ :type => 'test_cartridge_type',
96
+ :links => { :foo => 'bar' }
97
+ }}
98
+
99
+ it "deserializes to a cartridge" do
100
+ json_response = { :type => 'cartridge', :data => object }.to_json
101
+ cart_obj = Rhc::Rest::Cartridge.new(object)
102
+ subject.parse_response(json_response).should have_same_attributes_as(cart_obj)
103
+ end
104
+ end
105
+
106
+ context "with two cartridges" do
107
+ let(:object) {[{ :name => 'test_cartridge',
108
+ :type => 'test_cartridge_type',
109
+ :links => { :foo => 'bar' }
110
+ },
111
+ { :name => 'test_cartridge_2',
112
+ :type => 'test_cartridge_type_2',
113
+ :links => { :foo => 'bar' }
114
+ }
115
+ ]}
116
+
117
+ it "deserializes to a list of cartridges" do
118
+ json_response = { :type => 'cartridges', :data => object }.to_json
119
+ cart_obj_1 = Rhc::Rest::Cartridge.new(object[0])
120
+ cart_obj_2 = Rhc::Rest::Cartridge.new(object[1])
121
+ subject.parse_response(json_response).length.should equal(2)
122
+ subject.parse_response(json_response)[0].should have_same_attributes_as(cart_obj_1)
123
+ subject.parse_response(json_response)[1].should have_same_attributes_as(cart_obj_2)
124
+ end
125
+ end
126
+
127
+ context "with a domain" do
128
+ let(:object) {{
129
+ :id => 'test_domain',
130
+ :links => { :foo => 'bar' }
131
+ }}
132
+
133
+ it "deserializes to a domain" do
134
+ json_response = { :type => 'domain', :data => object }.to_json
135
+ dom_obj = Rhc::Rest::Domain.new(object)
136
+ subject.parse_response(json_response).should have_same_attributes_as(dom_obj)
137
+ end
138
+ end
139
+
140
+ context "with two domains" do
141
+ let(:object) {[{ :id => 'test_domain',
142
+ :links => { :foo => 'bar' }
143
+ },
144
+ { :id => 'test_domain_2',
145
+ :links => { :foo => 'bar' }
146
+ }
147
+ ]}
148
+
149
+ it "deserializes to a list of domains" do
150
+ json_response = { :type => 'domains', :data => object }.to_json
151
+ dom_obj_1 = Rhc::Rest::Domain.new(object[0])
152
+ dom_obj_2 = Rhc::Rest::Domain.new(object[1])
153
+ subject.parse_response(json_response).length.should equal(2)
154
+ subject.parse_response(json_response)[0].should have_same_attributes_as(dom_obj_1)
155
+ subject.parse_response(json_response)[1].should have_same_attributes_as(dom_obj_2)
156
+ end
157
+ end
158
+
159
+ context "with a key" do
160
+ let(:object) {{
161
+ :name => 'test_key',
162
+ :type => 'test_key_type',
163
+ :content => 'test_key_content',
164
+ :links => { :foo => 'bar' }
165
+ }}
166
+
167
+ it "deserializes to a key" do
168
+ json_response = { :type => 'key', :data => object }.to_json
169
+ key_obj = Rhc::Rest::Key.new(object)
170
+ subject.parse_response(json_response).should have_same_attributes_as(key_obj)
171
+ end
172
+ end
173
+
174
+ context "with two keys" do
175
+ let(:object) {[{ :name => 'test_key',
176
+ :type => 'test_key_type',
177
+ :content => 'test_key_content',
178
+ :links => { :foo => 'bar' }
179
+ },
180
+ { :name => 'test_key_2',
181
+ :type => 'test_key_type_2',
182
+ :content => 'test_key_content_2',
183
+ :links => { :foo => 'bar' }
184
+ }
185
+ ]}
186
+
187
+ it "deserializes to a list of keys" do
188
+ json_response = { :type => 'keys', :data => object }.to_json
189
+ key_obj_1 = Rhc::Rest::Key.new(object[0])
190
+ key_obj_2 = Rhc::Rest::Key.new(object[1])
191
+ subject.parse_response(json_response).length.should equal(2)
192
+ subject.parse_response(json_response)[0].should have_same_attributes_as(key_obj_1)
193
+ subject.parse_response(json_response)[1].should have_same_attributes_as(key_obj_2)
194
+ end
195
+ end
196
+
197
+ context "with a user" do
198
+ let(:object) {{
199
+ :login => 'test_user',
200
+ :links => { :foo => 'bar' }
201
+ }}
202
+
203
+ it "deserializes to a user" do
204
+ json_response = { :type => 'user', :data => object }.to_json
205
+ user_obj = Rhc::Rest::User.new(object)
206
+ subject.parse_response(json_response).should have_same_attributes_as(user_obj)
207
+ end
208
+ end
209
+ end
210
+
211
+ # send function
212
+ describe "send" do
213
+ context "with a successful request" do
214
+ let(:object) {{
215
+ :type => 'domain',
216
+ :data => {
217
+ :id => 'test_domain',
218
+ :links => { :foo => 'bar' }
219
+ }}}
220
+ before do
221
+ return_data = {
222
+ :body => object.to_json,
223
+ :status => 200,
224
+ :headers => { 'Set-Cookie' => "rh_sso=test_ssh_cookie" }
225
+ }
226
+ stub_request(:get, mock_href).to_return(return_data)
227
+ end
228
+
229
+ it "sends the response to be deserialized" do
230
+ dom_obj = Rhc::Rest::Domain.new(object)
231
+ request = RestClient::Request.new(:url => mock_href,
232
+ :method => 'get',
233
+ :headers => {:accept => :json},
234
+ :payload => {},
235
+ :timeout => 300
236
+ )
237
+ subject.send(request).should have_same_attributes_as(dom_obj)
238
+ end
239
+ end
240
+
241
+ context "with a nil response" do
242
+ before do
243
+ return_data = {
244
+ :body => nil,
245
+ :status => 200,
246
+ :headers => { 'Set-Cookie' => "rh_sso=test_ssh_cookie" }
247
+ }
248
+ stub_request(:get, mock_href).to_return(return_data)
249
+ end
250
+ it "throws an error" do
251
+ request = RestClient::Request.new(:url => mock_href,
252
+ :method => 'get',
253
+ :headers => {:accept => :json}
254
+ )
255
+ lambda { subject.send(request) }.should raise_error(Rhc::Rest::ResourceAccessException, 'Failed to access resource: unexpected nil')
256
+ end
257
+ end
258
+
259
+ context "with a 204 (No Content) response" do
260
+ before do
261
+ return_data = {
262
+ :body => nil,
263
+ :status => 204,
264
+ :headers => { 'Set-Cookie' => "rh_sso=test_ssh_cookie" }
265
+ }
266
+ stub_request(:get, mock_href).to_return(return_data)
267
+ end
268
+ it "quietly exits" do
269
+ request = RestClient::Request.new(:url => mock_href,
270
+ :method => 'get',
271
+ :headers => {:accept => :json}
272
+ )
273
+ subject.send(request).should equal(nil)
274
+ end
275
+ end
276
+
277
+ context "with a request timeout" do
278
+ before do
279
+ stub_request(:get, mock_href).to_timeout
280
+ end
281
+ it "raises a resource access exception error" do
282
+ request = RestClient::Request.new(:url => mock_href,
283
+ :method => 'get',
284
+ :headers => {:accept => :json}
285
+ )
286
+ lambda { subject.send(request) }.should raise_error(Rhc::Rest::ResourceAccessException, 'Failed to access resource: Request Timeout')
287
+ end
288
+ end
289
+
290
+ context "with a broken server connection" do
291
+ before do
292
+ stub_request(:get, mock_href).to_raise(RestClient::ServerBrokeConnection.new('Lost Server Connection'))
293
+ end
294
+ it "raises a resource access exception error" do
295
+ request = RestClient::Request.new(:url => mock_href,
296
+ :method => 'get',
297
+ :headers => {:accept => :json}
298
+ )
299
+ lambda { subject.send(request) }.should raise_error(Rhc::Rest::ResourceAccessException, 'Failed to access resource: Lost Server Connection')
300
+ end
301
+ end
302
+
303
+ context "with an unverified SSL certificate" do
304
+ before do
305
+ stub_request(:get, mock_href).to_raise(RestClient::SSLCertificateNotVerified.new('Unverified SSL Certificate'))
306
+ end
307
+ it "raises a resource access exception error" do
308
+ request = RestClient::Request.new(:url => mock_href,
309
+ :method => 'get',
310
+ :headers => {:accept => :json}
311
+ )
312
+ lambda { subject.send(request) }.should raise_error(Rhc::Rest::ResourceAccessException, 'Failed to access resource: Unverified SSL Certificate')
313
+ end
314
+ end
315
+
316
+ context "with a generic exception error" do
317
+ before do
318
+ stub_request(:get, mock_href).to_raise(Exception.new('Generic Error'))
319
+ end
320
+
321
+ it "raises a resource access exception error" do
322
+ request = RestClient::Request.new(:url => mock_href,
323
+ :method => 'get',
324
+ :headers => {:accept => :json}
325
+ )
326
+ lambda { subject.send(request) }.should raise_error(Rhc::Rest::ResourceAccessException, 'Failed to access resource: Generic Error')
327
+ end
328
+ end
329
+
330
+ context "with a specific error response" do
331
+ before do
332
+ return_data = {
333
+ :body => nil,
334
+ :status => 401,
335
+ :headers => { 'Set-Cookie' => "rh_sso=test_ssh_cookie" }
336
+ }
337
+ stub_request(:get, mock_href).to_return(return_data)
338
+ end
339
+
340
+ it "passes the response off for interpretation" do
341
+ request = RestClient::Request.new(:url => mock_href,
342
+ :method => 'get',
343
+ :headers => {:accept => :json}
344
+ )
345
+ lambda { subject.send(request) }.should raise_error(Rhc::Rest::UnAuthorizedException, 'Not authenticated')
346
+ end
347
+ end
348
+ end
349
+
350
+ # process_error_response function
351
+ describe "process_error_response" do
352
+ context "with a 400 response" do
353
+ it "raises a client error" do
354
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
355
+ json_data = RHC::Json.encode(mock_resp)
356
+ json_data.extend(MockRestResponse)
357
+ json_data.set_code(400)
358
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ClientErrorException, 'mock error message')
359
+ end
360
+ end
361
+
362
+ context "with a 401 response" do
363
+ it "raises an 'unauthorized exception' error" do
364
+ json_data = RHC::Json.encode({})
365
+ json_data.extend(MockRestResponse)
366
+ json_data.set_code(401)
367
+
368
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::UnAuthorizedException, 'Not authenticated')
369
+ end
370
+ end
371
+
372
+ context "with a 403 response" do
373
+ it "raises a 'request denied' error" do
374
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
375
+ json_data = RHC::Json.encode(mock_resp)
376
+ json_data.extend(MockRestResponse)
377
+ json_data.set_code(403)
378
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::RequestDeniedException, 'mock error message')
379
+ end
380
+ end
381
+
382
+ context "with a 404 response" do
383
+ it "raises a 'resource not found' error" do
384
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
385
+ json_data = RHC::Json.encode(mock_resp)
386
+ json_data.extend(MockRestResponse)
387
+ json_data.set_code(404)
388
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ResourceNotFoundException, 'mock error message')
389
+ end
390
+ end
391
+
392
+ context "with a 409 response" do
393
+ it "raises a validation error" do
394
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
395
+ json_data = RHC::Json.encode(mock_resp)
396
+ json_data.extend(MockRestResponse)
397
+ json_data.set_code(409)
398
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ValidationException, 'mock error message')
399
+ end
400
+ end
401
+
402
+ context "with a 422 response" do
403
+ it "raises a validation error" do
404
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
405
+ json_data = RHC::Json.encode(mock_resp)
406
+ json_data.extend(MockRestResponse)
407
+ json_data.set_code(422)
408
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ValidationException, 'mock error message')
409
+ end
410
+ end
411
+
412
+ context "with multiple 422 responses" do
413
+ it "raises a validation error with concatenated messages" do
414
+ mock_resp = { :messages => [{ :field => 'error', :text => 'mock error message 1' },
415
+ { :field => 'error', :text => 'mock error message 2' }] }
416
+ json_data = RHC::Json.encode(mock_resp)
417
+ json_data.extend(MockRestResponse)
418
+ json_data.set_code(422)
419
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ValidationException, 'mock error message 1 mock error message 2')
420
+ end
421
+ end
422
+
423
+ context "with a 500 response" do
424
+ it "raises a server error" do
425
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
426
+ json_data = RHC::Json.encode(mock_resp)
427
+ json_data.extend(MockRestResponse)
428
+ json_data.set_code(500)
429
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ServerErrorException, 'mock error message')
430
+ end
431
+ end
432
+
433
+ context "with a 503 response" do
434
+ it "raises a 'service unavailable' error" do
435
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
436
+ json_data = RHC::Json.encode(mock_resp)
437
+ json_data.extend(MockRestResponse)
438
+ json_data.set_code(503)
439
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ServiceUnavailableException, 'mock error message')
440
+ end
441
+ end
442
+
443
+ context "with an unhandled response code" do
444
+ it "raises a resource access error" do
445
+ mock_resp = { :messages => [{ :severity => 'error', :text => 'mock error message' }] }
446
+ json_data = RHC::Json.encode(mock_resp)
447
+ json_data.extend(MockRestResponse)
448
+ json_data.set_code(999)
449
+ lambda { subject.process_error_response(json_data) }.should raise_error(Rhc::Rest::ResourceAccessException, 'Server returned error code with no output: 999')
450
+ end
451
+ end
452
+ end
453
+ end
454
+ end
@@ -39,4 +39,17 @@ describe RHC::TarGz do
39
39
  }
40
40
  end
41
41
 
42
+ context 'with simple compressed .tar.gz' do
43
+ subject { File.expand_path('../assets/targz_sample.tar.gz', __FILE__) }
44
+ it('should read file in chunks') {
45
+ control = false
46
+ File.open(subject, 'rb') do |file|
47
+ file.chunk(1024) do |chunk|
48
+ control = true
49
+ end
50
+ end
51
+ control.should be_true
52
+ }
53
+ end
54
+
42
55
  end