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,756 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rest_spec_helper'
|
|
3
|
+
require 'rhc/wizard'
|
|
4
|
+
require 'rhc/vendor/parseconfig'
|
|
5
|
+
require 'rhc/config'
|
|
6
|
+
require 'ostruct'
|
|
7
|
+
require 'rest_spec_helper'
|
|
8
|
+
require 'wizard_spec_helper'
|
|
9
|
+
require 'tmpdir'
|
|
10
|
+
|
|
11
|
+
# Allow to define the id method
|
|
12
|
+
OpenStruct.__send__(:define_method, :id) { @table[:id] } if RUBY_VERSION.to_f == 1.8
|
|
13
|
+
|
|
14
|
+
describe RHC::Wizard do
|
|
15
|
+
|
|
16
|
+
def mock_config
|
|
17
|
+
RHC::Config.stub(:home_dir).and_return('/home/mock_user')
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:options){ (o = Commander::Command::Options.new).default(default_options); o }
|
|
21
|
+
let(:config){ RHC::Config.new.tap{ |c| c.stub(:home_dir).and_return('/home/mock_user') } }
|
|
22
|
+
let(:default_options){ {} }
|
|
23
|
+
|
|
24
|
+
describe "#finalize_stage" do
|
|
25
|
+
subject{ described_class.new(config, options) }
|
|
26
|
+
before{ subject.should_receive(:say).with(/The StartApp client tools have been configured/) }
|
|
27
|
+
it{ subject.send(:finalize_stage).should be_true }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "#token_store" do
|
|
31
|
+
subject{ described_class.new(config, options) }
|
|
32
|
+
it{ subject.send(:token_store).should be_a(RHC::Auth::TokenStore) }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "#has_configuration?" do
|
|
36
|
+
subject{ described_class }
|
|
37
|
+
before{ File.should_receive(:exists?).with(RHC::Config.local_config_path).at_least(1).times.and_return(true) }
|
|
38
|
+
its(:has_configuration?){ should be_true }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "#setup_test_stage" do
|
|
42
|
+
subject{ described_class.new(config, options) }
|
|
43
|
+
it "should rescue problems" do
|
|
44
|
+
subject.should_receive(:all_test_methods).and_return([:_test])
|
|
45
|
+
subject.should_receive(:_test).and_raise(StandardError.new("An error message"))
|
|
46
|
+
capture{ subject.send(:setup_test_stage) }.should match "An error message"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe "#test_private_key_mode" do
|
|
51
|
+
it "should raise when the file is in the wrong mode" do
|
|
52
|
+
FakeFS do
|
|
53
|
+
mock_config
|
|
54
|
+
FileUtils.mkdir_p(RHC::Config.ssh_dir)
|
|
55
|
+
File.open(RHC::Config.ssh_priv_key_file_path, 'w'){}
|
|
56
|
+
File.expect_mode(RHC::Config.ssh_priv_key_file_path, 0666)
|
|
57
|
+
expect{ subject.send(:test_private_key_mode) }.to raise_error(StandardError)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "#test_ssh_connectivity" do
|
|
63
|
+
subject{ described_class.new(config, options) }
|
|
64
|
+
let(:app) do
|
|
65
|
+
app = Object.new
|
|
66
|
+
app.should_receive(:ssh_url).at_least(1).and_return('ssh://uuid@foo.com')
|
|
67
|
+
app.stub(:host).and_return('foo.com')
|
|
68
|
+
app
|
|
69
|
+
end
|
|
70
|
+
let(:ssh) do
|
|
71
|
+
ssh = Object.new
|
|
72
|
+
ssh.should_receive(:close)
|
|
73
|
+
ssh
|
|
74
|
+
end
|
|
75
|
+
let(:interrupt){ Interrupt.new('interrupted') }
|
|
76
|
+
|
|
77
|
+
it "should not attempt an SSH connection" do
|
|
78
|
+
subject.should_receive(:ssh_key_uploaded?).and_return(true)
|
|
79
|
+
subject.should_receive(:applications).and_return([])
|
|
80
|
+
subject.send(:test_ssh_connectivity).should be_true
|
|
81
|
+
end
|
|
82
|
+
it "should attempt an SSH connection to the first app" do
|
|
83
|
+
subject.should_receive(:ssh_key_uploaded?).and_return(true)
|
|
84
|
+
subject.should_receive(:applications).and_return([app])
|
|
85
|
+
Net::SSH.should_receive(:start).with("foo.com", "uuid", {:timeout => 60}).and_return(ssh)
|
|
86
|
+
subject.send(:test_ssh_connectivity).should be_true
|
|
87
|
+
end
|
|
88
|
+
it "should handle a failed connection" do
|
|
89
|
+
subject.should_receive(:ssh_key_uploaded?).and_return(true)
|
|
90
|
+
subject.should_receive(:applications).and_return([app])
|
|
91
|
+
Net::SSH.should_receive(:start).and_raise(StandardError.new('an_error'))
|
|
92
|
+
expect{ subject.send(:test_ssh_connectivity) }.to raise_error(RuntimeError, /An SSH connection could not be established to foo.com/)
|
|
93
|
+
end
|
|
94
|
+
it "should handle an interrupted connection" do
|
|
95
|
+
subject.should_receive(:ssh_key_uploaded?).and_return(true)
|
|
96
|
+
subject.should_receive(:applications).and_return([app])
|
|
97
|
+
subject.should_receive(:debug_error).with(interrupt)
|
|
98
|
+
Net::SSH.should_receive(:start).and_raise(interrupt)
|
|
99
|
+
expect{ subject.send(:test_ssh_connectivity) }.to raise_error(RuntimeError, /Connection attempt to foo.com was interrupted/)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "#login_stage" do
|
|
104
|
+
let(:user){ 'test_user' }
|
|
105
|
+
let(:password){ 'test pass' }
|
|
106
|
+
let(:rest_client){ double }
|
|
107
|
+
let(:auth){ subject.send(:auth) }
|
|
108
|
+
let(:user_obj){ double(:login => user) }
|
|
109
|
+
|
|
110
|
+
subject{ described_class.new(config, options) }
|
|
111
|
+
|
|
112
|
+
def expect_client_test(with_sessions=false)
|
|
113
|
+
subject.should_receive(:new_client_for_options).ordered.and_return(rest_client)
|
|
114
|
+
rest_client.should_receive(:api).ordered
|
|
115
|
+
rest_client.should_receive(:user).ordered.and_return(user_obj)
|
|
116
|
+
rest_client.should_receive(:supports_sessions?).ordered.and_return(with_sessions)
|
|
117
|
+
end
|
|
118
|
+
def expect_raise_from_api(error)
|
|
119
|
+
subject.should_receive(:new_client_for_options).ordered.and_return(rest_client)
|
|
120
|
+
rest_client.should_receive(:api).ordered.and_raise(error)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should prompt for user and password" do
|
|
124
|
+
expect_client_test
|
|
125
|
+
subject.send(:login_stage).should be_true
|
|
126
|
+
subject.send(:options).rhlogin.should == user
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context "with token" do
|
|
130
|
+
let(:token){ 'a_test_value' }
|
|
131
|
+
let(:default_options){ {:token => token, :rhlogin => user} }
|
|
132
|
+
before{ subject.should_receive(:say).with(/Using an existing token for #{user} to login to /).ordered }
|
|
133
|
+
|
|
134
|
+
it "should continue without prompt" do
|
|
135
|
+
expect_client_test
|
|
136
|
+
subject.send(:login_stage).should be_true
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
context "with credentials" do
|
|
141
|
+
let(:server){ mock_uri }
|
|
142
|
+
let(:default_options){ {:rhlogin => user, :password => password, :server => server} }
|
|
143
|
+
before{ subject.should_receive(:say).with(/Using #{user} to login to /).ordered }
|
|
144
|
+
|
|
145
|
+
it "should warn about a self signed cert error" do
|
|
146
|
+
expect_raise_from_api(RHC::Rest::SelfSignedCertificate.new('reason', 'message'))
|
|
147
|
+
subject.should_receive(:warn).with(/server's certificate is self-signed/).ordered
|
|
148
|
+
subject.should_receive(:openshift_online_server?).ordered.and_return(true)
|
|
149
|
+
subject.should_receive(:warn).with(/server between you and StartApp/).ordered
|
|
150
|
+
|
|
151
|
+
subject.send(:login_stage).should be_nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "should warn about a cert error for Online" do
|
|
155
|
+
expect_raise_from_api(RHC::Rest::CertificateVerificationFailed.new('reason', 'message'))
|
|
156
|
+
subject.should_receive(:warn).with(/server's certificate could not be verified/).ordered
|
|
157
|
+
subject.should_receive(:openshift_online_server?).ordered.and_return(true)
|
|
158
|
+
subject.should_receive(:warn).with(/server between you and StartApp/).ordered
|
|
159
|
+
|
|
160
|
+
subject.send(:login_stage).should be_nil
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "should warn about a cert error for custom server and continue" do
|
|
164
|
+
expect_raise_from_api(RHC::Rest::CertificateVerificationFailed.new('reason', 'message'))
|
|
165
|
+
subject.should_receive(:warn).with(/server's certificate could not be verified/).ordered
|
|
166
|
+
subject.should_receive(:openshift_online_server?).ordered.and_return(false)
|
|
167
|
+
subject.should_receive(:warn).with(/bypass this check/).ordered
|
|
168
|
+
subject.should_receive(:agree).with(/Connect without checking/).ordered.and_return(true)
|
|
169
|
+
expect_client_test
|
|
170
|
+
|
|
171
|
+
subject.send(:login_stage).should be_true
|
|
172
|
+
options.insecure.should be_true
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "should warn about a cert error for custom server and be cancelled" do
|
|
176
|
+
expect_raise_from_api(RHC::Rest::CertificateVerificationFailed.new('reason', 'message'))
|
|
177
|
+
subject.should_receive(:warn).with(/server's certificate could not be verified/).ordered
|
|
178
|
+
subject.should_receive(:openshift_online_server?).ordered.and_return(false)
|
|
179
|
+
subject.should_receive(:warn).with(/bypass this check/).ordered
|
|
180
|
+
subject.should_receive(:agree).with(/Connect without checking/).ordered.and_return(false)
|
|
181
|
+
|
|
182
|
+
subject.send(:login_stage).should be_nil
|
|
183
|
+
options.insecure.should be_false
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
context "when the config has enabled tokens" do
|
|
187
|
+
let(:default_options){ {:rhlogin => user, :password => password, :server => server, :use_authorization_tokens => true} }
|
|
188
|
+
let(:store){ double }
|
|
189
|
+
before{ RHC::Auth::TokenStore.stub(:new).and_return(store) }
|
|
190
|
+
before{ expect_client_test(true) }
|
|
191
|
+
|
|
192
|
+
it "should check for an existing token" do
|
|
193
|
+
store.should_receive(:get).and_return(nil)
|
|
194
|
+
|
|
195
|
+
subject.should_receive(:info).with(/StartApp can create and store a token on disk/).ordered
|
|
196
|
+
subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(false)
|
|
197
|
+
|
|
198
|
+
subject.send(:login_stage).should be_true
|
|
199
|
+
options.token.should be_nil
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context "with a server that supports tokens" do
|
|
204
|
+
before{ expect_client_test(true) }
|
|
205
|
+
let(:token){ 'a_test_value' }
|
|
206
|
+
let(:auth_token){ double(:token => token, :expires_in_seconds => 100) }
|
|
207
|
+
let(:store){ double }
|
|
208
|
+
before{ RHC::Auth::TokenStore.stub(:new).and_return(store) }
|
|
209
|
+
|
|
210
|
+
it "should not generate a token if the user does not request it" do
|
|
211
|
+
store.should_not_receive(:get)
|
|
212
|
+
subject.should_receive(:info).with(/StartApp can create and store a token on disk/).ordered
|
|
213
|
+
subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(false)
|
|
214
|
+
|
|
215
|
+
subject.send(:login_stage).should be_true
|
|
216
|
+
options.token.should be_nil
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "should generate a token if the user requests it" do
|
|
220
|
+
store.should_not_receive(:get)
|
|
221
|
+
subject.should_receive(:info).with(/StartApp can create and store a token on disk/).ordered
|
|
222
|
+
subject.should_receive(:agree).with(/Generate a token now?/).ordered.and_return(true)
|
|
223
|
+
subject.should_receive(:say).with(/Generating an authorization token for this client /).ordered
|
|
224
|
+
rest_client.should_receive(:new_session).ordered.and_return(auth_token)
|
|
225
|
+
store.should_receive(:put).with(user, server, token).ordered.and_return(true)
|
|
226
|
+
subject.should_receive(:new_client_for_options).ordered.and_return(rest_client)
|
|
227
|
+
rest_client.should_receive(:user).ordered.and_return(true)
|
|
228
|
+
subject.should_receive(:success).with(/lasts 1 minute/).ordered
|
|
229
|
+
|
|
230
|
+
subject.send(:login_stage).should be_true
|
|
231
|
+
options.token.should == token
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
#TODO: Implement more stage level specs
|
|
238
|
+
|
|
239
|
+
context "when the wizard is run" do
|
|
240
|
+
subject{ RHC::RerunWizard.new(config, options) }
|
|
241
|
+
|
|
242
|
+
before(:each) do
|
|
243
|
+
mock_terminal
|
|
244
|
+
FakeFS.activate!
|
|
245
|
+
FakeFS::FileSystem.clear
|
|
246
|
+
mock_config
|
|
247
|
+
RHC::Config.initialize
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
after(:all) do
|
|
251
|
+
FakeFS.deactivate!
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
#after{ FileUtils.rm_rf(@tmpdir) if @tmpdir }
|
|
255
|
+
let(:home_dir){ '/home/mock_user' }#@tmpdir = Dir.mktmpdir }
|
|
256
|
+
let(:config){ RHC::Config.new.tap{ |c| c.stub(:home_dir).and_return(home_dir) } }
|
|
257
|
+
|
|
258
|
+
let(:options){ (o = Commander::Command::Options.new).default(default_options); o }
|
|
259
|
+
let(:default_options){ {:server => mock_uri} }
|
|
260
|
+
let(:username){ mock_user }
|
|
261
|
+
let(:password){ 'password' }
|
|
262
|
+
let(:user_auth){ {:user => username, :password => password} }
|
|
263
|
+
|
|
264
|
+
describe "#run" do
|
|
265
|
+
context "when a stage returns nil" do
|
|
266
|
+
before{ subject.stub(:greeting_stage).and_return(nil) }
|
|
267
|
+
it "should exit after that stage" do
|
|
268
|
+
subject.should_receive(:login_stage).never
|
|
269
|
+
subject.run.should be_nil
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context "with no settings" do
|
|
275
|
+
before do
|
|
276
|
+
stub_api(false)
|
|
277
|
+
challenge{ stub_user }
|
|
278
|
+
stub_no_keys
|
|
279
|
+
challenge{ stub_no_domains }
|
|
280
|
+
stub_simple_carts(false)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it "should execute the minimal path" do
|
|
284
|
+
should_greet_user
|
|
285
|
+
should_challenge_for(username, password)
|
|
286
|
+
should_write_config
|
|
287
|
+
should_create_an_ssh_keypair
|
|
288
|
+
should_skip_uploading_key
|
|
289
|
+
should_find_git
|
|
290
|
+
should_not_find_problems
|
|
291
|
+
should_skip_creating_namespace
|
|
292
|
+
should_list_types_of_apps_to_create
|
|
293
|
+
should_be_done
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
context "on windows systems" do
|
|
297
|
+
before{ subject.stub(:windows?).and_return(true) }
|
|
298
|
+
it "should display windows info" do
|
|
299
|
+
should_greet_user
|
|
300
|
+
should_challenge_for(username, password)
|
|
301
|
+
should_write_config
|
|
302
|
+
should_create_an_ssh_keypair
|
|
303
|
+
should_skip_uploading_key
|
|
304
|
+
should_display_windows_info
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
context "when the user enters a domain and uploads a key" do
|
|
309
|
+
before do
|
|
310
|
+
stub_add_key
|
|
311
|
+
stub_api_request(:post, 'broker/rest/domains', user_auth).
|
|
312
|
+
with(:body => /(thisnamespaceistoobig|invalidnamespace)/).
|
|
313
|
+
to_return({
|
|
314
|
+
:status => 409,
|
|
315
|
+
:body => {
|
|
316
|
+
:messages => [{:field => 'id', :severity => 'ERROR', :text => 'Too long', :exit_code => 123}]
|
|
317
|
+
}.to_json
|
|
318
|
+
})
|
|
319
|
+
stub_create_domain('testnamespace')
|
|
320
|
+
end
|
|
321
|
+
it "should create the domain" do
|
|
322
|
+
should_greet_user
|
|
323
|
+
should_challenge_for(username, password)
|
|
324
|
+
should_write_config
|
|
325
|
+
should_create_an_ssh_keypair
|
|
326
|
+
should_upload_default_key
|
|
327
|
+
should_find_git
|
|
328
|
+
should_not_find_problems
|
|
329
|
+
should_create_a_namespace
|
|
330
|
+
should_list_types_of_apps_to_create
|
|
331
|
+
should_be_done
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
context "when the user inputs incorrect authentication" do
|
|
335
|
+
before{ stub_api_request(:get, 'broker/rest/user', :user => username, :password => 'invalid').to_return(:status => 401).times(1).to_return(simple_user(username)) }
|
|
336
|
+
it "should prompt them again" do
|
|
337
|
+
should_greet_user
|
|
338
|
+
|
|
339
|
+
input_line username
|
|
340
|
+
input_line 'invalid'
|
|
341
|
+
input_line password
|
|
342
|
+
next_stage.should_not be_nil
|
|
343
|
+
|
|
344
|
+
last_output do |s|
|
|
345
|
+
s.should match("Login to ")
|
|
346
|
+
s.should match("Username or password is not correct")
|
|
347
|
+
s.scan("Password: *").length.should == 2
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
context "when the default key is not uploaded" do
|
|
353
|
+
before{ stub_one_key('a'); stub_update_key('a') }
|
|
354
|
+
it "should prompt for the new key" do
|
|
355
|
+
should_greet_user
|
|
356
|
+
should_challenge_for(username, password)
|
|
357
|
+
should_write_config
|
|
358
|
+
should_create_an_ssh_keypair
|
|
359
|
+
|
|
360
|
+
input_line 'yes'
|
|
361
|
+
input_line 'a'
|
|
362
|
+
next_stage
|
|
363
|
+
|
|
364
|
+
last_output do |s|
|
|
365
|
+
s.should match(/a \(type: ssh-rsa\)/)
|
|
366
|
+
s.should match("Fingerprint: #{rsa_key_fingerprint_public}")
|
|
367
|
+
s.should match(" name |a|")
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
context "when a multiple keys exist but is not the same" do
|
|
373
|
+
before{ setup_mock_ssh(true) }
|
|
374
|
+
before do
|
|
375
|
+
stub_one_key('a_key')
|
|
376
|
+
stub_add_key_error('invalid```--', 'Invalid key name')
|
|
377
|
+
stub_add_key('another_key')
|
|
378
|
+
end
|
|
379
|
+
it "should give the user a name the key" do
|
|
380
|
+
should_greet_user
|
|
381
|
+
should_challenge_for(username, password)
|
|
382
|
+
should_write_config
|
|
383
|
+
should_not_create_an_ssh_keypair
|
|
384
|
+
|
|
385
|
+
input_line 'yes'
|
|
386
|
+
input_line 'invalid```--'
|
|
387
|
+
input_line 'another_key'
|
|
388
|
+
next_stage
|
|
389
|
+
|
|
390
|
+
last_output do |s|
|
|
391
|
+
s.should match(/a_key \(type: ssh-rsa\)/)
|
|
392
|
+
s.should match("Fingerprint: #{rsa_key_fingerprint_public}")
|
|
393
|
+
s.should match(" name |a_key|")
|
|
394
|
+
s.should match("Invalid key name")
|
|
395
|
+
s.should match("Uploading key 'another_key'")
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
context "when the default key already exists on the server" do
|
|
400
|
+
before{ setup_mock_ssh(true) }
|
|
401
|
+
before{ stub_mock_ssh_keys }
|
|
402
|
+
|
|
403
|
+
it "should prompt for the new key" do
|
|
404
|
+
should_greet_user
|
|
405
|
+
should_challenge_for(username, password)
|
|
406
|
+
should_write_config
|
|
407
|
+
should_not_create_an_ssh_keypair
|
|
408
|
+
should_find_matching_server_key
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
context "with login and existing domain and app" do
|
|
414
|
+
let(:default_options){ {:rhlogin => username, :server => mock_uri} }
|
|
415
|
+
subject{ RHC::RerunWizard.new(config, options) }
|
|
416
|
+
|
|
417
|
+
before do
|
|
418
|
+
stub_api false
|
|
419
|
+
challenge{ stub_user }
|
|
420
|
+
stub_no_keys
|
|
421
|
+
stub_add_key
|
|
422
|
+
stub_api_request(:post, 'broker/rest/domains', user_auth).
|
|
423
|
+
with(:body => /(thisnamespaceistoobig|invalidnamespace)/).
|
|
424
|
+
to_return({
|
|
425
|
+
:status => 409,
|
|
426
|
+
:body => {
|
|
427
|
+
:messages => [{:field => 'id', :severity => 'ERROR', :text => 'Too long', :exit_code => 123}]
|
|
428
|
+
}.to_json
|
|
429
|
+
})
|
|
430
|
+
challenge{ stub_one_domain('testnamespace') }
|
|
431
|
+
stub_one_application('testnamespace', 'test1')
|
|
432
|
+
stub_simple_carts
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
it "should skip steps that have already been completed" do
|
|
436
|
+
should_greet_user
|
|
437
|
+
should_challenge_for(nil, password)
|
|
438
|
+
should_write_config
|
|
439
|
+
should_create_an_ssh_keypair
|
|
440
|
+
should_upload_default_key
|
|
441
|
+
should_not_find_git
|
|
442
|
+
should_check_remote_server
|
|
443
|
+
should_find_a_namespace('testnamespace')
|
|
444
|
+
should_find_apps(['test1', 'testnamespace'])
|
|
445
|
+
should_be_done
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
context "with different config" do
|
|
449
|
+
let(:config_option){ setup_different_config }
|
|
450
|
+
let(:default_options){ {:rhlogin => username, :server => mock_uri, :config => config_option} }
|
|
451
|
+
|
|
452
|
+
it "should overwrite the config" do
|
|
453
|
+
should_greet_user
|
|
454
|
+
should_challenge_for(nil, password)
|
|
455
|
+
should_overwrite_config
|
|
456
|
+
end
|
|
457
|
+
end
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
context "with SSHWizard" do
|
|
461
|
+
let(:default_options){ {:rhlogin => username, :password => password} }
|
|
462
|
+
let(:auth){ RHC::Auth::Basic.new(options) }
|
|
463
|
+
let(:rest_client){ RHC::Rest::Client.new(:server => mock_uri, :auth => auth) }
|
|
464
|
+
subject{ RHC::SSHWizard.new(rest_client, config, options) }
|
|
465
|
+
|
|
466
|
+
before do
|
|
467
|
+
stub_api false
|
|
468
|
+
challenge{ stub_user }
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
context "with no server keys" do
|
|
472
|
+
before{ stub_no_keys }
|
|
473
|
+
before{ stub_add_key }
|
|
474
|
+
|
|
475
|
+
it "should generate and upload keys since the user does not have them" do
|
|
476
|
+
input_line "yes"
|
|
477
|
+
input_line 'default'
|
|
478
|
+
input_line ""
|
|
479
|
+
|
|
480
|
+
should_create_an_ssh_keypair
|
|
481
|
+
should_upload_default_key
|
|
482
|
+
|
|
483
|
+
#last_output.should match("Uploading key 'default'")
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
context "with default keys created" do
|
|
487
|
+
before{ setup_mock_ssh(true) }
|
|
488
|
+
it "should upload the default key" do
|
|
489
|
+
should_not_create_an_ssh_keypair
|
|
490
|
+
should_upload_default_key
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
context "with the server having the default key" do
|
|
496
|
+
before{ setup_mock_ssh(true) }
|
|
497
|
+
before{ stub_mock_ssh_keys }
|
|
498
|
+
it "should pass through since the user has keys already" do
|
|
499
|
+
subject.run.should be_true
|
|
500
|
+
last_output.should == ""
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
context "Check odds and ends" do
|
|
506
|
+
before(:each) { mock_config }
|
|
507
|
+
let(:wizard){ RerunWizardDriver.new }
|
|
508
|
+
|
|
509
|
+
it "should cause ssh_key_upload? to catch NoMethodError and call the fallback to get the fingerprint" do
|
|
510
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(4).times.and_raise(NoMethodError)
|
|
511
|
+
wizard.should_receive(:ssh_keygen_fallback).exactly(4).times
|
|
512
|
+
wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
|
513
|
+
|
|
514
|
+
wizard.send(:ssh_key_uploaded?)
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it "should cause upload_ssh_key to catch NoMethodError and call the fallback to get the fingerprint" do
|
|
518
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(5).times.and_raise(NoMethodError)
|
|
519
|
+
wizard.stub(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
|
520
|
+
wizard.should_receive(:ssh_keygen_fallback).exactly(5).times.and_return(double(:name => 'default', :fingerprint => 'AA:BB:CC:DD:EE:FF', :type => 'ssh-rsa' ))
|
|
521
|
+
|
|
522
|
+
input_line 'y'
|
|
523
|
+
|
|
524
|
+
wizard.send(:upload_ssh_key_stage).should be_false
|
|
525
|
+
|
|
526
|
+
last_output.should match("Your public SSH key at .* is invalid or unreadable\.")
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
it "should cause upload_ssh_key to catch NotImplementedError and return false" do
|
|
530
|
+
Net::SSH::KeyFactory.should_receive(:load_public_key).exactly(5).times.and_raise(NoMethodError)
|
|
531
|
+
wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
|
532
|
+
|
|
533
|
+
input_line 'y'
|
|
534
|
+
|
|
535
|
+
wizard.send(:upload_ssh_key_stage).should be_false
|
|
536
|
+
|
|
537
|
+
output = last_output
|
|
538
|
+
output.should match("Your public SSH key at .* is invalid or unreadable\.")
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
it "should find a unique name" do
|
|
542
|
+
wizard.should_receive(:ssh_keys).at_least(1).times.and_return(wizard.get_mock_key_data)
|
|
543
|
+
|
|
544
|
+
wizard.send(:find_unique_key_name, 'cb490595').should == 'cb4905951'
|
|
545
|
+
wizard.send(:find_unique_key_name, 'default').should == 'default1'
|
|
546
|
+
wizard.send(:find_unique_key_name, 'abc').should == 'abc'
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
it "should match ssh key fallback fingerprint to net::ssh fingerprint" do
|
|
550
|
+
# we need to write to a live file system so ssh-keygen can find it
|
|
551
|
+
FakeFS.deactivate!
|
|
552
|
+
Dir.mktmpdir do |dir|
|
|
553
|
+
setup_mock_ssh_keys(dir)
|
|
554
|
+
pub_ssh = File.join dir, "id_rsa.pub"
|
|
555
|
+
fallback_fingerprint = wizard.send :ssh_keygen_fallback, pub_ssh
|
|
556
|
+
internal_fingerprint, short_name = wizard.get_key_fingerprint pub_ssh
|
|
557
|
+
|
|
558
|
+
fallback_fingerprint.should == internal_fingerprint
|
|
559
|
+
end
|
|
560
|
+
FakeFS.activate!
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
context "with the first run wizard" do
|
|
564
|
+
let(:wizard){ FirstRunWizardDriver.new }
|
|
565
|
+
|
|
566
|
+
it "prints the exception message when a domain error occurs" do
|
|
567
|
+
msg = "Resource conflict"
|
|
568
|
+
wizard.rest_client.stub(:add_domain) { raise RHC::Rest::ValidationException, msg }
|
|
569
|
+
input_line "testnamespace" # try to add a namespace
|
|
570
|
+
input_line '' # the above input will raise exception.
|
|
571
|
+
# we now skip configuring namespace.
|
|
572
|
+
wizard.send(:ask_for_namespace)
|
|
573
|
+
output = last_output
|
|
574
|
+
output.should match msg
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
it "should update the key correctly" do
|
|
578
|
+
key_name = 'default'
|
|
579
|
+
key_data = wizard.get_mock_key_data
|
|
580
|
+
wizard.ssh_keys = key_data
|
|
581
|
+
wizard.stub(:ssh_key_triple_for_default_key) { pub_key.chomp.split }
|
|
582
|
+
wizard.stub(:fingerprint_for_default_key) { "" } # this value is irrelevant
|
|
583
|
+
wizard.rest_client = double('RestClient').tap{ |o| o.stub(:find_key) { key_data.detect { |k| k.name == key_name } } }
|
|
584
|
+
|
|
585
|
+
wizard.send(:upload_ssh_key, key_name)
|
|
586
|
+
output = last_output
|
|
587
|
+
output.should match 'Updating'
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
it 'should pick a usable SSH key name' do
|
|
591
|
+
File.exists?('1').should be_false
|
|
592
|
+
key_name = 'default'
|
|
593
|
+
key_data = wizard.get_mock_key_data
|
|
594
|
+
Socket.stub(:gethostname) { key_name }
|
|
595
|
+
input_line("\n") # to accept default key name
|
|
596
|
+
wizard.ssh_keys = key_data
|
|
597
|
+
wizard.stub(:ssh_key_triple_for_default_key) { pub_key.chomp.split }
|
|
598
|
+
wizard.stub(:fingerprint_for_default_key) { "" } # this value is irrelevant
|
|
599
|
+
wizard.rest_client = double('RestClient').tap{ |o| o.stub(:add_key) { true } }
|
|
600
|
+
|
|
601
|
+
wizard.send(:upload_ssh_key, "other")
|
|
602
|
+
output = last_output
|
|
603
|
+
# since the clashing key name is short, we expect to present
|
|
604
|
+
# a key name with "1" attached to it.
|
|
605
|
+
output.should match "|" + key_name + "1" + "|"
|
|
606
|
+
File.exists?('1').should be_false
|
|
607
|
+
end
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
module WizardDriver
|
|
613
|
+
|
|
614
|
+
attr_accessor :mock_user, :rest_client
|
|
615
|
+
def initialize(*args)
|
|
616
|
+
if args.empty?
|
|
617
|
+
args = [RHC::Config.new, Commander::Command::Options.new]
|
|
618
|
+
args[1].default(args[0].to_options)
|
|
619
|
+
end
|
|
620
|
+
super *args
|
|
621
|
+
raise "No options" if options.nil?
|
|
622
|
+
@mock_user = 'mock_user@foo.bar'
|
|
623
|
+
@current_wizard_stage = nil
|
|
624
|
+
@platform_windows = false
|
|
625
|
+
#self.stub(:openshift_server).and_return('fake.foo')
|
|
626
|
+
end
|
|
627
|
+
|
|
628
|
+
def run_next_stage
|
|
629
|
+
if @current_wizard_stage.nil?
|
|
630
|
+
@current_wizard_stage = 0
|
|
631
|
+
else
|
|
632
|
+
return false if @current_wizard_stage >= stages.length + 1
|
|
633
|
+
@current_wizard_stage += 1
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
self.send stages[@current_wizard_stage]
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
# Set up @rest_client so that we can stub subsequent REST calls
|
|
640
|
+
def stub_rhc_client_new
|
|
641
|
+
@rest_client = RestSpecHelper::MockRestClient.new
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
def setup_mock_config(rhlogin=@mock_user)
|
|
645
|
+
FileUtils.mkdir_p File.dirname(RHC::Config.local_config_path)
|
|
646
|
+
File.open(RHC::Config.local_config_path, "w") do |file|
|
|
647
|
+
file.puts <<EOF
|
|
648
|
+
# Default user login
|
|
649
|
+
default_rhlogin='#{rhlogin}'
|
|
650
|
+
|
|
651
|
+
# Server API
|
|
652
|
+
libra_server = '#{openshift_server}'
|
|
653
|
+
EOF
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
# reload config
|
|
657
|
+
@config = RHC::Config.initialize
|
|
658
|
+
RHC::Config.ssh_dir.should =~ /mock_user/
|
|
659
|
+
@config.ssh_dir.should =~ /mock_user/
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
def setup_mock_domain_and_applications(domain, apps = {})
|
|
663
|
+
stub_rhc_client_new
|
|
664
|
+
apps_ary = []
|
|
665
|
+
apps.each do |app, url|
|
|
666
|
+
apps_ary.push OpenStruct.new(
|
|
667
|
+
:name => app,
|
|
668
|
+
:app_url => url == :default ? "http://#{app}-#{domain}.#{openshift_server}/" : url,
|
|
669
|
+
:u => true
|
|
670
|
+
)
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
@rest_client.stub(:domains) {
|
|
674
|
+
[OpenStruct.new(:id => domain, :applications => apps_ary)]
|
|
675
|
+
}
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
def windows=(bool)
|
|
679
|
+
@platform_windows = bool
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
def windows?
|
|
683
|
+
@platform_windows
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
def get_key_fingerprint(path=RHC::Config.ssh_pub_key_file_path)
|
|
687
|
+
# returns the fingerprint and the short name used as the default
|
|
688
|
+
# key name
|
|
689
|
+
fingerprint = Net::SSH::KeyFactory.load_public_key(path).fingerprint
|
|
690
|
+
short_name = fingerprint[0, 12].gsub(/[^0-9a-zA-Z]/,'')
|
|
691
|
+
return fingerprint, short_name
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
def ssh_keys=(data)
|
|
695
|
+
@ssh_keys = data
|
|
696
|
+
end
|
|
697
|
+
|
|
698
|
+
class Sshkey < OpenStruct
|
|
699
|
+
def update(type, content)
|
|
700
|
+
self.type = type
|
|
701
|
+
self.content = content
|
|
702
|
+
end
|
|
703
|
+
def type
|
|
704
|
+
@table[:type]
|
|
705
|
+
end
|
|
706
|
+
def type=(type)
|
|
707
|
+
@table[:type] = type
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
|
|
711
|
+
def get_mock_key_data
|
|
712
|
+
[
|
|
713
|
+
Sshkey.new(:name => 'default', :type => 'ssh-rsa', :fingerprint => "0f:97:4b:82:87:bb:c6:dc:40:a3:c1:bc:bb:55:1e:fa"),
|
|
714
|
+
Sshkey.new(:name => 'cb490595', :type => 'ssh-rsa', :fingerprint => "cb:49:05:95:b4:42:1c:95:74:f7:2d:41:0d:f0:37:3b"),
|
|
715
|
+
Sshkey.new(:name => '96d90241', :type => 'ssh-rsa', :fingerprint => "96:d9:02:41:e1:cb:0d:ce:e5:3b:fc:da:13:65:3e:32"),
|
|
716
|
+
Sshkey.new(:name => '73ce2cc1', :type => 'ssh-rsa', :fingerprint => "73:ce:2c:c1:01:ea:79:cc:f6:be:86:45:67:96:7f:e3")
|
|
717
|
+
]
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
def config_path
|
|
721
|
+
config.path
|
|
722
|
+
end
|
|
723
|
+
def openshift_server
|
|
724
|
+
super
|
|
725
|
+
end
|
|
726
|
+
# def config(local_conf_path=nil)
|
|
727
|
+
# @config.set_local_config(local_conf_path, false) if local_conf_path
|
|
728
|
+
# @config
|
|
729
|
+
# end
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
class FirstRunWizardDriver < RHC::Wizard
|
|
733
|
+
include WizardDriver
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
class RerunWizardDriver < RHC::RerunWizard
|
|
737
|
+
include WizardDriver
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
class SSHWizardDriver < RHC::SSHWizard
|
|
741
|
+
include WizardDriver
|
|
742
|
+
|
|
743
|
+
def initialize
|
|
744
|
+
super RestSpecHelper::MockRestClient.new, RHC::Config.new, Commander::Command::Options.new
|
|
745
|
+
end
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
describe RHC::DomainWizard do
|
|
750
|
+
context "with a rest client" do
|
|
751
|
+
let(:rest_client){ double }
|
|
752
|
+
it{ described_class.new(nil, nil, rest_client).rest_client.should == rest_client }
|
|
753
|
+
it{ subject.stages == [:config_namespace_stage] }
|
|
754
|
+
it{ expect{ described_class.new(nil, nil, rest_client).send(:config_namespace, '') }.to call(:add_domain).on(rest_client).and_stop }
|
|
755
|
+
end
|
|
756
|
+
end
|