rhc 1.9.6 → 1.10.7

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 (46) hide show
  1. checksums.yaml +7 -0
  2. data/features/lib/rhc_helper.rb +0 -4
  3. data/features/lib/rhc_helper/app.rb +10 -10
  4. data/features/lib/rhc_helper/commandify.rb +6 -24
  5. data/features/support/before_hooks.rb +1 -1
  6. data/features/support/env.rb +9 -2
  7. data/features/support/platform_support.rb +11 -1
  8. data/lib/rhc/auth/basic.rb +4 -1
  9. data/lib/rhc/cartridge_helpers.rb +4 -8
  10. data/lib/rhc/commands.rb +6 -3
  11. data/lib/rhc/commands/alias.rb +1 -0
  12. data/lib/rhc/commands/app.rb +104 -67
  13. data/lib/rhc/commands/authorization.rb +2 -1
  14. data/lib/rhc/commands/base.rb +8 -1
  15. data/lib/rhc/commands/cartridge.rb +39 -16
  16. data/lib/rhc/commands/git_clone.rb +2 -1
  17. data/lib/rhc/commands/port_forward.rb +4 -6
  18. data/lib/rhc/commands/ssh.rb +54 -0
  19. data/lib/rhc/exceptions.rb +12 -7
  20. data/lib/rhc/git_helpers.rb +4 -5
  21. data/lib/rhc/help_formatter.rb +11 -6
  22. data/lib/rhc/helpers.rb +24 -3
  23. data/lib/rhc/highline_extensions.rb +31 -6
  24. data/lib/rhc/output_helpers.rb +0 -29
  25. data/lib/rhc/rest.rb +16 -1
  26. data/lib/rhc/rest/application.rb +7 -3
  27. data/lib/rhc/rest/base.rb +7 -2
  28. data/lib/rhc/rest/client.rb +7 -14
  29. data/lib/rhc/rest/gear_group.rb +10 -1
  30. data/lib/rhc/rest/mock.rb +34 -8
  31. data/lib/rhc/ssh_helpers.rb +144 -1
  32. data/lib/rhc/usage_templates/command_help.erb +16 -2
  33. data/spec/coverage_helper.rb +10 -7
  34. data/spec/rhc/commands/alias_spec.rb +28 -0
  35. data/spec/rhc/commands/app_spec.rb +64 -45
  36. data/spec/rhc/commands/authorization_spec.rb +16 -0
  37. data/spec/rhc/commands/cartridge_spec.rb +59 -3
  38. data/spec/rhc/commands/port_forward_spec.rb +6 -6
  39. data/spec/rhc/commands/ssh_spec.rb +125 -0
  40. data/spec/rhc/commands/tail_spec.rb +4 -3
  41. data/spec/rhc/helpers_spec.rb +70 -42
  42. data/spec/rhc/highline_extensions_spec.rb +23 -1
  43. data/spec/rhc/rest_client_spec.rb +6 -9
  44. data/spec/rhc/rest_spec.rb +41 -2
  45. data/spec/spec_helper.rb +38 -0
  46. metadata +336 -373
@@ -295,4 +295,32 @@ describe RHC::Commands::Alias do
295
295
  end
296
296
  end
297
297
 
298
+ describe 'aliases' do
299
+ before do
300
+ rest_client.stub(:api_version_negotiated).and_return(1.4)
301
+ end
302
+ context 'app with existing certificate' do
303
+ let(:arguments) { ['aliases', 'mock_app_0'] }
304
+ it { expect { run }.to exit_with_code(0) }
305
+ it { run_output.should =~ /Has Certificate?/m }
306
+ it { run_output.should =~ /Certificate Added/m }
307
+ it { run_output.should =~ /www.foo.bar/m }
308
+ end
309
+ context 'app without certificates' do
310
+ let(:arguments) { ['aliases', 'mock_app_1'] }
311
+ it { expect { run }.to exit_with_code(0) }
312
+ it { run_output.should =~ /No aliases associated with the application mock_app_1/m }
313
+ end
314
+ context 'simple list is server does not support ssl certs' do
315
+ let(:arguments) { ['aliases', 'mock_app_0'] }
316
+ before do
317
+ rest_client.stub(:api_version_negotiated).and_return(1.3)
318
+ end
319
+ it { expect { run }.to exit_with_code(0) }
320
+ it { run_output.should =~ /no/m }
321
+ it { run_output.should =~ /-/m }
322
+ it { run_output.should =~ /www.foo.bar/m }
323
+ end
324
+ end
325
+
298
326
  end
@@ -19,8 +19,10 @@ describe RHC::Commands::App do
19
19
  @instance.stub(:git_config_set) { "" }
20
20
  Kernel.stub(:sleep) { }
21
21
  @instance.stub(:git_clone_repo) do |git_url, repo_dir|
22
+ $terminal.instance_variable_get(:@output).puts "Cloning into..."
22
23
  raise RHC::GitException, "Error in git clone" if repo_dir == "giterrorapp"
23
24
  Dir::mkdir(repo_dir)
25
+ File.expand_path(repo_dir)
24
26
  end
25
27
  @instance.stub(:host_exists?) do |host|
26
28
  host.match("dnserror") ? false : true
@@ -41,6 +43,8 @@ describe RHC::Commands::App do
41
43
  context 'app' do
42
44
  let(:arguments) { ['app'] }
43
45
  it { run_output.should match('Usage:') }
46
+ it { run_output.should match('List of Actions') }
47
+ it { run_output.should_not match('Options') }
44
48
  end
45
49
  end
46
50
 
@@ -159,7 +163,7 @@ describe RHC::Commands::App do
159
163
  before{ rest_client.domains.clear }
160
164
  let(:arguments) { ['app', 'create', 'app1', 'mock_standalone_cart-1'] }
161
165
  # skips login stage and insecure check because of mock rest client, doesn't check keys
162
- it { run_output(['mydomain', 'y', 'mykey']).should match(/This wizard.*Checking your namespace.*Your domain name 'mydomain' has been successfully created.*Creating application.*Your public SSH key.*Uploading key 'mykey' .*Downloading the application.*Success/m) }
166
+ it { run_output(['mydomain', 'y', 'mykey']).should match(/This wizard.*Checking your namespace.*Your domain name 'mydomain' has been successfully created.*Creating application.*Your public SSH key.*Uploading key 'mykey'.*Your application 'app1' is now available.*Cloned to/m) }
163
167
  end
164
168
 
165
169
  context 'when run without a cart' do
@@ -207,8 +211,8 @@ describe RHC::Commands::App do
207
211
  let(:arguments) { ['app', 'create', 'app1', 'mock_standalone_cart-1', '--from', 'git://url', '--noprompt', '-p', 'password'] }
208
212
  it { expect { run }.to exit_with_code(0) }
209
213
  it { run_output.should match("Success") }
214
+ it { run_output.should match("Git remote: git:fake.foo/git/app1.git\n") }
210
215
  it { run_output.should match("Source Code: git://url\n") }
211
- it { run_output.should match("Initial Git URL: git://url\n") }
212
216
  after{ rest_client.domains.first.applications.first.initial_git_url.should == 'git://url' }
213
217
  end
214
218
 
@@ -229,9 +233,7 @@ describe RHC::Commands::App do
229
233
  end
230
234
 
231
235
  describe 'cart matching behavior' do
232
- before(:each) do
233
- domain = rest_client.add_domain("mockdomain")
234
- end
236
+ before{ rest_client.add_domain("mockdomain") }
235
237
 
236
238
  context 'multiple web matches' do
237
239
  let(:arguments) { ['app', 'create', 'app1', 'mock_standalone_cart', '--trace', '--noprompt'] }
@@ -246,8 +248,8 @@ describe RHC::Commands::App do
246
248
  it('picks the non web cart') { run_output.should match('Using unique_mock_cart-1') }
247
249
  end
248
250
  context 'when I pick very ambiguous carts' do
249
- let(:arguments) { ['app', 'create', 'app1', 'mock', '--noprompt'] }
250
- it('shows only web carts') { run_output.should_not match('unique_mock_cart-1') }
251
+ let(:arguments) { ['app', 'create', 'app1', 'mock', 'embcart-', '--noprompt'] }
252
+ it('shows only web carts') { run_output.should match("There are multiple cartridges matching 'mock'") }
251
253
  end
252
254
  context 'when I pick only embedded carts' do
253
255
  let(:arguments) { ['app', 'create', 'app1', 'mock_cart', '--trace', '--noprompt'] }
@@ -259,7 +261,7 @@ describe RHC::Commands::App do
259
261
  end
260
262
  context 'when I pick multiple standalone carts' do
261
263
  let(:arguments) { ['app', 'create', 'app1', 'unique_standalone', 'mock_standalone_cart', '--trace', '--noprompt'] }
262
- it { expect { run }.to raise_error(RHC::MultipleCartridgesException, /You must select only a single web cart/) }
264
+ it { expect { run }.to raise_error(RHC::MultipleCartridgesException, /There are multiple cartridges matching 'mock_standalone_cart'/) }
263
265
  end
264
266
  context 'when I pick a custom URL cart' do
265
267
  let(:arguments) { ['app', 'create', 'app1', 'http://foo.com', '--trace', '--noprompt'] }
@@ -267,9 +269,9 @@ describe RHC::Commands::App do
267
269
  it('lists the cart using the short_name') { run_output.should match(%r(Cartridges:\s+http://foo.com$)) }
268
270
  end
269
271
  context 'when I pick a custom URL cart and a web cart' do
270
- let(:arguments) { ['app', 'create', 'app1', 'http://foo.com', 'unique_standalone', '--trace', '--noprompt'] }
272
+ let(:arguments) { ['app', 'create', 'app1', 'http://foo.com', 'embcart-1', '--trace', '--noprompt'] }
271
273
  it('tells me about custom carts') { run_output.should match("The cartridge 'http://foo.com' will be downloaded") }
272
- it('lists the carts using the short_name') { run_output.should match(%r(Cartridges:\s+http://foo.com, mock_unique_standalone_cart-1$)) }
274
+ it('lists the carts using the short_name') { run_output.should match(%r(Cartridges:\s+http://foo.com, embcart-1$)) }
273
275
  end
274
276
  end
275
277
 
@@ -494,6 +496,37 @@ describe RHC::Commands::App do
494
496
  end
495
497
  end
496
498
  end
499
+
500
+ context "against a 1.5 server" do
501
+ let!(:rest_client){ nil }
502
+ let(:username){ mock_user }
503
+ let(:password){ 'password' }
504
+ let(:server){ mock_uri }
505
+ let(:arguments){ ['delete-app', 'foo', '--confirm', '--trace'] }
506
+ before do
507
+ stub_api(true)
508
+ stub_one_domain('test')
509
+ stub_one_application('test', 'foo')
510
+ end
511
+ before do
512
+ stub_api_request(:delete, "broker/rest/domains/test/applications/foo").
513
+ to_return({
514
+ :body => {
515
+ :type => nil,
516
+ :data => nil,
517
+ :messages => [
518
+ {:exit_code => 0, :field => nil, :severity => 'info', :text => 'Removed foo'},
519
+ {:exit_code => 0, :field => nil, :severity => 'result', :text => 'Job URL changed'},
520
+ ]
521
+ }.to_json,
522
+ :status => 200
523
+ })
524
+ end
525
+
526
+ it("should display info returned by the server"){ run_output.should match "Removed foo" }
527
+ it("should display results returned by the server"){ run_output.should match "Job URL changed" }
528
+ it('should exit successfully'){ expect{ run }.to exit_with_code(0) }
529
+ end
497
530
  end
498
531
 
499
532
  describe 'app show' do
@@ -564,66 +597,52 @@ describe RHC::Commands::App do
564
597
  end
565
598
 
566
599
  describe 'app show --gears' do
567
- let(:arguments) { ['app', 'show', 'app1', '--gears', '--noprompt'] }
600
+ let(:arguments) { ['app', 'show', 'app1', '--gears'] }
568
601
 
569
602
  context 'when run' do
570
603
  before(:each) do
571
604
  @domain = rest_client.add_domain("mockdomain")
572
605
  @domain.add_application("app1", "mock_type")
573
606
  end
574
- it { run_output.should match("fakegearid started fake_geargroup_cart-0.1 small fakegearid@fakesshurl.com") }
607
+ it { run_output.should match("fakegearid0 started mock_type small fakegearid0@fakesshurl.com") }
608
+ it { expect{ run }.to exit_with_code(0) }
575
609
  end
576
610
  end
577
611
 
578
- describe 'app ssh' do
579
- let(:arguments) { ['app', 'ssh', 'app1'] }
612
+ describe 'app show --gears quota' do
613
+ let(:arguments) { ['app', 'show', 'app1', '--gears', 'quota'] }
580
614
 
581
615
  context 'when run' do
582
- before(:each) do
616
+ before do
583
617
  @domain = rest_client.add_domain("mockdomain")
584
- @domain.add_application("app1", "mock_type")
585
- Kernel.should_receive(:system).with("ssh fakeuuidfortestsapp1@127.0.0.1").and_return(0)
618
+ @domain.add_application("app1", "mock_type", true)
619
+ expect_multi_ssh('echo "$(du -s 2>/dev/null | cut -f 1)"', 'fakegearid0@fakesshurl.com' => '1734934', 'fakegearid1@fakesshurl.com' => '1934234')
586
620
  end
587
- it { run_output.should match("Connecting to fakeuuidfortestsapp") }
588
- it { expect { run }.to exit_with_code(0) }
621
+ it { run_output.should match(/Gear.*Cartridges.*Used.*fakegearid0.*1\.7 MB.*1 GB.*fakegearid1.*1\.9 MB/m) }
622
+ it { expect{ run }.to exit_with_code(0) }
589
623
  end
590
624
  end
591
625
 
592
- describe 'app ssh no system ssh' do
593
- let(:arguments) { ['app', 'ssh', 'app1'] }
626
+ describe 'app show --gears ssh' do
627
+ let(:arguments) { ['app', 'show', 'app1', '--gears', 'ssh'] }
594
628
 
595
629
  context 'when run' do
596
- before(:each) do
630
+ before do
597
631
  @domain = rest_client.add_domain("mockdomain")
598
- @domain.add_application("app1", "mock_type")
599
- @instance.should_receive(:has_ssh?).and_return(false)
632
+ @domain.add_application("app1", "mock_type", true)
600
633
  end
601
- it { run_output.should match("Please use the --ssh option to specify the path to your SSH executable, or install SSH.") }
602
- it { expect { run }.to exit_with_code(1) }
634
+ it { run_output.should == "fakegearid0@fakesshurl.com\nfakegearid1@fakesshurl.com\n\n" }
635
+ it { expect{ run }.to exit_with_code(0) }
603
636
  end
604
637
  end
605
638
 
606
- describe 'app ssh can use system exec' do
607
- let(:arguments) { ['app', 'ssh', 'app1', '--ssh', 'path_to_ssh'] }
639
+ describe 'app show --gears badcommand' do
640
+ let(:arguments) { ['app', 'show', 'app1', '--gears', 'badcommand'] }
608
641
 
609
642
  context 'when run' do
610
- before(:each) do
611
- @domain = rest_client.add_domain("mockdomain")
612
- @domain.add_application("app1", "mock_type")
613
- @instance.should_not_receive(:has_ssh?)
614
- Kernel.should_receive(:system).with("path_to_ssh fakeuuidfortestsapp1@127.0.0.1").and_return(1)
615
- end
616
- it { run_output.should match("Connecting to fakeuuidfortestsapp") }
617
- it { expect { run }.to exit_with_code(1) }
618
- end
619
- end
620
-
621
- describe 'ssh tests' do
622
- let(:arguments) { ['app', 'ssh', 'app1', '-s /bin/blah'] }
623
-
624
- context 'has_ssh?' do
625
- before{ @instance.stub(:ssh_version){ raise "Fake Exception" } }
626
- its(:has_ssh?) { should be_false }
643
+ before{ rest_client.add_domain("mockdomain").add_application("app1", "mock_type", true) }
644
+ it { run_output.should match(/The operation badcommand is not supported/m) }
645
+ it { expect{ run }.to exit_with_code(1) }
627
646
  end
628
647
  end
629
648
 
@@ -52,6 +52,22 @@ describe RHC::Commands::Authorization do
52
52
  end
53
53
  end
54
54
 
55
+ describe '#list' do
56
+ let(:arguments) { ['authorization', 'list'] }
57
+ context "with authorizations" do
58
+ with_authorization
59
+ before{ stub_authorizations }
60
+ it('should display the note') { run_output.should =~ /an_authorization/ }
61
+ it('should display the token') { run_output.should =~ /Token:\s+a_token_value/ }
62
+ it('should display the expiration') { run_output.should =~ /Expires In:\s+1 minute/ }
63
+ it('should display the creation date') { run_output.should =~ /Created:\s+#{RHC::Helpers.date('2013-02-21T01:00:01Z')}/ }
64
+ it('should display the scopes') { run_output.should =~ /Scopes:\s+session read/ }
65
+ it{ expect{ run }.to exit_with_code(0) }
66
+ end
67
+
68
+ expect_an_unsupported_message
69
+ end
70
+
55
71
  describe "#delete" do
56
72
  let(:arguments) { ['authorization', 'delete', 'foo', 'bar'] }
57
73
 
@@ -59,6 +59,7 @@ describe RHC::Commands::Cartridge do
59
59
  it{ run_output.should match "Mock2 description\n\n" }
60
60
  it{ run_output.should match "Tagged with: scheduled" }
61
61
  it{ run_output.should_not match("Tagged with: cartridge") }
62
+ it{ run_output.should match /Premium Cart.*\[premium_cart\-1\*\] \(web\)/ }
62
63
  end
63
64
  end
64
65
  end
@@ -208,6 +209,38 @@ describe RHC::Commands::Cartridge do
208
209
  expect { run }.to raise_error RHC::CartridgeNotFoundException
209
210
  end
210
211
  end
212
+
213
+ context "against a 1.5 server" do
214
+ let!(:rest_client){ nil }
215
+ let(:username){ mock_user }
216
+ let(:password){ 'password' }
217
+ let(:server){ mock_uri }
218
+ let(:arguments){ ['remove-cartridge', 'jenkins-1.4', '-a', 'foo', '--confirm', '--trace'] }
219
+ before do
220
+ stub_api(true)
221
+ stub_one_domain('test')
222
+ stub_one_application('test', 'foo').with(:query => {:include => 'cartridges'})
223
+ stub_application_cartridges('test', 'foo', [{:name => 'php-5.3'}, {:name => 'jenkins-1.4'}])
224
+ end
225
+ before do
226
+ stub_api_request(:delete, "broker/rest/domains/test/applications/foo/cartridges/jenkins-1.4").
227
+ to_return({
228
+ :body => {
229
+ :type => nil,
230
+ :data => nil,
231
+ :messages => [
232
+ {:exit_code => 0, :field => nil, :severity => 'info', :text => 'Removed Jenkins'},
233
+ {:exit_code => 0, :field => nil, :severity => 'result', :text => 'Job URL changed'},
234
+ ]
235
+ }.to_json,
236
+ :status => 200
237
+ })
238
+ end
239
+
240
+ it("should display info returned by the server"){ run_output.should match "Removed Jenkins" }
241
+ it("should display results returned by the server"){ run_output.should match "Job URL changed" }
242
+ it('should exit successfully'){ expect{ run }.to exit_with_code(0) }
243
+ end
211
244
  end
212
245
 
213
246
  describe 'cartridge status' do
@@ -353,10 +386,10 @@ describe RHC::Commands::Cartridge do
353
386
  let(:arguments) { ['cartridge', 'scale', @cart_type || 'mock_type', '-a', 'app1', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] | (@extra_args || []) }
354
387
 
355
388
  let(:current_scale) { 1 }
356
- before(:each) do
389
+ before do
357
390
  domain = rest_client.add_domain("mock_domain")
358
- app = domain.add_application("app1", "mock_type", scalable)
359
- app.cartridges.first.stub(:current_scale).and_return(current_scale)
391
+ @app = domain.add_application("app1", "mock_type", scalable)
392
+ @app.cartridges.first.stub(:current_scale).and_return(current_scale)
360
393
  end
361
394
 
362
395
  context 'when run with scalable app' do
@@ -371,6 +404,21 @@ describe RHC::Commands::Cartridge do
371
404
  succeed_with_message "minimum: 6"
372
405
  end
373
406
 
407
+ it "with an explicit value" do
408
+ @extra_args = ["6"]
409
+ succeed_with_message "minimum: 6, maximum: 6"
410
+ end
411
+
412
+ it "with an invalid explicit value" do
413
+ @extra_args = ["a6"]
414
+ fail_with_message "Multiplier must be a positive integer"
415
+ end
416
+
417
+ it "with an explicit value and a different minimum" do
418
+ @extra_args = ["6", "--min", "5"]
419
+ succeed_with_message "minimum: 5, maximum: 6"
420
+ end
421
+
374
422
  it "with a max value" do
375
423
  @extra_args = ["--max","3"]
376
424
  succeed_with_message 'maximum: 3'
@@ -385,6 +433,14 @@ describe RHC::Commands::Cartridge do
385
433
  @extra_args = ["--max","a"]
386
434
  fail_with_message "invalid argument: --max"
387
435
  end
436
+
437
+ context "when the operation times out" do
438
+ before{ @app.cartridges.first.should_receive(:set_scales).twice.and_raise(RHC::Rest::TimeoutException.new('Timeout', HTTPClient::ReceiveTimeoutError.new)) }
439
+ it "displays an error" do
440
+ @extra_args = ["--min","2"]
441
+ fail_with_message "The server has closed the connection, but your scaling operation is still in progress"
442
+ end
443
+ end
388
444
  end
389
445
 
390
446
  context 'when run with a nonscalable app' do
@@ -28,7 +28,7 @@ describe RHC::Commands::PortForward do
28
28
  it "should error out and suggest restarting the application" do
29
29
  expect { run }.to exit_with_code(1)
30
30
  end
31
- it { run_output.should match(/Application \S+ is stopped\..*restart/m) }
31
+ it { run_output.should match(/none.*The application is stopped\..*restart/m) }
32
32
  end
33
33
 
34
34
  context 'when port forwarding an app without ports to forward' do
@@ -174,11 +174,11 @@ describe RHC::Commands::PortForward do
174
174
 
175
175
  context 'when port forwarding a single gear on a scaled app' do
176
176
  let(:gear_host) { 'fakesshurl.com' }
177
- let(:gear_user) { 'fakegearid' }
177
+ let(:gear_user) { 'fakegearid0' }
178
178
  let(:arguments) { ['port-forward', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password', '--app', 'mockapp', '--gear', @gear_id] }
179
179
 
180
180
  it 'should run successfully' do
181
- @gear_id = 'fakegearid'
181
+ @gear_id = 'fakegearid0'
182
182
  Net::SSH.should_receive(:start).with(gear_host, gear_user).and_yield(@ssh).twice
183
183
 
184
184
  @ssh.should_receive(:exec!).with("rhc-list-ports --exclude-remote").
@@ -199,15 +199,15 @@ describe RHC::Commands::PortForward do
199
199
  end
200
200
 
201
201
  it 'should fail if the specified gear has no ssh info' do
202
- @gear_id = 'fakegearid'
202
+ @gear_id = 'fakegearid0'
203
203
 
204
204
  # Given - gears in gear group should not have ssh info
205
205
  gg = MockRestGearGroup.new(rest_client)
206
206
  @app.stub(:gear_groups).and_return([gg])
207
- gg.stub(:gears).and_return([{'state' => 'started', 'id' => 'fakegearid'}])
207
+ gg.stub(:gears).and_return([{'state' => 'started', 'id' => 'fakegearid0'}])
208
208
 
209
209
  expect { run }.to exit_with_code(1)
210
- run_output.should include('The server does not support per gear operations')
210
+ run_output.should match('The server does not support operations on individual gears.')
211
211
  end
212
212
 
213
213
  end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/ssh'
4
+
5
+ describe RHC::Commands::Ssh do
6
+ let!(:rest_client){ MockRestClient.new }
7
+ let!(:config){ user_config }
8
+ before{ RHC::Config.stub(:home_dir).and_return('/home/mock_user') }
9
+ before{ Kernel.stub(:exec).and_raise(RuntimeError) }
10
+
11
+ describe 'ssh default' do
12
+ context 'ssh' do
13
+ let(:arguments) { ['ssh'] }
14
+ it { run_output.should match('Usage:') }
15
+ end
16
+ end
17
+
18
+ describe 'ssh without command' do
19
+ let(:arguments) { ['app', 'ssh', 'app1'] }
20
+
21
+ context 'when run' do
22
+ before(:each) do
23
+ @domain = rest_client.add_domain("mockdomain")
24
+ @domain.add_application("app1", "mock_type")
25
+ Kernel.should_receive(:exec).with("ssh", "fakeuuidfortestsapp1@127.0.0.1").and_return(0)
26
+ end
27
+ it { run_output.should match("Connecting to fakeuuidfortestsapp") }
28
+ it { expect{ run }.to exit_with_code(0) }
29
+ end
30
+ end
31
+
32
+ describe 'app ssh with command' do
33
+ let(:arguments) { ['app', 'ssh', 'app1', 'ls', '/tmp'] }
34
+
35
+ context 'when run' do
36
+ before(:each) do
37
+ @domain = rest_client.add_domain("mockdomain")
38
+ @domain.add_application("app1", "mock_type")
39
+ Kernel.should_receive(:exec).with("ssh", "fakeuuidfortestsapp1@127.0.0.1", "ls", "/tmp").and_return(0)
40
+ end
41
+ it { run_output.should_not match("Connecting to fakeuuidfortestsapp") }
42
+ it { expect { run }.to exit_with_code(0) }
43
+ end
44
+ end
45
+
46
+ describe 'app ssh with --gears' do
47
+ before{ rest_client.add_domain("mockdomain").add_application("app1", "mock_type", true) }
48
+
49
+ context 'with no command' do
50
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears'] }
51
+ it('should display usage info') { run_output.should match("Usage:") }
52
+ it { expect { run }.to exit_with_code(1) }
53
+ end
54
+ context 'with a command' do
55
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--trace'] }
56
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
57
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid1 ] bar\n\n" }
58
+ it('should return successfully') { expect{ run }.to exit_with_code(0) }
59
+ end
60
+ context 'with --raw' do
61
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--raw'] }
62
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
63
+ it('should print the ssh output') { run_output.should == "foo\nbar\n\n" }
64
+ end
65
+ context 'with --limit' do
66
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--limit', '1'] }
67
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
68
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid1 ] bar\n\n" }
69
+ end
70
+ context 'with invalid --limit value' do
71
+ ['0','-10'].each do |value|
72
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--limit', value] }
73
+ it { run_output.should match('--limit must be an integer greater than zero') }
74
+ end
75
+ end
76
+ context 'with multiline output and --always-prefix' do
77
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--always-prefix'] }
78
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => "foo\ntest", 'fakegearid1@fakesshurl.com' => "bar\ntest") }
79
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid0 ] test\n[fakegearid1 ] bar\n[fakegearid1 ] test\n\n" }
80
+ end
81
+ context 'with multiline output' do
82
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command'] }
83
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => "foo\ntest", 'fakegearid1@fakesshurl.com' => "bar\ntest") }
84
+ it('should print the ssh output') { run_output.should == "=== fakegearid0 \nfoo\ntest\n=== fakegearid1 \nbar\ntest\n\n" }
85
+ end
86
+ end
87
+
88
+ describe 'app ssh no system ssh' do
89
+ let(:arguments) { ['app', 'ssh', 'app1'] }
90
+
91
+ context 'when run' do
92
+ before(:each) do
93
+ @domain = rest_client.add_domain("mockdomain")
94
+ @domain.add_application("app1", "mock_type")
95
+ RHC::Commands::Ssh.any_instance.should_receive(:has_ssh?).and_return(false)
96
+ end
97
+ it { run_output.should match("Please use the --ssh option to specify the path to your SSH executable, or install SSH.") }
98
+ it { expect { run }.to exit_with_code(1) }
99
+ end
100
+ end
101
+
102
+ describe 'app ssh custom ssh' do
103
+ let(:arguments) { ['app', 'ssh', 'app1', '--ssh', 'path_to_ssh'] }
104
+
105
+ context 'when run' do
106
+ before(:each) do
107
+ @domain = rest_client.add_domain("mockdomain")
108
+ @domain.add_application("app1", "mock_type")
109
+ RHC::Commands::Ssh.any_instance.should_not_receive(:has_ssh?)
110
+ Kernel.should_receive(:exec).with("path_to_ssh", "fakeuuidfortestsapp1@127.0.0.1").once.times.and_return(0)
111
+ end
112
+ it { run_output.should match("Connecting to fakeuuidfortestsapp") }
113
+ it { expect { run }.to exit_with_code(0) }
114
+ end
115
+ end
116
+
117
+ describe 'ssh tests' do
118
+ let(:arguments) { ['app', 'ssh', 'app1', '-s /bin/blah'] }
119
+
120
+ context 'has_ssh?' do
121
+ before{ RHC::Commands::Ssh.any_instance.stub(:ssh_version){ raise "Fake Exception" } }
122
+ its(:has_ssh?) { should be_false }
123
+ end
124
+ end
125
+ end