startapp 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -0,0 +1,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