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,286 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/deployment'
4
+
5
+ describe RHC::Commands::Deployment do
6
+
7
+ DEPLOYMENT_APP_NAME = 'mock_app_deploy'
8
+
9
+ let!(:rest_client) { MockRestClient.new }
10
+
11
+ before do
12
+ user_config
13
+ @rest_app = rest_client.add_domain("mock_domain").add_application(DEPLOYMENT_APP_NAME, 'ruby-1.8.7')
14
+ @rest_app.stub(:ssh_url).and_return("ssh://user@test.domain.com")
15
+ @targz_filename = File.dirname(__FILE__) + '/' + DEPLOYMENT_APP_NAME + '.tar.gz'
16
+ FileUtils.cp(File.expand_path('../../assets/targz_sample.tar.gz', __FILE__), @targz_filename)
17
+ File.chmod 0644, @targz_filename unless File.executable? @targz_filename
18
+ end
19
+
20
+ after do
21
+ File.delete @targz_filename if File.exist? @targz_filename
22
+ end
23
+
24
+ describe "configure app" do
25
+ context "manual deployment keeping a history of 10" do
26
+ let(:arguments) {['app', 'configure', '--app', DEPLOYMENT_APP_NAME, '--no-auto-deploy', '--keep-deployments', '10']}
27
+ it "should succeed" do
28
+ expect{ run }.to exit_with_code(0)
29
+ run_output.should match(/Configuring application '#{DEPLOYMENT_APP_NAME}' .../)
30
+ run_output.should match(/done/)
31
+ @rest_app.auto_deploy.should == false
32
+ @rest_app.keep_deployments.should == 10
33
+ run_output.should match(/Your application '#{DEPLOYMENT_APP_NAME}' is now configured as listed above/)
34
+ end
35
+ end
36
+
37
+ context "with no configuration options" do
38
+ let(:arguments) {['app', 'configure', '--app', DEPLOYMENT_APP_NAME]}
39
+ it "should display the current configuration" do
40
+ expect{ run }.to exit_with_code(0)
41
+ run_output.should_not match(/Configuring application '#{DEPLOYMENT_APP_NAME}' .../)
42
+ run_output.should_not match(/done/)
43
+ run_output.should match(/Your application '#{DEPLOYMENT_APP_NAME}' is configured as listed above/)
44
+ end
45
+ end
46
+ end
47
+
48
+ describe "deploy" do
49
+ context "git ref successfully" do
50
+ before { Net::SSH.should_receive(:start).exactly(3).times.with('test.domain.com', 'user', :compression=>false) }
51
+ let(:arguments) {['app', 'deploy', 'master', '--app', DEPLOYMENT_APP_NAME]}
52
+ it "should succeed" do
53
+ expect{ run }.to exit_with_code(0)
54
+ run_output.should match(/Deployment of git ref 'master' in progress for application #{DEPLOYMENT_APP_NAME} .../)
55
+ run_output.should match(/Success/)
56
+ end
57
+ end
58
+
59
+ context "binary file successfully" do
60
+ before do
61
+ ssh = double(Net::SSH)
62
+ session = double(Net::SSH::Connection::Session)
63
+ channel = double(Net::SSH::Connection::Channel)
64
+ exit_status = double(Net::SSH::Buffer)
65
+ exit_status.stub(:read_long).and_return(0)
66
+ Net::SSH.should_receive(:start).exactly(3).times.with('test.domain.com', 'user', :compression=>false).and_yield(session)
67
+ session.should_receive(:open_channel).exactly(3).times.and_yield(channel)
68
+ channel.should_receive(:exec).exactly(3).times.with("oo-binary-deploy").and_yield(nil, nil)
69
+ channel.should_receive(:on_data).exactly(3).times.and_yield(nil, 'foo')
70
+ channel.should_receive(:on_extended_data).exactly(3).times.and_yield(nil, nil, '')
71
+ channel.should_receive(:on_close).exactly(3).times.and_yield(nil)
72
+ channel.should_receive(:on_request).exactly(3).times.with("exit-status").and_yield(nil, exit_status)
73
+ lines = ''
74
+ File.open(@targz_filename, 'rb') do |file|
75
+ file.chunk(1024) do |chunk|
76
+ lines << chunk
77
+ end
78
+ end
79
+ channel.should_receive(:send_data).exactly(3).times.with(lines)
80
+ channel.should_receive(:eof!).exactly(3).times
81
+ session.should_receive(:loop).exactly(3).times
82
+ end
83
+ let(:arguments) {['app', 'deploy', @targz_filename, '--app', DEPLOYMENT_APP_NAME]}
84
+ it "should succeed" do
85
+ expect{ run }.to exit_with_code(0)
86
+ run_output.should match(/Deployment of file '#{@targz_filename}' in progress for application #{DEPLOYMENT_APP_NAME} .../)
87
+ run_output.should match(/Success/)
88
+ end
89
+ end
90
+
91
+ [URI('http://foo.com/path/to/file/' + DEPLOYMENT_APP_NAME + '.tar.gz'),
92
+ URI('https://foo.com/path/to/file/' + DEPLOYMENT_APP_NAME + '.tar.gz')].each do |uri|
93
+ context "url file successfully" do
94
+ before do
95
+ ssh = double(Net::SSH)
96
+ session = double(Net::SSH::Connection::Session)
97
+ channel = double(Net::SSH::Connection::Channel)
98
+ exit_status = double(Net::SSH::Buffer)
99
+ exit_status.stub(:read_long).and_return(0)
100
+ Net::SSH.should_receive(:start).exactly(3).times.with('test.domain.com', 'user', :compression=>false).and_yield(session)
101
+ session.should_receive(:open_channel).exactly(3).times.and_yield(channel)
102
+ channel.should_receive(:exec).exactly(3).times.with("oo-binary-deploy").and_yield(nil, nil)
103
+ channel.should_receive(:on_data).exactly(3).times.and_yield(nil, 'foo')
104
+ channel.should_receive(:on_extended_data).exactly(3).times.and_yield(nil, nil, '')
105
+ channel.should_receive(:on_close).exactly(3).times.and_yield(nil)
106
+ channel.should_receive(:on_request).exactly(3).times.with("exit-status").and_yield(nil, exit_status)
107
+ lines = ''
108
+ File.open(@targz_filename, 'rb') do |file|
109
+ file.chunk(1024) do |chunk|
110
+ lines << chunk
111
+ end
112
+ end
113
+ stub_request(:get, uri.to_s).to_return(:status => 200, :body => lines, :headers => {})
114
+ channel.should_receive(:send_data).exactly(3).times.with(lines)
115
+ channel.should_receive(:eof!).exactly(3).times
116
+ session.should_receive(:loop).exactly(3).times
117
+ end
118
+ let(:arguments) {['app', 'deploy', uri.to_s, '--app', DEPLOYMENT_APP_NAME]}
119
+ it "should succeed" do
120
+ expect{ run }.to exit_with_code(0)
121
+ run_output.should match(/Deployment of file '#{uri.to_s}' in progress for application #{DEPLOYMENT_APP_NAME} .../)
122
+ run_output.should match(/Success/)
123
+ end
124
+ end
125
+ end
126
+
127
+ context "binary file with corrupted file" do
128
+ before do
129
+ ssh = double(Net::SSH)
130
+ session = double(Net::SSH::Connection::Session)
131
+ channel = double(Net::SSH::Connection::Channel)
132
+ exit_status = double(Net::SSH::Buffer)
133
+ exit_status.stub(:read_long).and_return(255)
134
+ Net::SSH.should_receive(:start).exactly(3).times.with('test.domain.com', 'user', :compression=>false).and_yield(session)
135
+ session.should_receive(:open_channel).exactly(3).times.and_yield(channel)
136
+ channel.should_receive(:exec).exactly(3).times.with("oo-binary-deploy").and_yield(nil, nil)
137
+ channel.should_receive(:on_data).exactly(3).times.and_yield(nil, 'foo')
138
+ channel.should_receive(:on_extended_data).exactly(3).times.and_yield(nil, nil, 'Invalid file')
139
+ channel.should_receive(:on_close).exactly(3).times.and_yield(nil)
140
+ channel.should_receive(:on_request).exactly(3).times.with("exit-status").and_yield(nil, exit_status)
141
+ lines = ''
142
+ File.open(@targz_filename, 'rb') do |file|
143
+ file.chunk(1024) do |chunk|
144
+ lines << chunk
145
+ end
146
+ end
147
+ channel.should_receive(:send_data).exactly(3).times.with(lines)
148
+ channel.should_receive(:eof!).exactly(3).times
149
+ session.should_receive(:loop).exactly(3).times
150
+ end
151
+ let(:arguments) {['app', 'deploy', @targz_filename, '--app', DEPLOYMENT_APP_NAME]}
152
+ it "should not succeed" do
153
+ expect{ run }.to exit_with_code(133)
154
+ run_output.should match(/Deployment of file '#{@targz_filename}' in progress for application #{DEPLOYMENT_APP_NAME} .../)
155
+ run_output.should match(/Invalid file/)
156
+ end
157
+ end
158
+
159
+ context "fails when deploying git ref" do
160
+ before (:each) { Net::SSH.should_receive(:start).and_raise(Errno::ECONNREFUSED) }
161
+ let(:arguments) {['app', 'deploy', 'master', '--app', DEPLOYMENT_APP_NAME]}
162
+ it "should exit with error" do
163
+ expect{ run }.to exit_with_code(1)
164
+ end
165
+ end
166
+
167
+ context "fails when deploying binary file" do
168
+ before (:each) { Net::SSH.should_receive(:start).and_raise(Errno::ECONNREFUSED) }
169
+ let(:arguments) {['app', 'deploy', @targz_filename, '--app', DEPLOYMENT_APP_NAME]}
170
+ it "should exit with error" do
171
+ expect{ run }.to exit_with_code(1)
172
+ end
173
+ end
174
+
175
+ context "fails when deploying binary file" do
176
+ before (:each) { Net::SSH.should_receive(:start).and_raise(SocketError) }
177
+ let(:arguments) {['app', 'deploy', @targz_filename, '--app', DEPLOYMENT_APP_NAME]}
178
+ it "should exit with error" do
179
+ expect{ run }.to exit_with_code(1)
180
+ end
181
+ end
182
+
183
+ context "fails when deploying url file" do
184
+ before (:each) { Net::SSH.should_receive(:start).and_raise(Errno::ECONNREFUSED) }
185
+ let(:arguments) {['app', 'deploy', 'http://foo.com/deploy.tar.gz', '--app', DEPLOYMENT_APP_NAME]}
186
+ it "should exit with error" do
187
+ expect{ run }.to exit_with_code(1)
188
+ end
189
+ end
190
+
191
+ context "fails when deploying url file" do
192
+ before (:each) { Net::SSH.should_receive(:start).and_raise(SocketError) }
193
+ let(:arguments) {['app', 'deploy', 'http://foo.com/deploy.tar.gz', '--app', DEPLOYMENT_APP_NAME]}
194
+ it "should exit with error" do
195
+ expect{ run }.to exit_with_code(1)
196
+ end
197
+ end
198
+
199
+ context 'when run against an unsupported server' do
200
+ before {
201
+ @rest_app.links.delete 'UPDATE'
202
+ @rest_app.links.delete 'DEPLOY'
203
+ }
204
+ let(:arguments) {['app', 'deploy', 'master', '--app', DEPLOYMENT_APP_NAME]}
205
+ it "should raise not supported exception" do
206
+ expect{ run }.to exit_with_code(132)
207
+ run_output.should match(/The server does not support deployments/)
208
+ end
209
+ end
210
+
211
+ context "ssh authentication failure" do
212
+ before (:each) { Net::SSH.should_receive(:start).exactly(2).times.and_raise(Net::SSH::AuthenticationFailed) }
213
+ let(:arguments) {['app', 'deploy', 'master', '--app', DEPLOYMENT_APP_NAME]}
214
+ it "should exit with error" do
215
+ expect{ run }.to exit_with_code(1)
216
+ run_output.should match(/Authentication to server test.domain.com with user user failed/)
217
+ end
218
+ end
219
+
220
+ end
221
+
222
+ describe "activate deployment" do
223
+ context "activates 123456" do
224
+ before { Net::SSH.should_receive(:start).exactly(3).times.with('test.domain.com', 'user', :compression => false) }
225
+ let(:arguments) {['deployment', 'activate', '123456', '--app', DEPLOYMENT_APP_NAME]}
226
+ it "should succeed" do
227
+ expect{ run }.to exit_with_code(0)
228
+ run_output.should match(/Activating deployment '123456' on application #{DEPLOYMENT_APP_NAME} .../)
229
+ run_output.should match(/Success/)
230
+ end
231
+ end
232
+
233
+ context "fails with ssh error" do
234
+ before (:each) { Net::SSH.should_receive(:start).and_raise(Errno::ECONNREFUSED) }
235
+ let(:arguments) {['deployment', 'activate', '123456', '--app', DEPLOYMENT_APP_NAME]}
236
+ it "should exit with error" do
237
+ expect{ run }.to exit_with_code(1)
238
+ end
239
+ end
240
+ end
241
+
242
+ describe "list deployments" do
243
+ context "simple" do
244
+ let(:arguments) {['deployment', 'list', DEPLOYMENT_APP_NAME]}
245
+ it "should succeed" do
246
+ expect{ run }.to exit_with_code(0)
247
+ run_output.should match(/Jan 01\, 2000 1\:00 AM\, deployment 0000001/)
248
+ run_output.should match(/Jan 01\, 2000 2\:00 AM\, deployment 0000002/)
249
+ run_output.should match(/Jan 01\, 2000 3\:00 AM\, deployment 0000003 \(rolled back\)/)
250
+ run_output.should match(/Jan 01\, 2000 4\:00 AM\, deployment 0000004 \(rolled back\)/)
251
+ run_output.should match(/Jan 01\, 2000 5\:00 AM\, deployment 0000003 \(rollback to Jan 01\, 2000 3\:00 AM\, rolled back\)/)
252
+ run_output.should match(/Jan 01\, 2000 5\:00 AM\, deployment 0000005 \(rolled back\)/)
253
+ run_output.should match(/Jan 01\, 2000 6\:00 AM\, deployment 0000002 \(rollback to Jan 01\, 2000 2\:00 AM\)/)
254
+ end
255
+ end
256
+ end
257
+
258
+ describe "show deployment" do
259
+ context "simple" do
260
+ let(:arguments) {['deployment', 'show', '0000001', '--app', DEPLOYMENT_APP_NAME]}
261
+ it "should succeed" do
262
+ expect{ run }.to exit_with_code(0)
263
+ run_output.should match(/Deployment ID 0000001/)
264
+ end
265
+ end
266
+
267
+ context "fails when deployment is not found" do
268
+ let(:arguments) {['deployment', 'show', 'zee', '--app', DEPLOYMENT_APP_NAME]}
269
+ it "should succeed" do
270
+ expect{ run }.to exit_with_code(131)
271
+ run_output.should match(/Deployment ID 'zee' not found for application #{DEPLOYMENT_APP_NAME}/)
272
+ end
273
+ end
274
+ end
275
+
276
+ describe "show configuration" do
277
+ context "simple" do
278
+ let(:arguments) {['app', 'show', '--app', DEPLOYMENT_APP_NAME, '--configuration']}
279
+ it "should succeed" do
280
+ expect{ run }.to exit_with_code(0)
281
+ #run_output.should match(/Deployment ID 1/)
282
+ end
283
+ end
284
+ end
285
+
286
+ end
@@ -0,0 +1,383 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/domain'
4
+
5
+ describe RHC::Commands::Domain do
6
+ let(:rest_client){ MockRestClient.new }
7
+ before{ user_config }
8
+
9
+ describe 'default action' do
10
+ before{ rest_client }
11
+ context 'when run with no domains' do
12
+ let(:arguments) { ['domain'] }
13
+
14
+ it { expect { run }.to exit_with_code(1) }
15
+ it { run_output.should match(/To create your first domain.*pbox create-domain/m) }
16
+ end
17
+ context 'when help is shown' do
18
+ let(:arguments) { ['domain', '--noprompt', '--help'] }
19
+
20
+ it { expect { run }.to exit_with_code(0) }
21
+ it { run_output.should match(/configure.*delete.*leave.*list.*rename/m) }
22
+ end
23
+ end
24
+
25
+ describe 'show' do
26
+ before{ rest_client }
27
+ let(:arguments) { ['domain', 'show'] }
28
+
29
+ context 'when run with no domains' do
30
+ it { expect { run }.to exit_with_code(1) }
31
+ it { run_output.should match(/In order to deploy applications, you must create a domain/m) }
32
+ end
33
+
34
+ context 'when run with one domain no apps' do
35
+ before{ rest_client.add_domain("onedomain") }
36
+
37
+ it { expect { run }.to exit_with_code(0) }
38
+ it "should match output" do
39
+ output = run_output
40
+ output.should match("The domain onedomain exists but has no applications. You can use")
41
+ end
42
+ end
43
+
44
+ context 'when run with multiple domain no apps' do
45
+ before do
46
+ rest_client.add_domain("firstdomain")
47
+ rest_client.add_domain("seconddomain")
48
+ end
49
+ it { expect { run }.to exit_with_code(0) }
50
+ it "should match output" do
51
+ output = run_output
52
+ output.should match("The domain firstdomain exists but has no applications. You can use")
53
+ output.should_not match("Applications in seconddomain")
54
+ end
55
+ end
56
+
57
+ context 'when run with one domain multiple apps' do
58
+ before do
59
+ d = rest_client.add_domain("appdomain")
60
+ a = d.add_application("app_no_carts", "testframework-1.0")
61
+ a = d.add_application("app_multi_carts", "testframework-1.0")
62
+ a.add_cartridge("testcart-1")
63
+ a.add_cartridge("testcart-2")
64
+ a.add_cartridge("testcart-3")
65
+ end
66
+ it { expect { run }.to exit_with_code(0) }
67
+ it "should match output" do
68
+ output = run_output
69
+ output.should match("app_no_carts")
70
+ output.should match("app_multi_carts")
71
+ output.should match("testframework-1.0")
72
+ output.should match("testcart-1")
73
+ output.should match("testcart-2")
74
+ output.should match("testcart-3")
75
+ end
76
+ end
77
+
78
+ context 'when run with an app without cartridges' do
79
+ before do
80
+ d = rest_client.add_domain("appdomain")
81
+ a = d.add_application("app_no_carts")
82
+ end
83
+ it { expect { run }.to exit_with_code(0) }
84
+ it "should match output" do
85
+ output = run_output
86
+ output.should match("app_no_carts")
87
+ output.should match(/127.0.0.1\s*$/m)
88
+ end
89
+ end
90
+ end
91
+
92
+
93
+ describe 'list' do
94
+ before{ rest_client }
95
+ let(:arguments) { ['domain', 'list'] }
96
+
97
+ context 'when run with no domains' do
98
+ it { expect { run }.to exit_with_code(1) }
99
+ it { run_output.should match(/In order to deploy applications.*pbox create-domain/) }
100
+ end
101
+
102
+ context 'when run with one domain no apps' do
103
+ before{ rest_client.add_domain("onedomain") }
104
+
105
+ it { expect { run }.to exit_with_code(0) }
106
+ it "should match output" do
107
+ output = run_output
108
+ output.should match("You have access to 1 domain\\.")
109
+ output.should match("onedomain")
110
+ end
111
+
112
+ context 'when has no creation date, members, or allowed_gear_sizes' do
113
+ before{ rest_client.domains.first.attributes.merge(:creation_date => nil, :allowed_gear_sizes => nil, :members => nil, :id => '123') }
114
+ it { expect { run }.to exit_with_code(0) }
115
+ it "should match output" do
116
+ output = run_output
117
+ output.should match("onedomain")
118
+ output.should_not match ("Allowed Gear Sizes:")
119
+ output.should_not match ("Created:")
120
+ output.should_not match ("Members:")
121
+ output.should_not match ("ID:.*")
122
+ end
123
+ end
124
+ context 'when an ID is present and differs from name' do
125
+ let(:arguments) { ['domain', 'list', '--ids'] }
126
+ before{ rest_client.domains.first.attributes['id'] = '123' }
127
+ it { expect { run }.to exit_with_code(0) }
128
+ it "should match output" do
129
+ output = run_output
130
+ output.should match("onedomain")
131
+ output.should match ("ID:.*123")
132
+ end
133
+ end
134
+ context 'when an ID is present and identical to name' do
135
+ let(:arguments) { ['domain', 'list', '--ids'] }
136
+ before{ rest_client.domains.first.attributes['id'] = 'onedomain' }
137
+ it { expect { run }.to exit_with_code(0) }
138
+ it "should not match output" do
139
+ run_output.should_not match ("ID:.*123")
140
+ end
141
+ end
142
+ context 'when an ID is present and name is not' do
143
+ let(:arguments) { ['domain', 'list', '--ids'] }
144
+ before{ rest_client.domains.first.attributes['id'] = 'onedomain' }
145
+ before{ rest_client.domains.first.instance_variable_set(:@name, nil) }
146
+ it { expect { run }.to exit_with_code(0) }
147
+ it "should match output" do
148
+ run_output.should match ("onedomain")
149
+ run_output.should_not match ("ID:.*")
150
+ end
151
+ end
152
+ end
153
+
154
+ context 'when run with one owned domain' do
155
+ let(:arguments) { ['domains', '--mine'] }
156
+ before{ d = rest_client.add_domain('mine', true); rest_client.stub(:owned_domains).and_return([d]) }
157
+
158
+ it { expect { run }.to exit_with_code(0) }
159
+ it "should match output" do
160
+ output = run_output
161
+ output.should match("You have access to 1 domain\\.")
162
+ output.should match("mine")
163
+ output.should match("Created")
164
+ output.should match("Allowed Gear Sizes: small")
165
+ end
166
+ end
167
+
168
+ context 'when run with multiple domains and extra domain info' do
169
+ before do
170
+ rest_client.add_domain("firstdomain")
171
+ rest_client.add_domain("seconddomain", true)
172
+ end
173
+ it { expect { run }.to exit_with_code(0) }
174
+ it "should match output" do
175
+ output = run_output
176
+ output.should match("You have access to 2 domains")
177
+ output.should match("seconddomain \\(owned by a_user_name\\)")
178
+ output.should match("Created")
179
+ output.should match("Allowed Gear Sizes: small")
180
+ end
181
+ end
182
+ end
183
+
184
+ describe 'create' do
185
+ before{ rest_client }
186
+ let(:arguments) { ['domain', 'create', 'testnamespace'] }
187
+
188
+ context 'when no issues with ' do
189
+
190
+ it "should create a domain" do
191
+ expect { run }.to exit_with_code(0)
192
+ rest_client.domains[0].name.should == 'testnamespace'
193
+ end
194
+ it { run_output.should match(/Creating.*'testnamespace'.*done/m) }
195
+ end
196
+ end
197
+
198
+ describe 'rename' do
199
+ before{ rest_client }
200
+ let(:arguments) { ['domain', 'rename', 'olddomain', 'alterednamespace'] }
201
+
202
+ context 'when no issues with ' do
203
+ before{ rest_client.add_domain("olddomain") }
204
+
205
+ it "should update a domain" do
206
+ expect { run }.to exit_with_code(0)
207
+ rest_client.domains[0].name.should == 'alterednamespace'
208
+ end
209
+ it { run_output.should match(/Renaming domain 'olddomain' to 'alterednamespace'.*done.*?Applications in this domain will use the new name in their URL./m) }
210
+ end
211
+
212
+ context 'when there is no domain' do
213
+ it "should not create a domain" do
214
+ expect { run }.to exit_with_code(127)
215
+ rest_client.domains.empty?.should be_true
216
+ end
217
+ it { run_output.should match("not found") }
218
+ end
219
+ end
220
+
221
+ describe 'update' do
222
+ before{ rest_client }
223
+ let(:arguments) { ['domain', 'update', 'olddomain', 'alterednamespace'] }
224
+
225
+ before{ rest_client.add_domain("olddomain") }
226
+ it "should update a domain" do
227
+ expect { run }.to exit_with_code(0)
228
+ rest_client.domains[0].name.should == 'alterednamespace'
229
+ end
230
+ it { run_output.should match(/This command is deprecated.*Renaming domain 'olddomain' to 'alterednamespace'.*done.*?Applications in this domain will use the new name in their URL./m) }
231
+ end
232
+
233
+ describe 'alter alias has been removed' do
234
+ let(:arguments) { ['domain', 'alter', 'olddomain', 'alterednamespace'] }
235
+ it{ expect { run }.to exit_with_code(1) }
236
+ end
237
+
238
+ describe 'configure' do
239
+ context "no settings" do
240
+ before{ rest_client.add_domain("domain1") }
241
+ let(:arguments) { ['domain', 'configure', '-n', 'domain1'] }
242
+ it("should succeed"){ expect { run }.to exit_with_code(0) }
243
+ it("should display the domain config"){ run_output.should match(/Domain domain1 configuration/m) }
244
+ it("should not display the domain config without gear sizes"){ run_output.should_not match(/Allowed Gear Sizes/) }
245
+
246
+ context "server supports allowed gear sizes" do
247
+ before{ rest_client.domains.first.should_receive(:allowed_gear_sizes).and_return([]) }
248
+ it("should display the domain config"){ run_output.should match(/Domain domain1 configuration.*Allowed Gear Sizes:\s+<none>/m) }
249
+ end
250
+ context "server supports allowed gear sizes" do
251
+ before{ rest_client.domains.first.should_receive(:allowed_gear_sizes).and_return(['small', 'medium']) }
252
+ it("should display the domain config"){ run_output.should match(/Domain domain1 configuration.*Allowed Gear Sizes:\s+small, medium/m) }
253
+ end
254
+ end
255
+
256
+ context "when server does not support allowed-gear-sizes" do
257
+ before do
258
+ rest_client.add_domain("domain1")
259
+ rest_client.api.should_receive(:has_param?).with(:add_domain, 'allowed_gear_sizes').and_return(false)
260
+ end
261
+ let(:arguments) { ['domain', 'configure', '--allowed-gear-sizes', 'small'] }
262
+ it("display a message"){ run_output.should match 'The server does not support --allowed-gear-sizes' }
263
+ end
264
+
265
+ context "against a server that supports gear sizes" do
266
+ let(:username){ 'test_user' }
267
+ let(:password){ 'password' }
268
+ let(:server){ 'test.domain.com' }
269
+ let(:supports_allowed_gear_sizes?){ true }
270
+ before{ subject.class.any_instance.stub(:namespace_context).and_return('domain1') }
271
+ before do
272
+ stub_api
273
+ challenge{ stub_one_domain('domain1', nil, mock_user_auth) }
274
+ end
275
+
276
+ context "with --allowed-gear-sizes singular" do
277
+ before do
278
+ stub_api_request(:put, "domains/domain1/update", nil).
279
+ with(:body => {:allowed_gear_sizes => ['valid']}).
280
+ to_return({:body => {:type => 'domain', :data => {:name => 'domain1', :allowed_gear_sizes => ['valid']}, :messages => [{:severity => 'info', :text => 'Updated allowed gear sizes'},]}.to_json, :status => 200})
281
+ end
282
+ let(:arguments) { ['domain', 'configure', '--trace', '--allowed-gear-sizes', 'valid'] }
283
+ it("should succeed"){ expect { run }.to exit_with_code(0) }
284
+ it("should display the domain config"){ run_output.should match(/Domain domain1 configuration.*Allowed Gear Sizes:\s+valid/m) }
285
+ end
286
+
287
+ context "with --allowed-gear-sizes multiple" do
288
+ before do
289
+ stub_api_request(:put, "domains/domain1/update", nil).
290
+ with(:body => {:allowed_gear_sizes => ['one', 'two']}).
291
+ to_return({:body => {:type => 'domain', :data => {:name => 'domain1', :allowed_gear_sizes => ['one', 'two']}, :messages => [{:severity => 'info', :text => 'Updated allowed gear sizes'},]}.to_json, :status => 200})
292
+ end
293
+ let(:arguments) { ['domain', 'configure', '--trace', '--allowed-gear-sizes', 'one,two'] }
294
+ it("should succeed"){ expect { run }.to exit_with_code(0) }
295
+ it("should display the domain config"){ run_output.should match(/Domain domain1 configuration.*Allowed Gear Sizes:\s+one, two/m) }
296
+ end
297
+
298
+ context "with --allowed-gear-sizes" do
299
+ let(:arguments) { ['domain', 'configure', 'domain1', '--trace', '--allowed-gear-sizes'] }
300
+ it("raise an invalid option"){ expect{ run }.to raise_error(OptionParser::InvalidOption, /Provide a comma delimited list of valid gear/) }
301
+ end
302
+
303
+ context "with --allowed-gear-sizes=false" do
304
+ before do
305
+ stub_api_request(:put, "domains/domain1/update", nil).
306
+ with(:body => {:allowed_gear_sizes => ['false']}).
307
+ to_return({:body => {:type => 'domain', :messages => [{:field => 'allowed_gear_sizes', :exit_code => 10, :severity => 'error', :text => 'The specified gear size is invalid: false'},]}.to_json, :status => 422})
308
+ end
309
+ let(:arguments) { ['domain', 'configure', '--allowed-gear-sizes=false'] }
310
+ it("should succeed"){ expect { run }.to exit_with_code(1) }
311
+ it("should display the domain config"){ run_output.should match(/Updating domain configuration.*The specified gear size is invalid/m) }
312
+ end
313
+
314
+ context "with --no-allowed-gear-sizes" do
315
+ before do
316
+ stub_api_request(:put, "domains/domain1/update", nil).
317
+ with(:body => {:allowed_gear_sizes => []}).
318
+ to_return({:body => {:type => 'domain', :data => {:name => 'domain1', :allowed_gear_sizes => []}, :messages => [{:severity => 'info', :text => 'Updated allowed gear sizes'},]}.to_json, :status => 200})
319
+ end
320
+ let(:arguments) { ['domain', 'configure', '--no-allowed-gear-sizes'] }
321
+ it("should succeed"){ expect { run }.to exit_with_code(0) }
322
+ it("should display the domain config"){ run_output.should match(/Domain domain1 configuration.*Allowed Gear Sizes:\s+<none>/m) }
323
+ end
324
+ end
325
+ end
326
+
327
+ describe 'leave' do
328
+ before{ rest_client.add_domain("deleteme") }
329
+ let(:arguments) { ['domain', 'leave', '-n', 'deleteme'] }
330
+
331
+ it "should leave the domain" do
332
+ rest_client.domains.first.should_receive(:leave)
333
+ expect { run }.to exit_with_code(0)
334
+ end
335
+ end
336
+
337
+ describe 'delete' do
338
+ before{ rest_client }
339
+ let(:arguments) { ['domain', 'delete', 'deleteme'] }
340
+
341
+ context 'when no issues with ' do
342
+ before{ rest_client.add_domain("deleteme") }
343
+
344
+ it "should delete a domain" do
345
+ expect { run }.to exit_with_code(0)
346
+ rest_client.domains.empty?.should be_true
347
+ end
348
+ end
349
+
350
+ context 'when there is a different domain' do
351
+ before{ rest_client.add_domain("dontdelete") }
352
+
353
+ it "should error out" do
354
+ expect { run }.to exit_with_code(127)
355
+ rest_client.domains[0].name.should == 'dontdelete'
356
+ end
357
+ it { run_output.should match("Domain deleteme not found") }
358
+ end
359
+
360
+ context 'when there are applications on the domain' do
361
+ before do
362
+ domain = rest_client.add_domain("deleteme")
363
+ domain.add_application 'testapp1', 'mock-1.0'
364
+ end
365
+ it "should error out" do
366
+ expect { run }.to exit_with_code(1)
367
+ rest_client.domains[0].name.should == 'deleteme'
368
+ end
369
+ it { run_output.should match("Applications must be empty") }
370
+ end
371
+ end
372
+
373
+ describe 'help' do
374
+ let(:arguments) { ['domain', '--help'] }
375
+
376
+ context 'help is run' do
377
+ it "should display help" do
378
+ expect { run }.to exit_with_code(0)
379
+ end
380
+ it('should output usage') { run_output.should match("Usage: pbox domain") }
381
+ end
382
+ end
383
+ end