pbox 1.17.2

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 (139) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +40 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/pbox_bash +1639 -0
  7. data/bin/pbox +37 -0
  8. data/conf/protonbox.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +178 -0
  11. data/features/deployments_feature.rb +127 -0
  12. data/features/domains_feature.rb +49 -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 +186 -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 +701 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +96 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +326 -0
  31. data/lib/rhc/commands/deployment.rb +82 -0
  32. data/lib/rhc/commands/domain.rb +167 -0
  33. data/lib/rhc/commands/env.rb +142 -0
  34. data/lib/rhc/commands/git_clone.rb +29 -0
  35. data/lib/rhc/commands/logout.rb +51 -0
  36. data/lib/rhc/commands/member.rb +148 -0
  37. data/lib/rhc/commands/port_forward.rb +197 -0
  38. data/lib/rhc/commands/server.rb +40 -0
  39. data/lib/rhc/commands/setup.rb +60 -0
  40. data/lib/rhc/commands/snapshot.rb +137 -0
  41. data/lib/rhc/commands/ssh.rb +51 -0
  42. data/lib/rhc/commands/sshkey.rb +97 -0
  43. data/lib/rhc/commands/tail.rb +47 -0
  44. data/lib/rhc/commands/threaddump.rb +14 -0
  45. data/lib/rhc/commands.rb +396 -0
  46. data/lib/rhc/config.rb +320 -0
  47. data/lib/rhc/context_helper.rb +121 -0
  48. data/lib/rhc/core_ext.rb +202 -0
  49. data/lib/rhc/coverage_helper.rb +33 -0
  50. data/lib/rhc/deployment_helpers.rb +88 -0
  51. data/lib/rhc/exceptions.rb +232 -0
  52. data/lib/rhc/git_helpers.rb +91 -0
  53. data/lib/rhc/help_formatter.rb +55 -0
  54. data/lib/rhc/helpers.rb +477 -0
  55. data/lib/rhc/highline_extensions.rb +479 -0
  56. data/lib/rhc/json.rb +51 -0
  57. data/lib/rhc/output_helpers.rb +260 -0
  58. data/lib/rhc/rest/activation.rb +11 -0
  59. data/lib/rhc/rest/alias.rb +42 -0
  60. data/lib/rhc/rest/api.rb +87 -0
  61. data/lib/rhc/rest/application.rb +332 -0
  62. data/lib/rhc/rest/attributes.rb +36 -0
  63. data/lib/rhc/rest/authorization.rb +8 -0
  64. data/lib/rhc/rest/base.rb +79 -0
  65. data/lib/rhc/rest/cartridge.rb +154 -0
  66. data/lib/rhc/rest/client.rb +650 -0
  67. data/lib/rhc/rest/deployment.rb +18 -0
  68. data/lib/rhc/rest/domain.rb +98 -0
  69. data/lib/rhc/rest/environment_variable.rb +15 -0
  70. data/lib/rhc/rest/gear_group.rb +16 -0
  71. data/lib/rhc/rest/httpclient.rb +145 -0
  72. data/lib/rhc/rest/key.rb +44 -0
  73. data/lib/rhc/rest/membership.rb +105 -0
  74. data/lib/rhc/rest/mock.rb +1024 -0
  75. data/lib/rhc/rest/user.rb +32 -0
  76. data/lib/rhc/rest.rb +148 -0
  77. data/lib/rhc/ssh_helpers.rb +378 -0
  78. data/lib/rhc/tar_gz.rb +51 -0
  79. data/lib/rhc/usage_templates/command_help.erb +51 -0
  80. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  81. data/lib/rhc/usage_templates/help.erb +35 -0
  82. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  83. data/lib/rhc/usage_templates/options_help.erb +12 -0
  84. data/lib/rhc/vendor/okjson.rb +600 -0
  85. data/lib/rhc/vendor/parseconfig.rb +178 -0
  86. data/lib/rhc/vendor/sshkey.rb +253 -0
  87. data/lib/rhc/vendor/zliby.rb +628 -0
  88. data/lib/rhc/version.rb +5 -0
  89. data/lib/rhc/wizard.rb +633 -0
  90. data/lib/rhc.rb +34 -0
  91. data/spec/coverage_helper.rb +89 -0
  92. data/spec/direct_execution_helper.rb +338 -0
  93. data/spec/keys/example.pem +23 -0
  94. data/spec/keys/example_private.pem +27 -0
  95. data/spec/keys/server.pem +19 -0
  96. data/spec/rest_spec_helper.rb +31 -0
  97. data/spec/rhc/assets/cert.crt +22 -0
  98. data/spec/rhc/assets/cert_key_rsa +27 -0
  99. data/spec/rhc/assets/empty.txt +0 -0
  100. data/spec/rhc/assets/env_vars.txt +7 -0
  101. data/spec/rhc/assets/env_vars_2.txt +1 -0
  102. data/spec/rhc/assets/foo.txt +1 -0
  103. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  104. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  105. data/spec/rhc/auth_spec.rb +442 -0
  106. data/spec/rhc/cli_spec.rb +188 -0
  107. data/spec/rhc/command_spec.rb +435 -0
  108. data/spec/rhc/commands/account_spec.rb +42 -0
  109. data/spec/rhc/commands/alias_spec.rb +333 -0
  110. data/spec/rhc/commands/app_spec.rb +754 -0
  111. data/spec/rhc/commands/apps_spec.rb +39 -0
  112. data/spec/rhc/commands/authorization_spec.rb +145 -0
  113. data/spec/rhc/commands/cartridge_spec.rb +641 -0
  114. data/spec/rhc/commands/deployment_spec.rb +286 -0
  115. data/spec/rhc/commands/domain_spec.rb +383 -0
  116. data/spec/rhc/commands/env_spec.rb +493 -0
  117. data/spec/rhc/commands/git_clone_spec.rb +80 -0
  118. data/spec/rhc/commands/logout_spec.rb +86 -0
  119. data/spec/rhc/commands/member_spec.rb +228 -0
  120. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  121. data/spec/rhc/commands/server_spec.rb +69 -0
  122. data/spec/rhc/commands/setup_spec.rb +118 -0
  123. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  124. data/spec/rhc/commands/ssh_spec.rb +163 -0
  125. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  126. data/spec/rhc/commands/tail_spec.rb +81 -0
  127. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  128. data/spec/rhc/config_spec.rb +407 -0
  129. data/spec/rhc/helpers_spec.rb +524 -0
  130. data/spec/rhc/highline_extensions_spec.rb +314 -0
  131. data/spec/rhc/json_spec.rb +30 -0
  132. data/spec/rhc/rest_application_spec.rb +248 -0
  133. data/spec/rhc/rest_client_spec.rb +752 -0
  134. data/spec/rhc/rest_spec.rb +740 -0
  135. data/spec/rhc/targz_spec.rb +55 -0
  136. data/spec/rhc/wizard_spec.rb +756 -0
  137. data/spec/spec_helper.rb +575 -0
  138. data/spec/wizard_spec_helper.rb +330 -0
  139. metadata +435 -0
@@ -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 == "pbox.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
@@ -0,0 +1,188 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/sshkey'
4
+ require 'rhc/config'
5
+
6
+
7
+ describe RHC::Commands::Sshkey do
8
+ let!(:rest_client){ MockRestClient.new }
9
+ before{ user_config }
10
+
11
+ describe 'list' do
12
+
13
+ context "when run with list command" do
14
+ let(:arguments) { %w[sshkey list --noprompt --config test.conf -l test@test.foo -p password --trace] }
15
+
16
+ it { expect { run }.to exit_with_code(0) }
17
+
18
+ it { run_output.should match(/mockkey1 \(type: ssh-rsa\)/) }
19
+ it { run_output.should match(/Fingerprint:.*0f:ce:86:80:df:a0:81:ca:db:f1:a7:0c:70:85:ce:00/) }
20
+
21
+ it { run_output.should match(/mockkey3 \(type: krb5-principal\)/) }
22
+ it { run_output.should match(/Principal:.* mockuser@mockdomain/) }
23
+ it { run_output.should_not match(/Fingerprint:.*Invalid key/) }
24
+ end
25
+ end
26
+
27
+ describe 'show' do
28
+ context "when run with show command" do
29
+ let(:arguments) { %w[sshkey show mockkey1 --noprompt --config test.conf -l test@test.foo -p password --trace] }
30
+
31
+ it { expect { run }.to exit_with_code(0) }
32
+ it { run_output.should match(/mockkey1 \(type: ssh-rsa\)/) }
33
+ end
34
+ end
35
+
36
+ describe "add" do
37
+ context "when adding a valid key" do
38
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar id_rsa.pub] }
39
+
40
+ it 'adds the key' do
41
+ FakeFS do
42
+ keys = rest_client.sshkeys
43
+ num_keys = keys.length
44
+ File.open('id_rsa.pub', 'w') do |f|
45
+ f << 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnCOqK7/mmvZ9AtCAerxjAasJ1rSpfuWT4vNm1+O/Fh0Di3chTWjY9a0M2hEnqkqnVG589L9CqCUeT0kdc3Vgw3JEcacSUr1z7tLr9kO+p/D5lSdQYzDGGRFOZ0H6lc/y8iNxWV1VO/sJvKx6cr5zvKIn8Q6GvhVNOxlai0IOb9FJxLGK95GLpZ+elzh8Tc9giy7KfwheAwhV2JoF9uRltE5JP/CNs7w/E29i1Z+jlueuu8RVotLmhSVNJm91Ey7OCtoI1iBE0Wv/SucFe32Qi08RWTM/MaGGz93KQNOVRGjNkosJjPmP1qU6WGBfliDkJAZXB0b6sEcnx1fbVikwZ'
46
+ end
47
+ expect { run }.to exit_with_code(0)
48
+ rest_client.sshkeys.length.should == num_keys + 1
49
+ end
50
+ end
51
+ end
52
+
53
+ context "when adding a valid key via command line arguments" do
54
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar --type ssh-rsa --content AAAAB3NzaC1yc2EAAAADAQABAAABAQCnCOqK7/mmvZ9AtCAerxjAasJ1rSpfuWT4vNm1+O/Fh0Di3chTWjY9a0M2hEnqkqnVG589L9CqCUeT0kdc3Vgw3JEcacSUr1z7tLr9kO+p/D5lSdQYzDGGRFOZ0H6lc/y8iNxWV1VO/sJvKx6cr5zvKIn8Q6GvhVNOxlai0IOb9FJxLGK95GLpZ+elzh8Tc9giy7KfwheAwhV2JoF9uRltE5JP/CNs7w/E29i1Z+jlueuu8RVotLmhSVNJm91Ey7OCtoI1iBE0Wv/SucFe32Qi08RWTM/MaGGz93KQNOVRGjNkosJjPmP1qU6WGBfliDkJAZXB0b6sEcnx1fbVikwZ] }
55
+
56
+ it 'adds the key' do
57
+ keys = rest_client.sshkeys
58
+ num_keys = keys.length
59
+ expect { run }.to exit_with_code(0)
60
+ rest_client.sshkeys.length.should == num_keys + 1
61
+ end
62
+ end
63
+
64
+ context "when adding an invalid key" do
65
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar id_rsa.pub] }
66
+
67
+ it "fails to add the key" do
68
+ FakeFS do
69
+ keys = rest_client.sshkeys
70
+ num_keys = keys.length
71
+ File.open('id_rsa.pub', 'w') do |f|
72
+ f << 'ssh-rsa AADAQABAAABAQCnCOqK7/mmvZ9AtCAerxjAasJ1rSpfuWT4vNm1+O/Fh0Di3chTWjY9a0M2hEnqkqnVG589L9CqCUeT0kdc3Vgw3JEcacSUr1z7tLr9kO+p/D5lSdQYzDGGRFOZ0H6lc/y8iNxWV1VO/sJvKx6cr5zvKIn8Q6GvhVNOxlai0IOb9FJxLGK95GLpZ+elzh8Tc9giy7KfwheAwhV2JoF9uRltE5JP/CNs7w/E29i1Z+jlueuu8RVotLmhSVNJm91Ey7OCtoI1iBE0Wv/SucFe32Qi08RWTM/MaGGz93KQNOVRGjNkosJjPmP1qU6WGBfliDkJAZXB0b6sEcnx1fbVikwZ'
73
+ end
74
+ expect { run }.to exit_with_code(128)
75
+ expect { run_output.should match(/Name:.* mockkey/) }
76
+ rest_client.sshkeys.length.should == num_keys
77
+ end
78
+ end
79
+
80
+ it "does not throw an error on an empty file" do
81
+ FakeFS do
82
+ keys = rest_client.sshkeys
83
+ num_keys = keys.length
84
+ File.open('id_rsa.pub', 'w') do |f|
85
+ f << ''
86
+ end
87
+ expect { run }.to exit_with_code(128)
88
+ expect { run_output.should match(/Name:.* mockkey/) }
89
+ rest_client.sshkeys.length.should == num_keys
90
+ end
91
+ end
92
+
93
+ it "exits with status code Errno::EACCES::Errno" do
94
+ IO.should_receive(:read).and_return("ssh_foo bar")
95
+ expect { run }.to exit_with_code(128)
96
+ end
97
+ end
98
+
99
+ context "when adding an invalid key via command line arguments" do
100
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar --type ssh-rsa --content abcdef] }
101
+
102
+ it "fails to add the key" do
103
+ keys = rest_client.sshkeys
104
+ num_keys = keys.length
105
+ expect { run }.to exit_with_code(128)
106
+ expect { run_output.should match(/Name:.* mockkey/) }
107
+ rest_client.sshkeys.length.should == num_keys
108
+ end
109
+ end
110
+
111
+ context "when adding an invalid key with --confirm" do
112
+ let(:arguments) { %w[sshkey add --noprompt --confirm --config test.conf -l test@test.foo -p password foobar id_rsa.pub] }
113
+
114
+ it "warns and then adds the key" do
115
+ FakeFS do
116
+ keys = rest_client.sshkeys
117
+ num_keys = keys.length
118
+ File.open('id_rsa.pub', 'w') do |f|
119
+ f << 'ssh-rsa AADAQABAAABAQCnCOqK7/mmvZ9AtCAerxjAasJ1rSpfuWT4vNm1+O/Fh0Di3chTWjY9a0M2hEnqkqnVG589L9CqCUeT0kdc3Vgw3JEcacSUr1z7tLr9kO+p/D5lSdQYzDGGRFOZ0H6lc/y8iNxWV1VO/sJvKx6cr5zvKIn8Q6GvhVNOxlai0IOb9FJxLGK95GLpZ+elzh8Tc9giy7KfwheAwhV2JoF9uRltE5JP/CNs7w/E29i1Z+jlueuu8RVotLmhSVNJm91Ey7OCtoI1iBE0Wv/SucFe32Qi08RWTM/MaGGz93KQNOVRGjNkosJjPmP1qU6WGBfliDkJAZXB0b6sEcnx1fbVikwZ'
120
+ end
121
+ expect { run }.to exit_with_code(0)
122
+ expect { run_output.should match("key you are uploading is not recognized") }
123
+ rest_client.sshkeys.length.should == num_keys + 1
124
+ end
125
+ end
126
+ end
127
+
128
+ context "when adding a nonexistent key" do
129
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar id_rsa.pub] }
130
+
131
+ it "exits with status code Errno::ENOENT::Errno" do
132
+ expect { run }.to exit_with_code(128)
133
+ end
134
+ end
135
+
136
+ context "when attempting to add an existing but inaccessible key" do
137
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar inaccessible_key.pub] }
138
+
139
+ #before :all do
140
+ # @inaccessible_key = 'inaccessible_key.pub'
141
+ # File.new(@inaccessible_key, 'w+')
142
+ # File.chmod(0000, @inaccessible_key)
143
+ #end
144
+
145
+ #after :all do
146
+ # File.delete @inaccessible_key
147
+ #end
148
+
149
+ it "exits with status code Errno::EACCES::Errno" do
150
+ IO.should_receive(:read).and_raise(Errno::EACCES)
151
+ expect { run }.to exit_with_code(128)
152
+ end
153
+
154
+ end
155
+
156
+ context "when adding a key without correct arguments" do
157
+ let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar] }
158
+
159
+ it "exits with argument error" do
160
+ expect { run }.to exit_with_code(1)
161
+ end
162
+ end
163
+ end
164
+
165
+ describe "remove" do
166
+ context "when removing an existing key" do
167
+ let (:arguments) { %w[sshkey remove --noprompt --config test.conf -l test@test.foo -p password mockkey2] }
168
+
169
+ it 'deletes the key' do
170
+ keys = rest_client.sshkeys
171
+ num_keys = keys.length
172
+ expect{ run }.to exit_with_code(0)
173
+ rest_client.sshkeys.length.should == num_keys - 1
174
+ end
175
+ end
176
+
177
+ context "when removing a nonexistent key" do
178
+ let (:arguments) { %w[sshkey remove --noprompt --config test.conf -l test@test.foo -p password no_match] }
179
+ before{ @keys = rest_client.sshkeys }
180
+
181
+ it 'leaves keys untouched' do
182
+ num_keys = @keys.length
183
+ expect{ run }.to exit_with_code(0)
184
+ rest_client.sshkeys.length.should == num_keys
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/tail'
4
+ require 'rhc/config'
5
+
6
+ describe RHC::Commands::Tail do
7
+ let!(:rest_client) { MockRestClient.new }
8
+ before(:each) do
9
+ user_config
10
+ domain = rest_client.add_domain("mock-domain-0")
11
+ @app = domain.add_application("mock-app-0", "ruby-1.8.7")
12
+ @app.stub(:ssh_url).and_return("ssh://user@test.domain.com")
13
+ end
14
+
15
+ describe 'help' do
16
+ let(:arguments) { ['tail', '--help'] }
17
+
18
+ context 'help is run' do
19
+ it "should display help" do
20
+ expect { run }.to exit_with_code(0)
21
+ end
22
+ it('should output usage') { run_output.should match("Usage: pbox tail") }
23
+ end
24
+ end
25
+
26
+ describe 'tail' do
27
+ let(:arguments) { ['tail', 'mock-app-0'] }
28
+
29
+ context 'when ssh connects' do
30
+ before (:each) {Net::SSH.should_receive(:start).with('test.domain.com', 'user', :compression => false) }
31
+ it { expect { run }.to exit_with_code(0) }
32
+ end
33
+
34
+ context 'is run on an unreachable domain' do
35
+ before (:each) {Net::SSH.should_receive(:start).and_raise(SocketError) }
36
+ it { expect { run }.to exit_with_code(1) }
37
+ it { run_output.should =~ /The connection to test.domain.com failed: / }
38
+ end
39
+
40
+ context 'is refused' do
41
+ before (:each) {Net::SSH.should_receive(:start).and_raise(Errno::ECONNREFUSED) }
42
+ it { expect { run }.to exit_with_code(1) }
43
+ it { run_output.should =~ /The server test.domain.com refused a connection with user user/ }
44
+ end
45
+
46
+ context 'succeeds and exits on Interrupt' do
47
+ before (:each) { rest_client.stub(:find_domain) { raise Interrupt } }
48
+ it { expect { run }.to raise_error(Interrupt) }
49
+ end
50
+
51
+ context 'succeeds when a gear is specified' do
52
+ before (:each) {Net::SSH.should_receive(:start).with('fakesshurl.com', 'fakegearid0', :compression => false) }
53
+ let(:arguments) { ['tail', 'mock-app-0', '--gear', 'fakegearid0' ] }
54
+
55
+ it { run_output.should_not =~ /Connecting to fakesshurl.com/ }
56
+ it { expect { run }.to exit_with_code(0) }
57
+ end
58
+
59
+ context 'fails when an invalid gear is specified' do
60
+ let(:arguments) { ['tail', 'mock-app-0', '--gear', 'gearthatdoesnotexist' ] }
61
+
62
+ it { expect { run }.to exit_with_code(1) }
63
+ it { run_output.should =~ /Gear gearthatdoesnotexist not found/ }
64
+ end
65
+
66
+ context 'fails when a gear with no ssh info is specified' do
67
+ let(:arguments) { ['tail', 'mock-app-0', '--gear', 'fakegearid' ] }
68
+
69
+ # Given - gears in gear group should not have ssh info
70
+ before(:each) do
71
+ gg = MockRestGearGroup.new(rest_client)
72
+ @app.stub(:gear_groups).and_return([gg])
73
+ gg.stub(:gears).and_return([{'state' => 'started', 'id' => 'fakegearid'}])
74
+ end
75
+
76
+ it { expect { run }.to exit_with_code(1) }
77
+ it { run_output.should =~ /The server does not support operations on individual gears./ }
78
+ end
79
+
80
+ end
81
+ end