startapp 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/COPYRIGHT +1 -0
- data/LICENSE +11 -0
- data/README.md +95 -0
- data/Rakefile +6 -0
- data/autocomplete/rhc_bash +1672 -0
- data/bin/app +37 -0
- data/conf/express.conf +8 -0
- data/features/assets/deploy.tar.gz +0 -0
- data/features/core_feature.rb +191 -0
- data/features/deployments_feature.rb +129 -0
- data/features/domains_feature.rb +58 -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 +185 -0
- data/lib/rhc/commands/account.rb +25 -0
- data/lib/rhc/commands/alias.rb +124 -0
- data/lib/rhc/commands/app.rb +726 -0
- data/lib/rhc/commands/apps.rb +20 -0
- data/lib/rhc/commands/authorization.rb +115 -0
- data/lib/rhc/commands/base.rb +174 -0
- data/lib/rhc/commands/cartridge.rb +329 -0
- data/lib/rhc/commands/clone.rb +66 -0
- data/lib/rhc/commands/configure.rb +20 -0
- data/lib/rhc/commands/create.rb +100 -0
- data/lib/rhc/commands/delete.rb +19 -0
- data/lib/rhc/commands/deploy.rb +32 -0
- data/lib/rhc/commands/deployment.rb +82 -0
- data/lib/rhc/commands/domain.rb +172 -0
- data/lib/rhc/commands/env.rb +142 -0
- data/lib/rhc/commands/force_stop.rb +17 -0
- data/lib/rhc/commands/git_clone.rb +34 -0
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/logs.rb +21 -0
- data/lib/rhc/commands/member.rb +148 -0
- data/lib/rhc/commands/port_forward.rb +197 -0
- data/lib/rhc/commands/reload.rb +17 -0
- data/lib/rhc/commands/restart.rb +17 -0
- data/lib/rhc/commands/scp.rb +54 -0
- data/lib/rhc/commands/server.rb +40 -0
- data/lib/rhc/commands/setup.rb +60 -0
- data/lib/rhc/commands/show.rb +43 -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/start.rb +17 -0
- data/lib/rhc/commands/stop.rb +17 -0
- data/lib/rhc/commands/tail.rb +47 -0
- data/lib/rhc/commands/threaddump.rb +14 -0
- data/lib/rhc/commands/tidy.rb +17 -0
- data/lib/rhc/commands.rb +396 -0
- data/lib/rhc/config.rb +321 -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 +111 -0
- data/lib/rhc/exceptions.rb +256 -0
- data/lib/rhc/git_helpers.rb +106 -0
- data/lib/rhc/help_formatter.rb +55 -0
- data/lib/rhc/helpers.rb +481 -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 +348 -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 +162 -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 +1042 -0
- data/lib/rhc/rest/user.rb +32 -0
- data/lib/rhc/rest.rb +148 -0
- data/lib/rhc/scp_helpers.rb +27 -0
- data/lib/rhc/ssh_helpers.rb +380 -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 +61 -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 +637 -0
- data/lib/rhc.rb +34 -0
- data/spec/coverage_helper.rb +82 -0
- data/spec/direct_execution_helper.rb +339 -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 +186 -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 +777 -0
- data/spec/rhc/commands/apps_spec.rb +39 -0
- data/spec/rhc/commands/authorization_spec.rb +157 -0
- data/spec/rhc/commands/cartridge_spec.rb +665 -0
- data/spec/rhc/commands/clone_spec.rb +41 -0
- data/spec/rhc/commands/deployment_spec.rb +327 -0
- data/spec/rhc/commands/domain_spec.rb +401 -0
- data/spec/rhc/commands/env_spec.rb +493 -0
- data/spec/rhc/commands/git_clone_spec.rb +102 -0
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/member_spec.rb +247 -0
- data/spec/rhc/commands/port_forward_spec.rb +217 -0
- data/spec/rhc/commands/scp_spec.rb +77 -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 +531 -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 +258 -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 +469 -0
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'base64'
|
|
3
|
+
require 'rhc/commands'
|
|
4
|
+
|
|
5
|
+
describe RHC::Auth::Basic do
|
|
6
|
+
let(:user){ 'test_user' }
|
|
7
|
+
let(:password){ 'test pass' }
|
|
8
|
+
let(:auth_hash){ {:user => user, :password => password} }
|
|
9
|
+
let(:options){ (o = Commander::Command::Options.new).default(default_options); o }
|
|
10
|
+
let(:default_options){ {} }
|
|
11
|
+
let(:client){ double(:supports_sessions? => false) }
|
|
12
|
+
|
|
13
|
+
its(:username){ should be_nil }
|
|
14
|
+
its(:username?){ should be_false }
|
|
15
|
+
its(:password){ should be_nil }
|
|
16
|
+
its(:options){ should_not be_nil }
|
|
17
|
+
its(:can_authenticate?){ should be_false }
|
|
18
|
+
its(:openshift_server){ should == 'broker.startapp.bg' }
|
|
19
|
+
|
|
20
|
+
def resolved(hash)
|
|
21
|
+
hash.each_pair do |k,v|
|
|
22
|
+
hash[k] = v.call if v.is_a? Proc
|
|
23
|
+
end
|
|
24
|
+
hash
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with user options" do
|
|
28
|
+
subject{ described_class.new(options) }
|
|
29
|
+
|
|
30
|
+
its(:username){ should be_nil }
|
|
31
|
+
its(:username?){ should be_false }
|
|
32
|
+
its(:password){ should be_nil }
|
|
33
|
+
its(:options){ should equal(options) }
|
|
34
|
+
|
|
35
|
+
context "that include user info" do
|
|
36
|
+
let(:default_options){ {:rhlogin => user, :password => password} }
|
|
37
|
+
|
|
38
|
+
its(:username){ should == user }
|
|
39
|
+
its(:username?){ should be_true }
|
|
40
|
+
its(:password){ should == password }
|
|
41
|
+
its(:can_authenticate?){ should be_true }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "that includes server" do
|
|
45
|
+
let(:default_options){ {:server => 'test.com'} }
|
|
46
|
+
|
|
47
|
+
its(:openshift_server){ should == 'test.com' }
|
|
48
|
+
it do
|
|
49
|
+
subject.should_receive(:ask).with("Login to test.com: ").and_return(user)
|
|
50
|
+
subject.send(:ask_username).should == user
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "with --noprompt" do
|
|
55
|
+
let(:default_options){ {:noprompt => true} }
|
|
56
|
+
|
|
57
|
+
its(:ask_username){ should be_false }
|
|
58
|
+
its(:ask_password){ should be_false }
|
|
59
|
+
its(:username?){ should be_false }
|
|
60
|
+
it("should not retry") do
|
|
61
|
+
subject.should_not_receive(:ask_username)
|
|
62
|
+
subject.retry_auth?(double(:status => 401), client).should be_false
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when initialized with a hash" do
|
|
68
|
+
subject{ described_class.new({:rhlogin => user, :password => password}) }
|
|
69
|
+
its(:username){ should == user }
|
|
70
|
+
its(:password){ should == password }
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
describe "#ask_username" do
|
|
75
|
+
before{ subject.should_receive(:openshift_server).and_return('test.com') }
|
|
76
|
+
before{ subject.should_receive(:ask).with("Login to test.com: ").and_return(user) }
|
|
77
|
+
|
|
78
|
+
it do
|
|
79
|
+
subject.send(:ask_username).should == user
|
|
80
|
+
subject.send(:username).should == user
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
context "with a different user" do
|
|
84
|
+
subject{ described_class.new('other', nil) }
|
|
85
|
+
it do
|
|
86
|
+
subject.send(:ask_username).should == user
|
|
87
|
+
subject.send(:username).should == user
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "#ask_password" do
|
|
93
|
+
before{ subject.should_receive(:ask).with("Password: ").and_return(password) }
|
|
94
|
+
it do
|
|
95
|
+
subject.send(:ask_password).should == password
|
|
96
|
+
subject.send(:password).should == password
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "with a different password" do
|
|
100
|
+
subject{ described_class.new(user, 'other') }
|
|
101
|
+
it do
|
|
102
|
+
subject.send(:ask_password).should == password
|
|
103
|
+
subject.send(:password).should == password
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "#to_request" do
|
|
109
|
+
let(:request){ {} }
|
|
110
|
+
|
|
111
|
+
context "when the request is lazy" do
|
|
112
|
+
let(:request){ {:lazy_auth => true} }
|
|
113
|
+
before{ subject.should_receive(:ask_username).never }
|
|
114
|
+
before{ subject.should_receive(:ask_password).never }
|
|
115
|
+
|
|
116
|
+
it { subject.to_request(request).should == request }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
context "when password and user are provided" do
|
|
120
|
+
subject{ described_class.new(user, password) }
|
|
121
|
+
|
|
122
|
+
it { subject.to_request(request).should equal(request) }
|
|
123
|
+
it { resolved(subject.to_request(request)).should == auth_hash }
|
|
124
|
+
|
|
125
|
+
context "when the request is lazy" do
|
|
126
|
+
let(:request){ {:lazy_auth => true} }
|
|
127
|
+
|
|
128
|
+
it { subject.to_request(request).should == auth_hash.merge(request) }
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
context "when password is not provided" do
|
|
133
|
+
subject{ described_class.new(user, nil) }
|
|
134
|
+
|
|
135
|
+
its(:password){ should be_nil }
|
|
136
|
+
it "should ask for the password" do
|
|
137
|
+
subject.should_receive(:ask_password).and_return(password)
|
|
138
|
+
resolved(subject.to_request(request)).should == auth_hash
|
|
139
|
+
end
|
|
140
|
+
it "should remember the password" do
|
|
141
|
+
subject.should_receive(:ask_password).and_return(password)
|
|
142
|
+
subject.to_request(request)
|
|
143
|
+
resolved(subject.to_request(request)).should == auth_hash
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
context "when the request is lazy" do
|
|
147
|
+
let(:request){ {:lazy_auth => true} }
|
|
148
|
+
before{ subject.should_receive(:ask_password).never }
|
|
149
|
+
|
|
150
|
+
it { subject.to_request(request).should == auth_hash.merge(request) }
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context "when user is not provided" do
|
|
155
|
+
subject{ described_class.new(nil, password) }
|
|
156
|
+
|
|
157
|
+
its(:username){ should be_nil }
|
|
158
|
+
it "should ask for the username" do
|
|
159
|
+
subject.should_receive(:ask_username).and_return(user)
|
|
160
|
+
resolved(subject.to_request(request)).should == auth_hash
|
|
161
|
+
end
|
|
162
|
+
it "should remember the username" do
|
|
163
|
+
subject.should_receive(:ask_username).and_return(user)
|
|
164
|
+
subject.to_request(request)
|
|
165
|
+
resolved(subject.to_request(request)).should == auth_hash
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
context "when the request is lazy" do
|
|
169
|
+
let(:request){ {:lazy_auth => true} }
|
|
170
|
+
before{ subject.should_receive(:ask_username).never }
|
|
171
|
+
|
|
172
|
+
it { subject.to_request(request).should == auth_hash.merge(request) }
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
describe "#retry_auth?" do
|
|
178
|
+
context "when the response succeeds" do
|
|
179
|
+
let(:response){ double(:cookies => {}, :status => 200) }
|
|
180
|
+
|
|
181
|
+
it{ subject.retry_auth?(response, client).should be_false }
|
|
182
|
+
end
|
|
183
|
+
context "when the response succeeds with a cookie" do
|
|
184
|
+
let(:response){ double(:cookies => [double(:name => 'rh_sso', :value => '1')], :status => 200) }
|
|
185
|
+
it{ subject.retry_auth?(response, client).should be_false }
|
|
186
|
+
end
|
|
187
|
+
context "when the response requires authentication" do
|
|
188
|
+
let(:response){ double(:status => 401) }
|
|
189
|
+
|
|
190
|
+
context "with no user and no password" do
|
|
191
|
+
subject{ described_class.new(nil, nil) }
|
|
192
|
+
it("should ask for user and password") do
|
|
193
|
+
subject.should_receive(:ask_username).and_return(user)
|
|
194
|
+
subject.should_receive(:ask_password).and_return(password)
|
|
195
|
+
subject.retry_auth?(response, client).should be_true
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context "with user and no password" do
|
|
200
|
+
subject{ described_class.new(user, nil) }
|
|
201
|
+
it("should ask for password only") do
|
|
202
|
+
subject.should_receive(:ask_password).and_return(password)
|
|
203
|
+
subject.retry_auth?(response, client).should be_true
|
|
204
|
+
end
|
|
205
|
+
it("should ask for password twice") do
|
|
206
|
+
subject.should_receive(:ask_password).twice.and_return(password)
|
|
207
|
+
subject.retry_auth?(response, client).should be_true
|
|
208
|
+
subject.retry_auth?(response, client).should be_true
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
context "with user and password" do
|
|
213
|
+
subject{ described_class.new(user, password) }
|
|
214
|
+
it("should not prompt for reauthentication") do
|
|
215
|
+
subject.should_not_receive(:ask_password)
|
|
216
|
+
subject.should_receive(:error).with("Username or password is not correct")
|
|
217
|
+
subject.retry_auth?(response, client).should be_false
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
describe RHC::Auth::Token do
|
|
225
|
+
subject{ described_class.new(options) }
|
|
226
|
+
|
|
227
|
+
let(:token){ 'a_token' }
|
|
228
|
+
let(:options){ (o = Commander::Command::Options.new).default(default_options); o }
|
|
229
|
+
let(:default_options){ {} }
|
|
230
|
+
let(:client){ double(:supports_sessions? => false) }
|
|
231
|
+
let(:auth){ nil }
|
|
232
|
+
let(:store){ nil }
|
|
233
|
+
|
|
234
|
+
its(:username){ should be_nil }
|
|
235
|
+
its(:options){ should_not be_nil }
|
|
236
|
+
its(:can_authenticate?){ should be_false }
|
|
237
|
+
its(:openshift_server){ should == 'broker.startapp.bg' }
|
|
238
|
+
|
|
239
|
+
context "with user options" do
|
|
240
|
+
its(:username){ should be_nil }
|
|
241
|
+
its(:options){ should equal(options) }
|
|
242
|
+
|
|
243
|
+
context "that include token" do
|
|
244
|
+
let(:default_options){ {:token => token} }
|
|
245
|
+
its(:can_authenticate?){ should be_true }
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
context "that includes server" do
|
|
249
|
+
let(:default_options){ {:server => 'test.com'} }
|
|
250
|
+
its(:openshift_server){ should == 'test.com' }
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
context "with --noprompt" do
|
|
254
|
+
let(:default_options){ {:noprompt => true} }
|
|
255
|
+
|
|
256
|
+
its(:username){ should be_nil }
|
|
257
|
+
it("should not retry") do
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
context "when initialized with a hash" do
|
|
263
|
+
subject{ described_class.new({:token => token}) }
|
|
264
|
+
its(:token){ should == token }
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
context "when initialized with a string" do
|
|
268
|
+
subject{ described_class.new(token) }
|
|
269
|
+
its(:token){ should == token }
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
context "when initialized with an auth object" do
|
|
273
|
+
subject{ described_class.new(nil, auth) }
|
|
274
|
+
let(:auth){ double(:username => 'foo') }
|
|
275
|
+
its(:username){ should == 'foo' }
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
context "when initialized with a store" do
|
|
279
|
+
subject{ described_class.new(nil, nil, store) }
|
|
280
|
+
let(:store){ double }
|
|
281
|
+
before{ store.should_receive(:get).with(nil, 'broker.startapp.bg').and_return(token) }
|
|
282
|
+
it("should read the token for the user") do
|
|
283
|
+
subject.send(:token).should == token
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
describe "#save" do
|
|
288
|
+
subject{ described_class.new(nil, nil, store) }
|
|
289
|
+
context "when store is set" do
|
|
290
|
+
let(:store){ double(:get => nil) }
|
|
291
|
+
it("should call put on store") do
|
|
292
|
+
subject.should_receive(:username).and_return('foo')
|
|
293
|
+
subject.should_receive(:openshift_server).and_return('bar')
|
|
294
|
+
store.should_receive(:put).with('foo', 'bar', token)
|
|
295
|
+
subject.save(token)
|
|
296
|
+
end
|
|
297
|
+
end
|
|
298
|
+
context "when store is nil" do
|
|
299
|
+
it("should skip calling store"){ subject.save(token) }
|
|
300
|
+
end
|
|
301
|
+
after{ subject.instance_variable_get(:@token).should == token }
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
describe "#to_request" do
|
|
305
|
+
let(:request){ {} }
|
|
306
|
+
subject{ described_class.new(token, auth) }
|
|
307
|
+
|
|
308
|
+
context "when token is provided" do
|
|
309
|
+
it("should pass bearer token to the server"){ subject.to_request(request).should == {:headers => {'authorization' => "Bearer #{token}"}} }
|
|
310
|
+
|
|
311
|
+
context "when the request is lazy" do
|
|
312
|
+
let(:request){ {:lazy_auth => true} }
|
|
313
|
+
it("should pass bearer token to the server"){ subject.to_request(request).should == {:lazy_auth => true, :headers => {'authorization' => "Bearer #{token}"}} }
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
context "when token is not provided" do
|
|
318
|
+
subject{ described_class.new(nil) }
|
|
319
|
+
|
|
320
|
+
it("should pass not bearer token to the server"){ subject.to_request(request).should == {} }
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
context "when a parent auth class is passed" do
|
|
324
|
+
subject{ described_class.new(nil, auth) }
|
|
325
|
+
let(:auth){ double }
|
|
326
|
+
it("should invoke the parent") do
|
|
327
|
+
auth.should_receive(:to_request).with(request).and_return(request)
|
|
328
|
+
subject.to_request(request).should == request
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
describe "#retry_auth?" do
|
|
334
|
+
subject{ described_class.new(token, auth) }
|
|
335
|
+
|
|
336
|
+
context "when the response succeeds" do
|
|
337
|
+
let(:response){ double(:cookies => {}, :status => 200) }
|
|
338
|
+
it{ subject.retry_auth?(response, client).should be_false }
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
context "when the response requires authentication" do
|
|
342
|
+
let(:response){ double(:status => 401) }
|
|
343
|
+
|
|
344
|
+
context "with no token" do
|
|
345
|
+
subject{ described_class.new(nil, nil) }
|
|
346
|
+
it("should return false"){ subject.retry_auth?(response, client).should be_false }
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
context "when a nested auth object can't authenticate" do
|
|
350
|
+
let(:auth){ double(:can_authenticate? => false) }
|
|
351
|
+
it("should raise an error"){ expect{ subject.retry_auth?(response, client) }.to raise_error(RHC::Rest::TokenExpiredOrInvalid) }
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
context "with a nested auth object" do
|
|
355
|
+
let(:auth){ double('nested_auth', :can_authenticate? => true) }
|
|
356
|
+
subject{ described_class.new(options, auth) }
|
|
357
|
+
|
|
358
|
+
it("should not use token auth") do
|
|
359
|
+
auth.should_receive(:retry_auth?).with(response, client).and_return true
|
|
360
|
+
subject.retry_auth?(response, client).should be_true
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
context "when noprompt is requested" do
|
|
364
|
+
let(:default_options){ {:token => token, :noprompt => true} }
|
|
365
|
+
it("should raise an error"){ expect{ subject.retry_auth?(response, client) }.to raise_error(RHC::Rest::TokenExpiredOrInvalid) }
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
context "when authorization tokens are enabled locally" do
|
|
369
|
+
let(:default_options){ {:use_authorization_tokens => true} }
|
|
370
|
+
|
|
371
|
+
context "without session support" do
|
|
372
|
+
let(:default_options){ {:use_authorization_tokens => true, :token => 'foo'} }
|
|
373
|
+
let(:client){ double('client', :supports_sessions? => false) }
|
|
374
|
+
|
|
375
|
+
it("should invoke raise an error on retry because sessions are not supported") do
|
|
376
|
+
expect{ subject.retry_auth?(response, client) }.to raise_error RHC::Rest::AuthorizationsNotSupported
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
context "we expect a warning and a call to client" do
|
|
381
|
+
let(:auth_token){ nil }
|
|
382
|
+
let(:client){ double('client', :supports_sessions? => true) }
|
|
383
|
+
before{ client.should_receive(:new_session).with(:auth => auth).and_return(auth_token) }
|
|
384
|
+
|
|
385
|
+
it("should print a message") do
|
|
386
|
+
subject.should_receive(:info).with("Please sign in to start a new session to #{subject.openshift_server}.")
|
|
387
|
+
auth.should_receive(:retry_auth?).with(response, client).and_return true
|
|
388
|
+
subject.retry_auth?(response, client).should be_true
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
context "with a token" do
|
|
392
|
+
let(:default_options){ {:use_authorization_tokens => true, :token => 'foo'} }
|
|
393
|
+
it("should invoke raise an error on retry because sessions are not supported") do
|
|
394
|
+
subject.should_receive(:warn).with("Your authorization token has expired. Please sign in now to continue on #{subject.openshift_server}.")
|
|
395
|
+
auth.should_receive(:retry_auth?).with(response, client).and_return true
|
|
396
|
+
subject.retry_auth?(response, client).should be_true
|
|
397
|
+
#expect{ subject.retry_auth?(response, client) }.to raise_error RHC::Rest::AuthorizationsNotSupported
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
context "when the token request fails" do
|
|
402
|
+
before{ subject.should_receive(:info).with("Please sign in to start a new session to #{subject.openshift_server}.") }
|
|
403
|
+
it("should invoke retry on the parent") do
|
|
404
|
+
auth.should_receive(:retry_auth?).with(response, client).and_return false
|
|
405
|
+
subject.retry_auth?(response, client).should be_false
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
context "when the token request succeeds" do
|
|
410
|
+
let(:auth_token){ double('auth_token', :token => 'bar') }
|
|
411
|
+
before{ subject.should_receive(:info).with("Please sign in to start a new session to #{subject.openshift_server}.") }
|
|
412
|
+
it("should save the token and return true") do
|
|
413
|
+
subject.should_receive(:save).with(auth_token.token).and_return true
|
|
414
|
+
subject.retry_auth?(response, client).should be_true
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
end
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
end
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
describe RHC::Auth::TokenStore do
|
|
425
|
+
subject{ described_class.new(dir) }
|
|
426
|
+
let(:dir){ Dir.mktmpdir }
|
|
427
|
+
|
|
428
|
+
context "when a key is stored" do
|
|
429
|
+
before{ subject.put('foo', 'bar', 'token') }
|
|
430
|
+
it("can be retrieved"){ subject.get('foo', 'bar').should == 'token' }
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it("should handle missing files"){ subject.get('foo', 'other').should be_nil }
|
|
434
|
+
it("should put a file on disk"){ expect{ subject.put('test', 'server', 'value') }.to change{ Dir.entries(dir).length }.by(1) }
|
|
435
|
+
|
|
436
|
+
describe "#clear" do
|
|
437
|
+
before{ subject.put('test', 'server2', 'value2') }
|
|
438
|
+
it("should return true"){ subject.clear.should be_true }
|
|
439
|
+
it("should empty the directory"){ expect{ subject.clear }.to change{ Dir.entries(dir).length }.by_at_least(-1) }
|
|
440
|
+
after{ Dir.entries(dir).length.should == 2 }
|
|
441
|
+
end
|
|
442
|
+
end
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rhc/wizard'
|
|
3
|
+
|
|
4
|
+
describe RHC::CLI do
|
|
5
|
+
|
|
6
|
+
shared_examples_for 'a global help page' do
|
|
7
|
+
let(:arguments) { @arguments or raise "no arguments" }
|
|
8
|
+
it('should contain the program description') { run_output.should =~ /Command line interface for StartApp/ }
|
|
9
|
+
it('should describe getting started') { run_output.should =~ /Getting started:/ }
|
|
10
|
+
it('should describe basic command') { run_output.should =~ /Working with apps:/ }
|
|
11
|
+
it('should mention the help command') { run_output.should =~ /See 'app help <command>'/ }
|
|
12
|
+
it('should mention the help options command') { run_output.should =~ /app help options/ }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
shared_examples_for 'a first run wizard' do
|
|
16
|
+
let(:arguments) { @arguments or raise "no arguments" }
|
|
17
|
+
let!(:wizard){ RHC::Wizard.new }
|
|
18
|
+
before{ RHC::Wizard.should_receive(:new).and_return(wizard) }
|
|
19
|
+
it('should create and run a new wizard') { expect{ run }.to call(:run).on(wizard) }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
shared_examples_for 'a help page' do
|
|
23
|
+
let(:arguments) { @arguments or raise "no arguments" }
|
|
24
|
+
it('should contain the program description') { run_output.should =~ /Command line interface for StartApp/ }
|
|
25
|
+
it('should contain the global options') { run_output.should =~ /Global Options/ }
|
|
26
|
+
it('should provide a --config switch') { run_output.should =~ /\-\-config FILE/ }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
shared_examples_for 'a list of all commands' do
|
|
30
|
+
let(:arguments) { @arguments or raise "no arguments" }
|
|
31
|
+
it('should contain a message') { run_output.should =~ /Showing all commands/ }
|
|
32
|
+
it('should contain command help') { run_output.should =~ /Create an application./ }
|
|
33
|
+
it('should contain aliases') { run_output.should =~ /\(also/ }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
shared_examples_for 'a list of commands' do
|
|
37
|
+
let(:arguments) { @arguments or raise "no arguments" }
|
|
38
|
+
it('should contain a message') { run_output.should =~ /Showing commands matching '/ }
|
|
39
|
+
it('should contain command help') { run_output.should =~ /Create an application./ }
|
|
40
|
+
it('should contain aliases') { run_output.should =~ /\(also/ }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
shared_examples_for 'a command-line options help page' do
|
|
44
|
+
let(:arguments) { @arguments or raise "no arguments" }
|
|
45
|
+
it('should contain an introduction') { run_output.should =~ /The following options can be passed to any/ }
|
|
46
|
+
it('should reference the configuration') { run_output.should match(".startapp/express.conf") }
|
|
47
|
+
it('should describe the --config switch') { run_output.should =~ /\-\-config FILE/ }
|
|
48
|
+
it('should describe the --ssl-version switch') { run_output.should =~ /\-\-ssl\-version VERSION/ }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
shared_examples_for 'an invalid command' do
|
|
52
|
+
let(:arguments) { @arguments }
|
|
53
|
+
it('should contain the invalid command message') { run_output.should =~ /is not recognized/ }
|
|
54
|
+
it('should contain the arguments') { run_output.should include(@arguments[0]) }
|
|
55
|
+
it('should reference --help') { run_output.should =~ / help\b/ }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
shared_examples_for 'version output' do
|
|
59
|
+
let(:arguments) { @arguments }
|
|
60
|
+
it 'should contain version output' do
|
|
61
|
+
run_output.should =~ /app \d+\.\d+(:?\.d+)?/
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
before{ base_config }
|
|
66
|
+
|
|
67
|
+
describe "--version" do
|
|
68
|
+
context "by itself" do
|
|
69
|
+
before :each do
|
|
70
|
+
@arguments = ['--version']
|
|
71
|
+
end
|
|
72
|
+
it_should_behave_like 'version output'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe '#start' do
|
|
77
|
+
before{ RHC::Wizard.stub(:has_configuration?).and_return(true) }
|
|
78
|
+
|
|
79
|
+
context 'with no arguments' do
|
|
80
|
+
before(:each) { @arguments = [] }
|
|
81
|
+
it_should_behave_like 'a global help page'
|
|
82
|
+
|
|
83
|
+
context "without a config file" do
|
|
84
|
+
it_should_behave_like 'a global help page'
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
context 'with an ambiguous option' do
|
|
89
|
+
let(:arguments){ ['help', '-s'] }
|
|
90
|
+
it('should describe an ambiguous error'){ run_output.should match("The option -s is ambiguous. You will need to specify the entire option.") }
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'with an invalid command' do
|
|
94
|
+
before(:each) { @arguments = ['invalidcommand'] }
|
|
95
|
+
it_should_behave_like 'an invalid command'
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
context 'with --help and invalid command' do
|
|
99
|
+
before(:each) { @arguments = ['invalidcommand', '--help'] }
|
|
100
|
+
it_should_behave_like 'an invalid command'
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'with help and invalid command' do
|
|
104
|
+
before(:each) { @arguments = ['help', 'invalidcommand'] }
|
|
105
|
+
it_should_behave_like 'an invalid command'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context 'with help commands' do
|
|
109
|
+
before(:each) { @arguments = ['help', 'commands'] }
|
|
110
|
+
it_should_behave_like 'a list of all commands'
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'with help and possible command matches' do
|
|
114
|
+
before(:each) { @arguments = ['help', 'app c'] }
|
|
115
|
+
it_should_behave_like 'a list of commands'
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
context 'with help and a single matching command segment' do
|
|
119
|
+
let(:arguments){ ['help', 'app creat'] }
|
|
120
|
+
it("prints the usage for the command"){ run_output.should match('Usage: app app-create <') }
|
|
121
|
+
it("prints part of the description for the command"){ run_output.should match('StartApp runs the components of your') }
|
|
122
|
+
it("prints a local option"){ run_output.should match('--namespace NAME') }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context 'with --help' do
|
|
126
|
+
before(:each){ @arguments = ['--help'] }
|
|
127
|
+
it_should_behave_like 'a global help page'
|
|
128
|
+
|
|
129
|
+
context 'without a config file' do
|
|
130
|
+
before{ RHC::Wizard.stub(:has_configuration?).and_return(false) }
|
|
131
|
+
it_should_behave_like 'a global help page'
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context 'with -h' do
|
|
136
|
+
before(:each){ @arguments = ['-h'] }
|
|
137
|
+
it_should_behave_like 'a global help page'
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context 'with help' do
|
|
141
|
+
before(:each){ @arguments = ['help'] }
|
|
142
|
+
it_should_behave_like 'a global help page'
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context 'with help options' do
|
|
146
|
+
before(:each){ @arguments = ['help', 'options'] }
|
|
147
|
+
it_should_behave_like 'a command-line options help page'
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe 'option provided twice' do
|
|
152
|
+
before{ user_config }
|
|
153
|
+
let!(:rest_client){ MockRestClient.new }
|
|
154
|
+
before(:each) do
|
|
155
|
+
domain = rest_client.add_domain("mock_domain")
|
|
156
|
+
@app = domain.add_application("app1", "mock_type")
|
|
157
|
+
end
|
|
158
|
+
context 'when run with -a provided twice, last being the valid one' do
|
|
159
|
+
let(:arguments) { ['cartridge', 'remove', 'mock_cart-1', '--confirm', '--trace','-a', 'app2', '-a', 'app1', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
|
|
160
|
+
it "should remove cartridge" do
|
|
161
|
+
@app.add_cartridge('mock_cart-1')
|
|
162
|
+
expect { run }.to exit_with_code(0)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
context 'when run with -a provided twice, last not being the valid one' do
|
|
166
|
+
let(:arguments) { ['cartridge', 'remove', 'mock_cart-1', '--confirm', '--trace','-a', 'app1', '-a', 'app2', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
|
|
167
|
+
it "should raise an application not found exception" do
|
|
168
|
+
expect{ run }.to raise_error(RHC::Rest::ApplicationNotFoundException)
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe '#set_terminal' do
|
|
174
|
+
before(:each) { mock_terminal }
|
|
175
|
+
it('should update $terminal.wrap_at') do
|
|
176
|
+
$stdout.should_receive(:tty?).twice.and_return(true)
|
|
177
|
+
HighLine::SystemExtensions.should_receive(:terminal_size).and_return([5])
|
|
178
|
+
expect { RHC::CLI.set_terminal }.to change($terminal, :wrap_at)
|
|
179
|
+
end
|
|
180
|
+
it('should not update $terminal.page_at') do
|
|
181
|
+
$stdout.should_receive(:tty?).twice.and_return(true)
|
|
182
|
+
expect { RHC::CLI.set_terminal }.to_not change($terminal, :page_at)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
end
|