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.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +40 -0
- data/Rakefile +6 -0
- data/autocomplete/pbox_bash +1639 -0
- data/bin/pbox +37 -0
- data/conf/protonbox.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +178 -0
- data/features/deployments_feature.rb +127 -0
- data/features/domains_feature.rb +49 -0
- data/features/keys_feature.rb +37 -0
- data/features/members_feature.rb +166 -0
- data/lib/rhc/auth/basic.rb +64 -0
- data/lib/rhc/auth/token.rb +102 -0
- data/lib/rhc/auth/token_store.rb +53 -0
- data/lib/rhc/auth.rb +5 -0
- data/lib/rhc/autocomplete.rb +66 -0
- data/lib/rhc/autocomplete_templates/bash.erb +39 -0
- data/lib/rhc/cartridge_helpers.rb +118 -0
- data/lib/rhc/cli.rb +40 -0
- data/lib/rhc/command_runner.rb +186 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +701 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +96 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +326 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +167 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/git_clone.rb +29 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/snapshot.rb +137 -0
- data/lib/rhc/commands/ssh.rb +51 -0
- data/lib/rhc/commands/sshkey.rb +97 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +320 -0
- data/lib/rhc/context_helper.rb +121 -0
- data/lib/rhc/core_ext.rb +202 -0
- data/lib/rhc/coverage_helper.rb +33 -0
- data/lib/rhc/deployment_helpers.rb +88 -0
- data/lib/rhc/exceptions.rb +232 -0
- data/lib/rhc/git_helpers.rb +91 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +477 -0
- data/lib/rhc/highline_extensions.rb +479 -0
- data/lib/rhc/json.rb +51 -0
- data/lib/rhc/output_helpers.rb +260 -0
- data/lib/rhc/rest/activation.rb +11 -0
- data/lib/rhc/rest/alias.rb +42 -0
- data/lib/rhc/rest/api.rb +87 -0
- data/lib/rhc/rest/application.rb +332 -0
- data/lib/rhc/rest/attributes.rb +36 -0
- data/lib/rhc/rest/authorization.rb +8 -0
- data/lib/rhc/rest/base.rb +79 -0
- data/lib/rhc/rest/cartridge.rb +154 -0
- data/lib/rhc/rest/client.rb +650 -0
- data/lib/rhc/rest/deployment.rb +18 -0
- data/lib/rhc/rest/domain.rb +98 -0
- data/lib/rhc/rest/environment_variable.rb +15 -0
- data/lib/rhc/rest/gear_group.rb +16 -0
- data/lib/rhc/rest/httpclient.rb +145 -0
- data/lib/rhc/rest/key.rb +44 -0
- data/lib/rhc/rest/membership.rb +105 -0
- data/lib/rhc/rest/mock.rb +1024 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/ssh_helpers.rb +378 -0
- data/lib/rhc/tar_gz.rb +51 -0
- data/lib/rhc/usage_templates/command_help.erb +51 -0
- data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
- data/lib/rhc/usage_templates/help.erb +35 -0
- data/lib/rhc/usage_templates/missing_help.erb +1 -0
- data/lib/rhc/usage_templates/options_help.erb +12 -0
- data/lib/rhc/vendor/okjson.rb +600 -0
- data/lib/rhc/vendor/parseconfig.rb +178 -0
- data/lib/rhc/vendor/sshkey.rb +253 -0
- data/lib/rhc/vendor/zliby.rb +628 -0
- data/lib/rhc/version.rb +5 -0
- data/lib/rhc/wizard.rb +633 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +89 -0
- data/spec/direct_execution_helper.rb +338 -0
- data/spec/keys/example.pem +23 -0
- data/spec/keys/example_private.pem +27 -0
- data/spec/keys/server.pem +19 -0
- data/spec/rest_spec_helper.rb +31 -0
- data/spec/rhc/assets/cert.crt +22 -0
- data/spec/rhc/assets/cert_key_rsa +27 -0
- data/spec/rhc/assets/empty.txt +0 -0
- data/spec/rhc/assets/env_vars.txt +7 -0
- data/spec/rhc/assets/env_vars_2.txt +1 -0
- data/spec/rhc/assets/foo.txt +1 -0
- data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
- data/spec/rhc/assets/targz_sample.tar.gz +0 -0
- data/spec/rhc/auth_spec.rb +442 -0
- data/spec/rhc/cli_spec.rb +188 -0
- data/spec/rhc/command_spec.rb +435 -0
- data/spec/rhc/commands/account_spec.rb +42 -0
- data/spec/rhc/commands/alias_spec.rb +333 -0
- data/spec/rhc/commands/app_spec.rb +754 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +145 -0
- data/spec/rhc/commands/cartridge_spec.rb +641 -0
- data/spec/rhc/commands/deployment_spec.rb +286 -0
- data/spec/rhc/commands/domain_spec.rb +383 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +80 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +228 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/server_spec.rb +69 -0
- data/spec/rhc/commands/setup_spec.rb +118 -0
- data/spec/rhc/commands/snapshot_spec.rb +179 -0
- data/spec/rhc/commands/ssh_spec.rb +163 -0
- data/spec/rhc/commands/sshkey_spec.rb +188 -0
- data/spec/rhc/commands/tail_spec.rb +81 -0
- data/spec/rhc/commands/threaddump_spec.rb +84 -0
- data/spec/rhc/config_spec.rb +407 -0
- data/spec/rhc/helpers_spec.rb +524 -0
- data/spec/rhc/highline_extensions_spec.rb +314 -0
- data/spec/rhc/json_spec.rb +30 -0
- data/spec/rhc/rest_application_spec.rb +248 -0
- data/spec/rhc/rest_client_spec.rb +752 -0
- data/spec/rhc/rest_spec.rb +740 -0
- data/spec/rhc/targz_spec.rb +55 -0
- data/spec/rhc/wizard_spec.rb +756 -0
- data/spec/spec_helper.rb +575 -0
- data/spec/wizard_spec_helper.rb +330 -0
- 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
|