startapp 0.1.6

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 (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/server'
4
+ require 'rhc/config'
5
+
6
+ describe RHC::Commands::Server do
7
+ before(:each){ user_config }
8
+ let(:rest_client) { MockRestClient.new }
9
+
10
+ describe 'run against a different server' do
11
+ let(:arguments) { ['server', '--server', 'foo.com', '-l', 'person', '-p', ''] }
12
+
13
+ context 'when server refuses connection' do
14
+ before { stub_request(:get, 'https://foo.com/broker/rest/api').with(&user_agent_header).to_raise(SocketError) }
15
+ it('should output an error') { run_output.should =~ /Connected to foo.com.*Unable to connect to the server/m }
16
+ it { expect { run }.to exit_with_code(1) }
17
+ end
18
+
19
+ context 'when API is missing' do
20
+ before { stub_request(:get, 'https://foo.com/broker/rest/api').with(&user_agent_header).to_return(:status => 404) }
21
+ it('should output an error') { run_output.should =~ /Connected to foo.com.*server is not responding correctly/m }
22
+ it { expect { run }.to exit_with_code(1) }
23
+ end
24
+
25
+ context 'when API is at version 1.2' do
26
+ before do
27
+ rest_client.stub(:api_version_negotiated).and_return('1.2')
28
+ end
29
+ it('should output an error') { run_output.should =~ /Connected to foo.com.*Using API version 1.2/m }
30
+ it { expect { run }.to exit_with_code(0) }
31
+ end
32
+ end
33
+
34
+ describe 'run against an invalid server url' do
35
+ let(:arguments) { ['server', '--server', 'invalid_uri', '-l', 'person', '-p', ''] }
36
+ it('should output an invalid URI error') { run_output.should match('Invalid URI specified: invalid_uri') }
37
+ end
38
+
39
+ describe 'run' do
40
+ let(:arguments) { ['server'] }
41
+ before{ rest_client.stub(:auth).and_return(nil) }
42
+
43
+ context 'when no issues' do
44
+ before { stub_request(:get, 'https://broker.startapp.bg/app/status/status.json').with(&user_agent_header).to_return(:body => {'issues' => []}.to_json) }
45
+ it('should output success') { run_output.should =~ /All systems running fine/ }
46
+ it { expect { run }.to exit_with_code(0) }
47
+ end
48
+
49
+ context 'when 1 issue' do
50
+ before do
51
+ stub_request(:get, 'https://broker.startapp.bg/app/status/status.json').with(&user_agent_header).to_return(:body =>
52
+ {'open' => [
53
+ {'issue' => {
54
+ 'created_at' => '2011-05-22T17:31:32-04:00',
55
+ 'id' => 11,
56
+ 'title' => 'Root cause',
57
+ 'updates' => [{
58
+ 'created_at' => '2012-05-22T13:48:20-04:00',
59
+ 'description' => 'Working on update'
60
+ }]
61
+ }}]}.to_json)
62
+ end
63
+ it { expect { run }.to exit_with_code(1) }
64
+ it('should output message') { run_output.should =~ /1 open issue/ }
65
+ it('should output title') { run_output.should =~ /Root cause/ }
66
+ it('should contain update') { run_output.should =~ /Working on update/ }
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/setup'
4
+
5
+ # just test the command runner as we already have extensive wizard tests
6
+ describe RHC::Commands::Setup do
7
+ subject{ RHC::Commands::Setup }
8
+ let(:instance){ subject.new }
9
+ let!(:config){ base_config }
10
+ before{ described_class.send(:public, *described_class.protected_instance_methods) }
11
+ before{ FakeFS::FileSystem.clear }
12
+ before{ RHC::Config.stub(:home_dir).and_return('/home/mock_user') }
13
+
14
+ describe '#run' do
15
+ it{ expects_running('setup').should call(:run).on(instance).with(no_args) }
16
+
17
+ let(:arguments) { ['setup', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
18
+
19
+ before(:each) do
20
+ @wizard = double('wizard')
21
+ @wizard.stub(:run).and_return(true)
22
+ RHC::RerunWizard.stub(:new){ @wizard }
23
+ end
24
+
25
+ context 'when no issues' do
26
+ it "should exit 0" do
27
+ expect { run }.to exit_with_code(0)
28
+ end
29
+ end
30
+
31
+ context 'when there is an issue' do
32
+ it "should exit 1" do
33
+ @wizard.stub(:run).and_return(false)
34
+ expect { run }.to exit_with_code(1)
35
+ end
36
+ end
37
+ end
38
+
39
+ it{ expects_running('setup').should call(:run).on(instance).with(no_args) }
40
+ it{ command_for('setup', '--clean').options.clean.should be_true }
41
+
42
+ it{ command_for('setup').options.server.should == 'broker.startapp.bg' }
43
+ it{ command_for('setup', '--server', 'foo.com').options.server.should == 'foo.com' }
44
+ it{ command_for('setup', '--no-create-token').options.create_token.should == false }
45
+ it{ command_for('setup', '--create-token').options.create_token.should == true }
46
+
47
+ context "when config has use_authorization_tokens=false" do
48
+ let!(:config){ base_config{ |c, d| d.add('use_authorization_tokens', 'false') } }
49
+ it{ command_for('setup').options.use_authorization_tokens.should == false }
50
+ end
51
+ context "when config has use_authorization_tokens=true" do
52
+ let!(:config){ base_config{ |c, d| d.add('use_authorization_tokens', 'true') } }
53
+ it{ command_for('setup').options.use_authorization_tokens.should == true }
54
+ end
55
+
56
+ =begin context 'when libra_server is set' do
57
+ before{ ENV.stub(:[]).with('LIBRA_SERVER').and_return('bar.com') }
58
+ it{ command_for('setup').config['libra_server'].should == 'bar.com' }
59
+ it{ command_for('setup').options.server.should == 'bar.com' }
60
+ it{ command_for('setup', '--server', 'foo.com').options.server.should == 'foo.com' }
61
+ =end end
62
+
63
+ context 'when --clean is used' do
64
+ let!(:config){ base_config{ |config, defaults| defaults.add 'libra_server', 'test.com' } }
65
+
66
+ it("should ignore a config value"){ command_for('setup', '--clean').options.server.should == 'broker.startapp.bg' }
67
+ end
68
+
69
+ context 'when -d is passed' do
70
+ let(:arguments) { ['setup', '-d', '-l', 'test@test.foo'] }
71
+ # 'y' for the password prompt
72
+ let(:input) { ['', 'y', '', ''] }
73
+ let!(:rest_client){ MockRestClient.new }
74
+
75
+ it("succeeds"){ FakeFS{ expect { run input }.to exit_with_code 0 } }
76
+ it("the output includes debug output") do
77
+ FakeFS{ run_output( input ).should match 'DEBUG' }
78
+ end
79
+ end
80
+
81
+ context 'when -l is used to specify the user name' do
82
+ let(:arguments) { ['setup', '-l', 'test@test.foo'] }
83
+ # 'y' for the password prompt
84
+ let(:input) { ['', 'y', '', ''] }
85
+ let!(:rest_client){ MockRestClient.new }
86
+
87
+ it("succeeds"){ FakeFS{ expect { run input }.to exit_with_code 0 } }
88
+ it("sets the user name to the value given by the command line") do
89
+ FakeFS{ run_output( input ).should match 'test@test.foo' }
90
+ end
91
+ end
92
+
93
+ describe 'help' do
94
+ let(:arguments) { ['setup', '--help'] }
95
+
96
+ context 'help is run' do
97
+ it "should display help" do
98
+ @wizard.stub(:run).and_return(true)
99
+ expect { run }.to exit_with_code(0)
100
+ end
101
+ it('should output usage') { run_output.should match("Connects to an StartApp server to get you started. Will") }
102
+ end
103
+ end
104
+
105
+ describe '--autocomplete' do
106
+ let(:arguments) { ['setup', '--autocomplete'] }
107
+ before do
108
+ path = File.join(Gem.loaded_specs['app'].full_gem_path, "autocomplete")
109
+ FakeFS::FileUtils.mkdir_p(path)
110
+ FakeFS::FileUtils.touch(File.join(path, "rhc_bash"))
111
+ end
112
+
113
+ context 'is passed' do
114
+ it('should output information') { FakeFS{ run_output.should match("To enable tab-completion") } }
115
+ it('should output the gem path') { FakeFS{ run_output.should match File.join(RHC::Config.home_conf_dir, 'bash_autocomplete') } }
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,179 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/snapshot'
4
+ require 'rhc/config'
5
+ require 'rhc/tar_gz'
6
+
7
+ describe RHC::Commands::Snapshot do
8
+
9
+ APP_NAME = 'mockapp'
10
+
11
+ let!(:rest_client) { MockRestClient.new }
12
+ before do
13
+ user_config
14
+ @app = rest_client.add_domain("mockdomain").add_application APP_NAME, 'mock-1.0'
15
+ @ssh_uri = URI.parse @app.ssh_url
16
+ @targz_filename = APP_NAME + '.tar.gz'
17
+ FileUtils.cp(File.expand_path('../../assets/targz_sample.tar.gz', __FILE__), @targz_filename)
18
+ File.chmod 0644, @targz_filename unless File.executable? @targz_filename
19
+ end
20
+
21
+ after do
22
+ File.delete @targz_filename if File.exist? @targz_filename
23
+ end
24
+
25
+ describe 'snapshot without an action' do
26
+ let(:arguments) {['snapshot', '--trace', '--noprompt']}
27
+ it('should raise') { expect{ run }.to raise_error(ArgumentError, /Please specify an action to take/) }
28
+ end
29
+
30
+ describe 'snapshot save' do
31
+ let(:arguments) {['snapshot', 'save', '--app', 'mockapp', '-d']}
32
+
33
+ context 'when saving a snapshot' do
34
+ before do
35
+ subject.class.any_instance.should_receive(:exec).with("ssh #{@ssh_uri.user}@#{@ssh_uri.host} 'snapshot' > #{@app.name}.tar.gz").and_return([0, 'some save output'])
36
+ end
37
+ it { expect { run }.to exit_with_code(0) }
38
+ it { run_output.should_not match 'some save output' }
39
+ end
40
+
41
+ context 'when failing to save a snapshot' do
42
+ before do
43
+ subject.class.any_instance.should_receive(:has_ssh?).and_return(true)
44
+ subject.class.any_instance.should_receive(:exec).with("ssh #{@ssh_uri.user}@#{@ssh_uri.host} 'snapshot' > #{@app.name}.tar.gz").and_return([1, 'some save failures'])
45
+ end
46
+ it { expect { run }.to exit_with_code(130) }
47
+ it { run_output.should match 'some save failures' }
48
+ end
49
+
50
+ context 'when saving a snapshot on windows' do
51
+ before do
52
+ RHC::Helpers.stub(:windows?) do ; true; end
53
+ RHC::Helpers.stub(:jruby?) do ; false ; end
54
+ RHC::Helpers.stub(:linux?) do ; false ; end
55
+ ssh = double(Net::SSH)
56
+ Net::SSH.should_receive(:start).with(@ssh_uri.host, @ssh_uri.user).and_yield(ssh)
57
+ ssh.should_receive(:exec!).with("snapshot").and_yield(nil, :stdout, 'foo').and_yield(nil, :stderr, 'foo')
58
+ end
59
+ it { expect { run }.to exit_with_code(0) }
60
+ it { run_output.should match("Success") }
61
+ end
62
+
63
+ context 'when timing out on windows' do
64
+ before do
65
+ RHC::Helpers.stub(:windows?) do ; true; end
66
+ RHC::Helpers.stub(:jruby?) do ; false ; end
67
+ RHC::Helpers.stub(:linux?) do ; false ; end
68
+ ssh = double(Net::SSH)
69
+ Net::SSH.should_receive(:start).with(@ssh_uri.host, @ssh_uri.user).and_raise(Timeout::Error)
70
+ end
71
+ it { expect { run }.to exit_with_code(130) }
72
+ end
73
+
74
+ describe 'snapshot save deployment' do
75
+ let(:arguments) {['snapshot', 'save', '--app', 'mockapp', '--deployment', '-d']}
76
+
77
+ context 'when saving a deployment snapshot' do
78
+ before do
79
+ subject.class.any_instance.should_receive(:exec).with("ssh #{@ssh_uri.user}@#{@ssh_uri.host} 'gear archive-deployment' > #{@app.name}.tar.gz").and_return([0, 'some save output'])
80
+ end
81
+ it { expect { run }.to exit_with_code(0) }
82
+ it { run_output.should_not match 'some save output' }
83
+ end
84
+ end
85
+
86
+ end
87
+
88
+ describe 'snapshot save with invalid ssh executable' do
89
+ let(:arguments) {['snapshot', 'save', '--trace', '--noprompt', '-l', 'test@test.foo', '-p', 'password', '--app', 'mockapp', '--ssh', 'path_to_ssh']}
90
+ it('should raise') { expect{ run }.to raise_error(RHC::InvalidSSHExecutableException, /SSH executable 'path_to_ssh' does not exist./) }
91
+ end
92
+
93
+ describe 'snapshot save when ssh is not executable' do
94
+ let(:arguments) {['snapshot', 'save', '--trace', '--noprompt', '-l', 'test@test.foo', '-p', 'password', '--app', 'mockapp', '--ssh', @targz_filename]}
95
+ it('should raise') { expect{ run }.to raise_error(RHC::InvalidSSHExecutableException, /SSH executable '#{@targz_filename}' is not executable./) }
96
+ end
97
+
98
+ describe 'snapshot restore' do
99
+ let(:arguments) {['snapshot', 'restore', '--app', 'mockapp', '-d']}
100
+
101
+ context 'when restoring a snapshot' do
102
+ before do
103
+ File.stub(:exists?).and_return(true)
104
+ RHC::TarGz.stub(:contains).and_return(true)
105
+ subject.class.any_instance.should_receive(:exec).with("cat '#{@app.name}.tar.gz' | ssh #{@ssh_uri.user}@#{@ssh_uri.host} 'restore INCLUDE_GIT'").and_return([0, 'some restore output'])
106
+ end
107
+ it('should succeed') { expect { run }.to exit_with_code(0) }
108
+ it { run_output.should_not match 'some restore output' }
109
+ end
110
+
111
+ context 'when restoring a snapshot and failing to ssh' do
112
+ before do
113
+ File.stub(:exists?).and_return(true)
114
+ RHC::TarGz.stub(:contains).and_return(true)
115
+ subject.class.any_instance.should_receive(:has_ssh?).and_return(true)
116
+ subject.class.any_instance.should_receive(:exec).with("cat '#{@app.name}.tar.gz' | ssh #{@ssh_uri.user}@#{@ssh_uri.host} 'restore INCLUDE_GIT'").and_return([1, 'some restore failures'])
117
+ end
118
+ it { expect { run }.to exit_with_code(130) }
119
+ it { run_output.should match 'some restore failures' }
120
+ end
121
+
122
+ context 'when restoring a snapshot on windows' do
123
+ before do
124
+ RHC::Helpers.stub(:windows?) do ; true; end
125
+ RHC::Helpers.stub(:jruby?) do ; false ; end
126
+ RHC::Helpers.stub(:linux?) do ; false ; end
127
+ ssh = double(Net::SSH)
128
+ session = double(Net::SSH::Connection::Session)
129
+ channel = double(Net::SSH::Connection::Channel)
130
+ Net::SSH.should_receive(:start).with(@ssh_uri.host, @ssh_uri.user).and_return(session)
131
+ session.should_receive(:open_channel).and_yield(channel)
132
+ channel.should_receive(:exec).with("restore INCLUDE_GIT").and_yield(nil, nil)
133
+ channel.should_receive(:on_data).and_yield(nil, 'foo')
134
+ channel.should_receive(:on_extended_data).and_yield(nil, nil, 'foo')
135
+ channel.should_receive(:on_close).and_yield(nil)
136
+ lines = ''
137
+ File.open(File.expand_path('../../assets/targz_sample.tar.gz', __FILE__), 'rb') do |file|
138
+ file.chunk(1024) do |chunk|
139
+ lines << chunk
140
+ end
141
+ end
142
+ channel.should_receive(:send_data).with(lines)
143
+ channel.should_receive(:eof!)
144
+ session.should_receive(:loop)
145
+ end
146
+ it { expect { run }.to exit_with_code(0) }
147
+ end
148
+
149
+ context 'when timing out on windows' do
150
+ before do
151
+ RHC::Helpers.stub(:windows?) do ; true; end
152
+ RHC::Helpers.stub(:jruby?) do ; false ; end
153
+ RHC::Helpers.stub(:linux?) do ; false ; end
154
+ ssh = double(Net::SSH)
155
+ Net::SSH.should_receive(:start).with(@ssh_uri.host, @ssh_uri.user).and_raise(Timeout::Error)
156
+ end
157
+ it { expect { run }.to exit_with_code(130) }
158
+ end
159
+
160
+ end
161
+
162
+ describe 'snapshot restore file not found' do
163
+ let(:arguments) {['snapshot', 'restore', 'mockapp', '-f', 'foo.tar.gz']}
164
+ context 'when restoring a snapshot' do
165
+ it { expect { run }.to exit_with_code(130) }
166
+ end
167
+ end
168
+
169
+ describe 'snapshot restore with invalid ssh executable' do
170
+ let(:arguments) {['snapshot', 'restore', '--trace', '--noprompt', '-l', 'test@test.foo', '-p', 'password', '--app', 'mockapp', '--ssh', 'path_to_ssh']}
171
+ it('should raise') { expect{ run }.to raise_error(RHC::InvalidSSHExecutableException, /SSH executable 'path_to_ssh' does not exist./) }
172
+ end
173
+
174
+ describe 'snapshot save when ssh is not executable' do
175
+ let(:arguments) {['snapshot', 'restore', '--trace', '--noprompt', '-l', 'test@test.foo', '-p', 'password', '--app', 'mockapp', '--ssh', @targz_filename]}
176
+ it('should raise') { expect{ run }.to raise_error(RHC::InvalidSSHExecutableException, /SSH executable '#{@targz_filename}' is not executable./) }
177
+ end
178
+ end
179
+
@@ -0,0 +1,163 @@
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 an implicit app name' do
61
+ before{ subject.class.any_instance.stub(:git_config_get){ |key| 'app1' if key == "rhc.app-name" } }
62
+ let(:arguments) { ['app', 'ssh', '--gears', '--', 'command', '--trace'] }
63
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
64
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid1 ] bar\n\n" }
65
+ it('should return successfully') { expect{ run }.to exit_with_code(0) }
66
+ end
67
+ context 'with an application id' do
68
+ let(:arguments) { ['app', 'ssh', '--application-id', rest_client.domains.first.applications.first.id, '--gears', 'command', '--trace'] }
69
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
70
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid1 ] bar\n\n" }
71
+ it('should return successfully') { expect{ run }.to exit_with_code(0) }
72
+ end
73
+ context 'with --raw' do
74
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--raw'] }
75
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
76
+ it('should print the ssh output') { run_output.should == "foo\nbar\n\n" }
77
+ end
78
+ context 'with --limit' do
79
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--limit', '1'] }
80
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => 'foo', 'fakegearid1@fakesshurl.com' => 'bar') }
81
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid1 ] bar\n\n" }
82
+ end
83
+ context 'with invalid --limit value' do
84
+ ['0','-10'].each do |value|
85
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--limit', value] }
86
+ it { run_output.should match('--limit must be an integer greater than zero') }
87
+ end
88
+ end
89
+ context 'with multiline output and --always-prefix' do
90
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command', '--always-prefix'] }
91
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => "foo\ntest", 'fakegearid1@fakesshurl.com' => "bar\ntest") }
92
+ it('should print the ssh output') { run_output.should == "[fakegearid0 ] foo\n[fakegearid0 ] test\n[fakegearid1 ] bar\n[fakegearid1 ] test\n\n" }
93
+ end
94
+ context 'with multiline output' do
95
+ let(:arguments) { ['app', 'ssh', 'app1', '--gears', 'command'] }
96
+ before{ expect_multi_ssh('command', 'fakegearid0@fakesshurl.com' => "foo\ntest", 'fakegearid1@fakesshurl.com' => "bar\ntest") }
97
+ it('should print the ssh output') { run_output.should == "=== fakegearid0 \nfoo\ntest\n=== fakegearid1 \nbar\ntest\n\n" }
98
+ end
99
+ end
100
+
101
+ describe 'app ssh no system ssh' do
102
+ let(:arguments) { ['app', 'ssh', 'app1'] }
103
+
104
+ context 'when run' do
105
+ before(:each) do
106
+ @domain = rest_client.add_domain("mockdomain")
107
+ @domain.add_application("app1", "mock_type")
108
+ RHC::Commands::Ssh.any_instance.should_receive(:has_ssh?).and_return(false)
109
+ end
110
+ it { run_output.should match("No system SSH available. Please use the --ssh option to specify the path to your SSH executable, or install SSH.") }
111
+ it { expect { run }.to exit_with_code(1) }
112
+ end
113
+ end
114
+
115
+ describe 'app ssh custom ssh' do
116
+ let(:arguments) { ['app', 'ssh', 'app1', '--ssh', 'path_to_ssh'] }
117
+
118
+ context 'when custom ssh does not exist' do
119
+ before(:each) do
120
+ @domain = rest_client.add_domain("mockdomain")
121
+ @domain.add_application("app1", "mock_type")
122
+ RHC::Commands::Ssh.any_instance.should_not_receive(:has_ssh?)
123
+ File.should_receive(:exist?).with("path_to_ssh").once.and_return(false)
124
+ end
125
+ it { run_output.should match("SSH executable 'path_to_ssh' does not exist.") }
126
+ it { expect { run }.to exit_with_code(1) }
127
+ end
128
+
129
+ context 'when custom ssh is not executable' do
130
+ before(:each) do
131
+ @domain = rest_client.add_domain("mockdomain")
132
+ @domain.add_application("app1", "mock_type")
133
+ RHC::Commands::Ssh.any_instance.should_not_receive(:has_ssh?)
134
+ File.should_receive(:exist?).with("path_to_ssh").once.and_return(true)
135
+ File.should_receive(:executable?).with(/.*path_to_ssh/).at_least(1).and_return(false)
136
+ end
137
+ it { run_output.should match("SSH executable 'path_to_ssh' is not executable.") }
138
+ it { expect { run }.to exit_with_code(1) }
139
+ end
140
+
141
+ context 'when custom ssh exists' do
142
+ before(:each) do
143
+ @domain = rest_client.add_domain("mockdomain")
144
+ @domain.add_application("app1", "mock_type")
145
+ RHC::Commands::Ssh.any_instance.should_not_receive(:has_ssh?)
146
+ File.should_receive(:exist?).with("path_to_ssh").once.and_return(true)
147
+ File.should_receive(:executable?).with("path_to_ssh").once.and_return(true)
148
+ Kernel.should_receive(:exec).with("path_to_ssh", "fakeuuidfortestsapp1@127.0.0.1").once.times.and_return(0)
149
+ end
150
+ it { run_output.should match("Connecting to fakeuuidfortestsapp") }
151
+ it { expect { run }.to exit_with_code(0) }
152
+ end
153
+ end
154
+
155
+ describe 'ssh tests' do
156
+ let(:arguments) { ['app', 'ssh', 'app1', '-s /bin/blah'] }
157
+
158
+ context 'has_ssh?' do
159
+ before{ RHC::Commands::Ssh.any_instance.stub(:ssh_version){ raise "Fake Exception" } }
160
+ its(:has_ssh?) { should be_false }
161
+ end
162
+ end
163
+ end