rhc 1.6.8 → 1.7.8
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.
- data/autocomplete/rhc_bash +1167 -0
- data/features/README.md +1 -1
- data/features/domain.feature +1 -1
- data/features/lib/rhc_helper/persistable.rb +4 -1
- data/features/multiple_cartridge.feature +4 -3
- data/features/sshkey.feature +3 -3
- data/features/support/assumptions.rb +3 -3
- data/features/support/env.rb +10 -0
- data/features/support/platform_support.rb +2 -2
- data/lib/rhc.rb +6 -0
- data/lib/rhc/auth/token.rb +4 -0
- data/lib/rhc/autocomplete.rb +50 -52
- data/lib/rhc/autocomplete_templates/{rhc.erb → bash.erb} +8 -2
- data/lib/rhc/cartridge_helpers.rb +1 -1
- data/lib/rhc/cli.rb +1 -7
- data/lib/rhc/command_runner.rb +45 -16
- data/lib/rhc/commands.rb +75 -55
- data/lib/rhc/commands/account.rb +7 -51
- data/lib/rhc/commands/alias.rb +26 -17
- data/lib/rhc/commands/app.rb +75 -39
- data/lib/rhc/commands/authorization.rb +4 -2
- data/lib/rhc/commands/base.rb +31 -29
- data/lib/rhc/commands/cartridge.rb +66 -44
- data/lib/rhc/commands/domain.rb +20 -8
- data/lib/rhc/commands/git_clone.rb +3 -3
- data/lib/rhc/commands/logout.rb +51 -0
- data/lib/rhc/commands/port_forward.rb +15 -11
- data/lib/rhc/commands/setup.rb +25 -0
- data/lib/rhc/commands/snapshot.rb +20 -10
- data/lib/rhc/commands/sshkey.rb +21 -7
- data/lib/rhc/commands/tail.rb +2 -2
- data/lib/rhc/commands/threaddump.rb +2 -2
- data/lib/rhc/context_helper.rb +0 -4
- data/lib/rhc/core_ext.rb +96 -76
- data/lib/rhc/exceptions.rb +6 -0
- data/lib/rhc/help_formatter.rb +19 -2
- data/lib/rhc/helpers.rb +32 -194
- data/lib/rhc/highline_extensions.rb +412 -0
- data/lib/rhc/output_helpers.rb +31 -67
- data/lib/rhc/rest.rb +4 -2
- data/lib/rhc/rest/alias.rb +0 -2
- data/lib/rhc/rest/application.rb +9 -4
- data/lib/rhc/rest/authorization.rb +0 -2
- data/lib/rhc/rest/base.rb +1 -1
- data/lib/rhc/rest/client.rb +11 -9
- data/lib/rhc/rest/domain.rb +5 -1
- data/lib/rhc/rest/gear_group.rb +0 -2
- data/lib/rhc/rest/key.rb +0 -2
- data/lib/rhc/rest/mock.rb +32 -10
- data/lib/rhc/ssh_helpers.rb +2 -2
- data/lib/rhc/usage_templates/command_help.erb +20 -13
- data/lib/rhc/usage_templates/command_syntax_help.erb +1 -3
- data/lib/rhc/usage_templates/help.erb +15 -16
- data/lib/rhc/usage_templates/options_help.erb +7 -9
- data/lib/rhc/wizard.rb +193 -159
- data/spec/rest_spec_helper.rb +2 -2
- data/spec/rhc/cli_spec.rb +36 -5
- data/spec/rhc/command_spec.rb +94 -42
- data/spec/rhc/commands/account_spec.rb +1 -75
- data/spec/rhc/commands/alias_spec.rb +28 -28
- data/spec/rhc/commands/app_spec.rb +141 -33
- data/spec/rhc/commands/apps_spec.rb +4 -4
- data/spec/rhc/commands/authorization_spec.rb +8 -8
- data/spec/rhc/commands/cartridge_spec.rb +18 -9
- data/spec/rhc/commands/domain_spec.rb +16 -16
- data/spec/rhc/commands/git_clone_spec.rb +3 -3
- data/spec/rhc/commands/logout_spec.rb +86 -0
- data/spec/rhc/commands/port_forward_spec.rb +9 -9
- data/spec/rhc/commands/server_spec.rb +5 -5
- data/spec/rhc/commands/setup_spec.rb +19 -5
- data/spec/rhc/commands/snapshot_spec.rb +12 -12
- data/spec/rhc/commands/sshkey_spec.rb +11 -11
- data/spec/rhc/commands/tail_spec.rb +5 -5
- data/spec/rhc/commands/threaddump_spec.rb +3 -3
- data/spec/rhc/config_spec.rb +6 -6
- data/spec/rhc/helpers_spec.rb +72 -219
- data/spec/rhc/highline_extensions_spec.rb +269 -0
- data/spec/rhc/rest_application_spec.rb +28 -1
- data/spec/rhc/rest_client_spec.rb +20 -21
- data/spec/rhc/rest_spec.rb +10 -0
- data/spec/rhc/wizard_spec.rb +72 -32
- data/spec/spec_helper.rb +86 -56
- data/spec/wizard_spec_helper.rb +7 -4
- metadata +165 -160
- data/spec/spec.opts +0 -1
data/lib/rhc/rest.rb
CHANGED
@@ -19,7 +19,7 @@ module RHC
|
|
19
19
|
attr_reader :code
|
20
20
|
def initialize(message=nil, code=1)
|
21
21
|
super(message)
|
22
|
-
@code = (Integer(code) rescue
|
22
|
+
@code = (Integer(code) rescue nil)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -68,7 +68,7 @@ module RHC
|
|
68
68
|
#Exceptions thrown in case of an HTTP 422 is received.
|
69
69
|
class ValidationException < ClientErrorException
|
70
70
|
attr_reader :field
|
71
|
-
def initialize(message, field=nil, error_code=
|
71
|
+
def initialize(message, field=nil, error_code=1)
|
72
72
|
super(message, error_code)
|
73
73
|
@field = field
|
74
74
|
end
|
@@ -113,6 +113,8 @@ module RHC
|
|
113
113
|
|
114
114
|
class MultipleCartridgeCreationNotSupported < Exception; end
|
115
115
|
|
116
|
+
class InitialGitUrlNotSupported < Exception; end
|
117
|
+
|
116
118
|
class SslCertificatesNotSupported < Exception; end
|
117
119
|
|
118
120
|
class AuthorizationsNotSupported < Exception
|
data/lib/rhc/rest/alias.rb
CHANGED
data/lib/rhc/rest/application.rb
CHANGED
@@ -106,10 +106,15 @@ module RHC
|
|
106
106
|
|
107
107
|
def aliases
|
108
108
|
debug "Getting all aliases for application #{name}"
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
109
|
+
@aliases ||= begin
|
110
|
+
aliases = attributes['aliases']
|
111
|
+
if aliases.nil? or not aliases.is_a?(Array)
|
112
|
+
supports?('LIST_ALIASES') ? rest_method("LIST_ALIASES") : []
|
113
|
+
else
|
114
|
+
aliases.map do |a|
|
115
|
+
Alias.new(a.is_a?(String) ? {'id' => a} : a, client)
|
116
|
+
end
|
117
|
+
end
|
113
118
|
end
|
114
119
|
end
|
115
120
|
|
data/lib/rhc/rest/base.rb
CHANGED
data/lib/rhc/rest/client.rb
CHANGED
@@ -199,14 +199,6 @@ module RHC
|
|
199
199
|
# See #api_version_negotiated
|
200
200
|
CLIENT_API_VERSIONS = [1.1, 1.2, 1.3, 1.4]
|
201
201
|
|
202
|
-
# Set the http_proxy env variable, read by
|
203
|
-
# HTTPClient, being sure to add the http protocol
|
204
|
-
# if not specified already
|
205
|
-
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
206
|
-
if proxy && proxy !~ /^(\w+):\/\// then
|
207
|
-
ENV['http_proxy'] = "http://#{proxy}"
|
208
|
-
end
|
209
|
-
|
210
202
|
def initialize(*args)
|
211
203
|
options = args[0].is_a?(Hash) && args[0] || {}
|
212
204
|
@end_point, @debug, @preferred_api_versions =
|
@@ -237,6 +229,8 @@ module RHC
|
|
237
229
|
self.headers.merge!(options.delete(:headers)) if options[:headers]
|
238
230
|
self.options.merge!(options)
|
239
231
|
|
232
|
+
update_http_proxy_env
|
233
|
+
|
240
234
|
debug "Connecting to #{@end_point}"
|
241
235
|
end
|
242
236
|
|
@@ -266,7 +260,7 @@ module RHC
|
|
266
260
|
auth = options[:auth] || self.auth
|
267
261
|
response = nil
|
268
262
|
|
269
|
-
debug "Request #{args[0].to_s.upcase} #{args[1]}" if debug?
|
263
|
+
debug "Request #{args[0].to_s.upcase} #{args[1]}#{"?#{args[2].map{|a| a.join('=')}.join(' ')}" if args[2] && args[0] == 'GET'}" if debug?
|
270
264
|
time = Benchmark.realtime{ response = client.request(*(args << true)) }
|
271
265
|
debug " code %s %4i ms" % [response.status, (time*1000).to_i] if debug? && response
|
272
266
|
|
@@ -598,6 +592,14 @@ module RHC
|
|
598
592
|
keys = messages.group_by{ |m| m['field'] }.keys.compact.sort.map(&:to_sym) rescue []
|
599
593
|
[messages_to_error(messages), keys]
|
600
594
|
end
|
595
|
+
|
596
|
+
def update_http_proxy_env
|
597
|
+
# Set the http_proxy env variable, read by
|
598
|
+
# HTTPClient, being sure to add the http protocol
|
599
|
+
# if not specified already
|
600
|
+
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
601
|
+
ENV['http_proxy'] = "http://#{proxy}" if proxy && proxy !~ /^(\w+):\/\//
|
602
|
+
end
|
601
603
|
end
|
602
604
|
end
|
603
605
|
end
|
data/lib/rhc/rest/domain.rb
CHANGED
@@ -16,13 +16,17 @@ module RHC
|
|
16
16
|
options.each{ |key, value| payload[key.to_sym] = value }
|
17
17
|
|
18
18
|
cartridges = Array(payload.delete(:cartridge)).concat(Array(payload.delete(:cartridges))).compact.uniq
|
19
|
-
if
|
19
|
+
if client.api_version_negotiated >= 1.3
|
20
20
|
payload[:cartridges] = cartridges
|
21
21
|
else
|
22
22
|
raise RHC::Rest::MultipleCartridgeCreationNotSupported, "The server only supports creating an application with a single web cartridge." if cartridges.length > 1
|
23
23
|
payload[:cartridge] = cartridges.first
|
24
24
|
end
|
25
25
|
|
26
|
+
if client.api_version_negotiated < 1.3 && payload[:initial_git_url]
|
27
|
+
raise RHC::Rest::InitialGitUrlNotSupported, "The server does not support creating applications from a source repository."
|
28
|
+
end
|
29
|
+
|
26
30
|
options = {:timeout => options[:scale] && 0 || nil}
|
27
31
|
rest_method "ADD_APPLICATION", payload, options
|
28
32
|
end
|
data/lib/rhc/rest/gear_group.rb
CHANGED
data/lib/rhc/rest/key.rb
CHANGED
data/lib/rhc/rest/mock.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require "rhc/rest"
|
2
|
-
|
3
1
|
module RHC::Rest::Mock
|
4
2
|
|
5
3
|
def self.start
|
@@ -70,9 +68,9 @@ module RHC::Rest::Mock
|
|
70
68
|
def stub_user(auth=mock_user_auth)
|
71
69
|
stub_api_request(:get, 'broker/rest/user', auth).to_return(simple_user(username))
|
72
70
|
end
|
73
|
-
def
|
71
|
+
def stub_add_key(name='default')
|
74
72
|
stub_api_request(:post, 'broker/rest/user/keys', mock_user_auth).
|
75
|
-
with(:body => hash_including({:name =>
|
73
|
+
with(:body => hash_including({:name => name, :type => 'ssh-rsa'})).
|
76
74
|
to_return({:status => 201, :body => {}.to_json})
|
77
75
|
end
|
78
76
|
def stub_update_key(name)
|
@@ -80,6 +78,11 @@ module RHC::Rest::Mock
|
|
80
78
|
with(:body => hash_including({:type => 'ssh-rsa'})).
|
81
79
|
to_return({:status => 200, :body => {}.to_json})
|
82
80
|
end
|
81
|
+
def stub_add_key_error(name, message, code=422)
|
82
|
+
stub_api_request(:post, "broker/rest/user/keys", mock_user_auth).
|
83
|
+
with(:body => hash_including({:type => 'ssh-rsa'})).
|
84
|
+
to_return({:status => code, :body => {:messages => [{:text => message, :field => 'name', :severity => 'error'}]}.to_json})
|
85
|
+
end
|
83
86
|
def stub_create_domain(name)
|
84
87
|
stub_api_request(:post, 'broker/rest/domains', mock_user_auth).
|
85
88
|
with(:body => hash_including({:id => name})).
|
@@ -117,7 +120,7 @@ module RHC::Rest::Mock
|
|
117
120
|
to_return(new_authorization(params))
|
118
121
|
end
|
119
122
|
def stub_no_keys
|
120
|
-
stub_api_request(:get, 'broker/rest/user/keys', mock_user_auth).to_return(
|
123
|
+
stub_api_request(:get, 'broker/rest/user/keys', mock_user_auth).to_return(empty_keys)
|
121
124
|
end
|
122
125
|
def stub_mock_ssh_keys(name='test')
|
123
126
|
stub_api_request(:get, 'broker/rest/user/keys', mock_user_auth).
|
@@ -156,7 +159,7 @@ module RHC::Rest::Mock
|
|
156
159
|
})
|
157
160
|
end
|
158
161
|
def stub_no_domains
|
159
|
-
stub_api_request(:get, 'broker/rest/domains', mock_user_auth).to_return(
|
162
|
+
stub_api_request(:get, 'broker/rest/domains', mock_user_auth).to_return(empty_domains)
|
160
163
|
end
|
161
164
|
def stub_one_domain(name)
|
162
165
|
stub_api_request(:get, 'broker/rest/domains', mock_user_auth).
|
@@ -218,10 +221,10 @@ module RHC::Rest::Mock
|
|
218
221
|
EOM
|
219
222
|
end
|
220
223
|
|
221
|
-
def
|
224
|
+
def empty_keys
|
222
225
|
empty_response_list('keys')
|
223
226
|
end
|
224
|
-
def
|
227
|
+
def empty_domains
|
225
228
|
empty_response_list('domains')
|
226
229
|
end
|
227
230
|
|
@@ -411,6 +414,20 @@ module RHC::Rest::Mock
|
|
411
414
|
}
|
412
415
|
end
|
413
416
|
|
417
|
+
def mock_alias_response(count=1)
|
418
|
+
aliases = count.times.inject([]) do |arr, i|
|
419
|
+
arr << {:id => "www.alias#{i}.com"}
|
420
|
+
end
|
421
|
+
|
422
|
+
return {
|
423
|
+
:body => {
|
424
|
+
:type => count == 1 ? 'alias' : 'aliases',
|
425
|
+
:data => aliases
|
426
|
+
}.to_json,
|
427
|
+
:status => 200
|
428
|
+
}
|
429
|
+
end
|
430
|
+
|
414
431
|
def mock_gear_groups_response()
|
415
432
|
groups = [{}]
|
416
433
|
type = 'gear_groups'
|
@@ -428,7 +445,7 @@ module RHC::Rest::Mock
|
|
428
445
|
class MockRestClient < RHC::Rest::Client
|
429
446
|
include Helpers
|
430
447
|
|
431
|
-
def initialize(config=RHC::Config)
|
448
|
+
def initialize(config=RHC::Config, version=1.0)
|
432
449
|
obj = self
|
433
450
|
if RHC::Rest::Client.respond_to?(:stub)
|
434
451
|
RHC::Rest::Client.stub(:new) { obj }
|
@@ -443,6 +460,7 @@ module RHC::Rest::Mock
|
|
443
460
|
@domains = []
|
444
461
|
@user = MockRestUser.new(client, config.username)
|
445
462
|
@api = MockRestApi.new(client, config)
|
463
|
+
@version = version
|
446
464
|
end
|
447
465
|
|
448
466
|
def api
|
@@ -457,6 +475,10 @@ module RHC::Rest::Mock
|
|
457
475
|
@domains
|
458
476
|
end
|
459
477
|
|
478
|
+
def api_version_negotiated
|
479
|
+
@version
|
480
|
+
end
|
481
|
+
|
460
482
|
def cartridges
|
461
483
|
premium_embedded = MockRestCartridge.new(self, "premium_cart", "embedded")
|
462
484
|
premium_embedded.usage_rate = 0.05
|
@@ -618,7 +640,7 @@ module RHC::Rest::Mock
|
|
618
640
|
end
|
619
641
|
end
|
620
642
|
|
621
|
-
def destroy
|
643
|
+
def destroy
|
622
644
|
puts @application.inspect
|
623
645
|
puts self.inspect
|
624
646
|
@application.aliases.delete self
|
data/lib/rhc/ssh_helpers.rb
CHANGED
@@ -127,7 +127,7 @@ module RHC
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def fingerprint_for_default_key
|
130
|
-
fingerprint_for_local_key
|
130
|
+
fingerprint_for_local_key(RHC::Config.ssh_pub_key_file_path)
|
131
131
|
end
|
132
132
|
|
133
133
|
# for an SSH public key specified by 'key', return a triple
|
@@ -144,7 +144,7 @@ module RHC
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def ssh_key_triple_for_default_key
|
147
|
-
ssh_key_triple_for
|
147
|
+
ssh_key_triple_for(RHC::Config.ssh_pub_key_file_path)
|
148
148
|
end
|
149
149
|
|
150
150
|
private
|
@@ -4,27 +4,34 @@ Usage: <%= Array(program :name).first %> <%= @command.name %> <%= @command.synta
|
|
4
4
|
<% if @actions.blank? -%>
|
5
5
|
<% unless @command.options.blank? or @command.options.all?{ |o| o[:hide] } -%>
|
6
6
|
|
7
|
-
Options
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
Options
|
8
|
+
<%= table(
|
9
|
+
@command.options.select do |opt|
|
10
|
+
not opt[:hide]
|
11
|
+
end.map do |opt|
|
12
|
+
[opt[:switches].join(', '), opt[:description]]
|
13
|
+
end,
|
14
|
+
table_args(' ', 25)
|
15
|
+
).join("\n") %>
|
11
16
|
<% end -%>
|
12
17
|
|
13
18
|
Global Options
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
<%= table(
|
20
|
+
@global_options.select do |opt|
|
21
|
+
not (opt[:hide] || @command.options.any?{ |o| (o[:switches] & opt[:switches]).present? })
|
22
|
+
end.map do |opt|
|
23
|
+
[opt[:switches].join(', '), opt[:description]]
|
24
|
+
end,
|
25
|
+
table_args(' ', 25)
|
26
|
+
).join("\n") %>
|
19
27
|
|
28
|
+
See 'rhc help options' for a full list of global options.
|
20
29
|
<% else -%>
|
21
30
|
|
22
31
|
List of Actions
|
23
|
-
|
24
|
-
<%= "%-18s %s\n" % [action[:name], action[:summary]] -%>
|
25
|
-
<% end -%>
|
32
|
+
<%= table(@actions.map{ |a| [a[:name], a[:summary]] }, table_args(' ', 13)).join("\n") %>
|
26
33
|
<% if @command.default_action? -%>
|
27
34
|
|
28
35
|
The default action for this resource is '<%= @command.default_action %>'
|
29
36
|
<% end -%>
|
30
|
-
<% end -%>
|
37
|
+
<% end -%>
|
@@ -5,7 +5,5 @@ Pass '--help' to see the full list of options
|
|
5
5
|
<% unless @actions.nil? or @actions.empty? -%>
|
6
6
|
|
7
7
|
List of Actions
|
8
|
-
|
9
|
-
<%= "%-18s %s\n" % [action[:name], action[:summary]] -%>
|
10
|
-
<% end -%>
|
8
|
+
<%= table(@actions.map{ |a| [a[:name], a[:summary]] }, table_args(' ', 18)).join("\n") %>
|
11
9
|
<% end -%>
|
@@ -3,34 +3,33 @@ Usage: rhc [--help] [--version] [--debug] <command> [<args>]
|
|
3
3
|
<%= Array(program :description).first %>
|
4
4
|
|
5
5
|
<%
|
6
|
-
remaining = Hash[
|
7
|
-
basic = remaining.slice!('setup', 'app
|
6
|
+
remaining = Hash[commands.dup.select{ |name, command| not command.summary.blank? }]
|
7
|
+
basic = remaining.slice!('setup', 'create-app', 'apps', 'cartridges', 'add-cartridge', 'server', 'logout')
|
8
|
+
remaining.delete_if{ |name, command| alias?(name) }
|
8
9
|
begin -%>
|
9
10
|
Getting started:
|
10
|
-
|
11
|
-
|
12
|
-
<%
|
13
|
-
<% end unless basic.empty?
|
11
|
+
<%= table(basic.map{ |arr| arr[1] = arr[1].summary || arr[1].description; arr }, table_args(' ', 18)).join("\n") %>
|
12
|
+
<% end unless basic.empty? %>
|
13
|
+
<%
|
14
14
|
|
15
15
|
debugging = remaining.slice!('app restart', 'app show', 'tail', 'port-forward', 'threaddump', 'snapshot', 'git-clone')
|
16
16
|
begin -%>
|
17
17
|
Working with apps:
|
18
|
-
|
19
|
-
|
20
|
-
<% end
|
21
|
-
end unless debugging.empty?
|
22
|
-
%>
|
18
|
+
<%= table(debugging.map{ |arr| arr[1] = arr[1].summary || arr[1].description; arr }, table_args(' ', 18)).join("\n") %>
|
19
|
+
<% end unless debugging.empty? %>
|
23
20
|
Management commands:
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
<%= table(remaining.sort.select{ |arr| arr[1].root? and arr[1].summary.present? }.map do |arr|
|
22
|
+
arr[1] = arr[1].summary || arr[1].description
|
23
|
+
arr
|
24
|
+
end, table_args(' ', 18)).join("\n") %>
|
27
25
|
|
28
|
-
|
26
|
+
Some management commands have nested actions - run 'rhc help <command>' for more info.
|
29
27
|
|
28
|
+
See '<%= Array(program :name).first %> help <command>' for more information on a specific command. You can see a list of all commands with 'rhc help commands'. See 'rhc help options' for a list of global command-line options and information about the config file.
|
30
29
|
<% if program :help -%>
|
31
30
|
<% for title, body in program(:help) %>
|
32
31
|
<%= $terminal.color title.to_s.upcase, :bold %>:
|
33
32
|
|
34
33
|
<%= body %>
|
35
34
|
<% end -%>
|
36
|
-
<% end -%>
|
35
|
+
<% end -%>
|
@@ -1,14 +1,12 @@
|
|
1
1
|
The following options can be passed to any command:
|
2
2
|
|
3
|
-
|
4
|
-
<%= "%-25s %s\n" % [option[:switches].join(', '), option[:description]] -%>
|
5
|
-
<% end -%>
|
3
|
+
<%= table(options.map{ |option| [option[:switches].join(', '), option[:description]] }, table_args(' ', 26)).join("\n") %>
|
6
4
|
|
7
5
|
The following configuration options are stored in the <%= RHC::Helpers.system_path('.openshift/express.conf') %> file in your home directory. Passing any of these options to 'rhc setup' will save that value to the file:
|
8
6
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
7
|
+
<%= table(
|
8
|
+
RHC::Config::OPTIONS.select{ |key,value| not value.nil? }.map do |key,value|
|
9
|
+
["--#{key.to_s.gsub('_','-')}", value[0] || key]
|
10
|
+
end,
|
11
|
+
table_args(' ', 26).merge(:header => ['Option', 'In Config'])
|
12
|
+
).join("\n") -%>
|
data/lib/rhc/wizard.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'rhc'
|
2
|
-
require 'highline/system_extensions'
|
3
2
|
require 'fileutils'
|
4
3
|
require 'socket'
|
5
4
|
|
@@ -13,16 +12,26 @@ module RHC
|
|
13
12
|
|
14
13
|
DEFAULT_MAX_LENGTH = 16
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
15
|
+
CONFIG_STAGES = [
|
16
|
+
:login_stage,
|
17
|
+
:create_config_stage,
|
18
|
+
]
|
19
|
+
KEY_STAGES = [
|
20
|
+
:config_ssh_key_stage,
|
21
|
+
:upload_ssh_key_stage,
|
22
|
+
]
|
23
|
+
TEST_STAGES = [
|
24
|
+
:install_client_tools_stage,
|
25
|
+
:setup_test_stage,
|
26
|
+
]
|
27
|
+
NAMESPACE_STAGES = [
|
28
|
+
:config_namespace_stage,
|
29
|
+
]
|
30
|
+
APP_STAGES = [
|
31
|
+
:show_app_info_stage,
|
32
|
+
]
|
33
|
+
STAGES = [:greeting_stage] + CONFIG_STAGES + KEY_STAGES + TEST_STAGES + NAMESPACE_STAGES + APP_STAGES + [:finalize_stage]
|
34
|
+
|
26
35
|
def stages
|
27
36
|
STAGES
|
28
37
|
end
|
@@ -58,55 +67,64 @@ module RHC
|
|
58
67
|
end
|
59
68
|
|
60
69
|
protected
|
61
|
-
include RHC::Helpers
|
62
|
-
include RHC::SSHHelpers
|
63
|
-
include RHC::GitHelpers
|
64
|
-
include RHC::CartridgeHelpers
|
65
|
-
attr_reader :config, :options
|
66
|
-
attr_accessor :auth, :user
|
67
|
-
|
68
|
-
def openshift_server
|
69
|
-
options.server || config['libra_server'] || "openshift.redhat.com"
|
70
|
-
end
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
include RHC::Helpers
|
72
|
+
include RHC::SSHHelpers
|
73
|
+
include RHC::GitHelpers
|
74
|
+
include RHC::CartridgeHelpers
|
75
|
+
attr_reader :config, :options
|
76
|
+
attr_accessor :auth, :user
|
77
|
+
attr_writer :rest_client
|
77
78
|
|
78
|
-
|
79
|
-
|
80
|
-
|
79
|
+
def debug?
|
80
|
+
@debug
|
81
|
+
end
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
def hostname
|
84
|
+
Socket.gethostname
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
87
|
+
def openshift_server
|
88
|
+
options.server || config['libra_server'] || "openshift.redhat.com"
|
89
|
+
end
|
90
|
+
|
91
|
+
def new_client_for_options
|
92
|
+
client_from_options({
|
93
|
+
:auth => auth,
|
94
|
+
})
|
95
|
+
end
|
96
|
+
|
97
|
+
def core_auth
|
98
|
+
@core_auth ||= RHC::Auth::Basic.new(options)
|
99
|
+
end
|
100
|
+
|
101
|
+
def token_auth
|
102
|
+
RHC::Auth::Token.new(options, core_auth, token_store)
|
103
|
+
end
|
104
|
+
|
105
|
+
def auth(reset=false)
|
106
|
+
@auth = nil if reset
|
107
|
+
@auth ||= begin
|
108
|
+
if options.token
|
109
|
+
token_auth
|
110
|
+
else
|
111
|
+
core_auth
|
94
112
|
end
|
95
|
-
|
113
|
+
end
|
114
|
+
end
|
96
115
|
|
97
|
-
|
98
|
-
|
99
|
-
|
116
|
+
def token_store
|
117
|
+
@token_store ||= RHC::Auth::TokenStore.new(config.home_conf_path)
|
118
|
+
end
|
100
119
|
|
101
|
-
|
102
|
-
|
103
|
-
|
120
|
+
def username
|
121
|
+
options.rhlogin || (auth.username if auth.respond_to?(:username))
|
122
|
+
end
|
104
123
|
|
105
|
-
|
106
|
-
|
107
|
-
|
124
|
+
def print_dot
|
125
|
+
$terminal.instance_variable_get(:@output).print('.')
|
126
|
+
end
|
108
127
|
|
109
|
-
private
|
110
128
|
|
111
129
|
# cache SSH keys from the REST client
|
112
130
|
def ssh_keys
|
@@ -118,6 +136,29 @@ module RHC
|
|
118
136
|
@ssh_keys = nil
|
119
137
|
end
|
120
138
|
|
139
|
+
# return true if the account has the public key defined by
|
140
|
+
# RHC::Config::ssh_pub_key_file_path
|
141
|
+
def ssh_key_uploaded?
|
142
|
+
ssh_keys.present? && ssh_keys.any? { |k| k.fingerprint.present? && k.fingerprint == fingerprint_for_default_key }
|
143
|
+
end
|
144
|
+
|
145
|
+
def existing_keys_info
|
146
|
+
return unless ssh_keys
|
147
|
+
indent{ ssh_keys.each{ |key| paragraph{ display_key(key) } } }
|
148
|
+
end
|
149
|
+
|
150
|
+
def applications
|
151
|
+
@applications ||= rest_client.domains.map(&:applications).flatten
|
152
|
+
end
|
153
|
+
|
154
|
+
def namespace_optional?
|
155
|
+
true
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# Stages
|
160
|
+
#
|
161
|
+
|
121
162
|
def greeting_stage
|
122
163
|
info "OpenShift Client Tools (RHC) Setup Wizard"
|
123
164
|
|
@@ -129,7 +170,8 @@ module RHC
|
|
129
170
|
end
|
130
171
|
|
131
172
|
def login_stage
|
132
|
-
if
|
173
|
+
if token_for_user
|
174
|
+
options.token = token_for_user
|
133
175
|
say "Using an existing token for #{options.rhlogin} to login to #{openshift_server}"
|
134
176
|
elsif options.rhlogin
|
135
177
|
say "Using #{options.rhlogin} to login to #{openshift_server}"
|
@@ -161,6 +203,7 @@ module RHC
|
|
161
203
|
end
|
162
204
|
|
163
205
|
self.user = rest_client.user
|
206
|
+
options.rhlogin = self.user.login unless username
|
164
207
|
|
165
208
|
if rest_client.supports_sessions? && !options.token && options.create_token != false
|
166
209
|
paragraph do
|
@@ -215,122 +258,106 @@ module RHC
|
|
215
258
|
true
|
216
259
|
end
|
217
260
|
|
218
|
-
|
219
|
-
|
220
|
-
def ssh_key_uploaded?
|
221
|
-
ssh_keys.any? { |k| k.fingerprint == fingerprint_for_default_key }
|
222
|
-
end
|
261
|
+
def upload_ssh_key_stage
|
262
|
+
return true if ssh_key_uploaded?
|
223
263
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
end
|
264
|
+
upload = paragraph do
|
265
|
+
agree "Your public SSH key must be uploaded to the OpenShift server to access code. Upload now? (yes|no) "
|
266
|
+
end
|
228
267
|
|
229
|
-
|
230
|
-
|
268
|
+
if upload
|
269
|
+
if ssh_keys.empty?
|
270
|
+
paragraph do
|
271
|
+
info "Since you do not have any keys associated with your OpenShift account, "\
|
272
|
+
"your new key will be uploaded as the 'default' key."
|
273
|
+
upload_ssh_key('default')
|
274
|
+
end
|
275
|
+
else
|
276
|
+
paragraph { existing_keys_info }
|
277
|
+
|
278
|
+
key_fingerprint = fingerprint_for_default_key
|
279
|
+
unless key_fingerprint
|
280
|
+
paragraph do
|
281
|
+
warn "Your ssh public key at #{system_path(RHC::Config.ssh_pub_key_file_path)} is invalid or unreadable. "\
|
282
|
+
"Setup can not continue until you manually remove or fix your "\
|
283
|
+
"public and private keys id_rsa keys."
|
284
|
+
end
|
285
|
+
return false
|
286
|
+
end
|
231
287
|
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
288
|
+
paragraph do
|
289
|
+
say "You can enter a name for your key, or leave it blank to use the default name. " \
|
290
|
+
"Using the same name as an existing key will overwrite the old key."
|
291
|
+
end
|
292
|
+
ask_for_key_name
|
236
293
|
end
|
237
294
|
else
|
238
295
|
paragraph do
|
239
|
-
|
240
|
-
"Using the same name as an existing key will overwrite the old key."
|
241
|
-
end
|
242
|
-
|
243
|
-
paragraph { existing_keys_info }
|
244
|
-
|
245
|
-
key_fingerprint = fingerprint_for_default_key
|
246
|
-
unless key_fingerprint
|
247
|
-
paragraph do
|
248
|
-
warn "Your ssh public key at #{system_path(RHC::Config.ssh_pub_key_file_path)} is invalid or unreadable. "\
|
249
|
-
"Setup can not continue until you manually remove or fix your "\
|
250
|
-
"public and private keys id_rsa keys."
|
251
|
-
end
|
252
|
-
return nil
|
296
|
+
info "You can upload your SSH key at a later time using the 'rhc sshkey' command"
|
253
297
|
end
|
298
|
+
end
|
254
299
|
|
255
|
-
|
256
|
-
|
257
|
-
default_name = find_unique_key_name(
|
258
|
-
:keys => ssh_keys,
|
259
|
-
:base => pubkey_base_name,
|
260
|
-
:max_length => DEFAULT_MAX_LENGTH
|
261
|
-
)
|
300
|
+
true
|
301
|
+
end
|
262
302
|
|
263
|
-
|
264
|
-
|
303
|
+
def ask_for_key_name(default_name=get_preferred_key_name)
|
304
|
+
key_name = nil
|
305
|
+
paragraph do
|
306
|
+
begin
|
307
|
+
key_name = ask "Provide a name for this key: " do |q|
|
265
308
|
q.default = default_name
|
266
|
-
q.
|
267
|
-
q.responses[:not_valid] = 'Your key name must be letters and numbers only.'
|
309
|
+
q.responses[:ask_on_error] = ''
|
268
310
|
end
|
269
|
-
end
|
311
|
+
end while !upload_ssh_key(key_name)
|
270
312
|
end
|
313
|
+
end
|
271
314
|
|
272
|
-
|
315
|
+
def get_preferred_key_name
|
316
|
+
userkey = username ? username.gsub(/@.*/, '') : ''
|
317
|
+
pubkey_base_name = "#{userkey}#{hostname.gsub(/\..*\z/,'')}".gsub(/[^A-Za-z0-9]/,'').slice(0,16)
|
318
|
+
find_unique_key_name(pubkey_base_name)
|
273
319
|
end
|
274
|
-
|
320
|
+
|
275
321
|
# given the base name and the maximum length,
|
276
322
|
# find a name that does not clash with what is in opts[:keys]
|
277
|
-
def find_unique_key_name(
|
278
|
-
|
279
|
-
base = opts[:base] || 'default'
|
280
|
-
max = opts[:max_length] || DEFAULT_MAX_LENGTH
|
323
|
+
def find_unique_key_name(base='default')
|
324
|
+
max = DEFAULT_MAX_LENGTH
|
281
325
|
key_name_suffix = 1
|
282
326
|
candidate = base
|
283
327
|
while ssh_keys.detect { |k| k.name == candidate }
|
284
|
-
candidate = base.slice(0, max - key_name_suffix.to_s.length) +
|
285
|
-
key_name_suffix.to_s
|
328
|
+
candidate = base.slice(0, max - key_name_suffix.to_s.length) + key_name_suffix.to_s
|
286
329
|
key_name_suffix += 1
|
287
330
|
end
|
288
331
|
candidate
|
289
332
|
end
|
290
333
|
|
291
|
-
def upload_ssh_key
|
292
|
-
|
293
|
-
return false unless key_name
|
334
|
+
def upload_ssh_key(key_name)
|
335
|
+
return false unless key_name.present?
|
294
336
|
|
295
337
|
type, content, comment = ssh_key_triple_for_default_key
|
296
|
-
indent do
|
297
|
-
say table([['Type:', type], ['Fingerprint:', fingerprint_for_default_key]])
|
298
|
-
end
|
299
338
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
say "Key with the name #{key_name} already exists. Updating ... "
|
339
|
+
if ssh_keys.present? && ssh_keys.any? { |k| k.name == key_name }
|
340
|
+
clear_ssh_keys_cache
|
341
|
+
paragraph do
|
342
|
+
say "Key with the name '#{key_name}' already exists. Updating ... "
|
304
343
|
key = rest_client.find_key(key_name)
|
305
344
|
key.update(type, content)
|
306
|
-
|
307
|
-
clear_ssh_keys_cache
|
308
|
-
say "Uploading key '#{key_name}' from #{system_path(RHC::Config::ssh_pub_key_file_path)} ... "
|
309
|
-
rest_client.add_key key_name, content, type
|
345
|
+
success "done"
|
310
346
|
end
|
311
|
-
success "done"
|
312
|
-
end
|
313
|
-
|
314
|
-
true
|
315
|
-
end
|
316
|
-
|
317
|
-
def upload_ssh_key_stage
|
318
|
-
return true if ssh_key_uploaded?
|
319
|
-
|
320
|
-
upload = paragraph do
|
321
|
-
agree "Your public SSH key must be uploaded to the OpenShift server to access code. Upload now? (yes|no) "
|
322
|
-
end
|
323
|
-
|
324
|
-
if upload
|
325
|
-
upload_ssh_key
|
326
347
|
else
|
327
|
-
|
328
|
-
|
348
|
+
clear_ssh_keys_cache
|
349
|
+
begin
|
350
|
+
rest_client.add_key(key_name, content, type)
|
351
|
+
paragraph{ say "Uploading key '#{key_name}' ... #{color('done', :green)}" }
|
352
|
+
rescue RHC::Rest::ValidationException => e
|
353
|
+
error e.message || "Unknown error during key upload."
|
354
|
+
return false
|
329
355
|
end
|
330
356
|
end
|
331
357
|
|
332
358
|
true
|
333
|
-
end
|
359
|
+
end
|
360
|
+
|
334
361
|
|
335
362
|
##
|
336
363
|
# Alert the user that they should manually install tools if they are not
|
@@ -397,7 +424,7 @@ module RHC
|
|
397
424
|
paragraph do
|
398
425
|
say table(standalone_cartridges.sort {|a,b| a.display_name <=> b.display_name }.map do |cart|
|
399
426
|
[' ', cart.display_name, "rhc app create <app name> #{cart.name}"]
|
400
|
-
end)
|
427
|
+
end)
|
401
428
|
end
|
402
429
|
end
|
403
430
|
paragraph do
|
@@ -440,12 +467,7 @@ module RHC
|
|
440
467
|
end
|
441
468
|
|
442
469
|
def all_test_methods
|
443
|
-
private_methods.select {|m| m.to_s.start_with? 'test_'}
|
444
|
-
end
|
445
|
-
|
446
|
-
# cached list of applications needed for test stage
|
447
|
-
def applications
|
448
|
-
@applications ||= rest_client.domains.map(&:applications).flatten
|
470
|
+
(protected_methods + private_methods).select {|m| m.to_s.start_with? 'test_'}
|
449
471
|
end
|
450
472
|
|
451
473
|
###
|
@@ -491,13 +513,14 @@ module RHC
|
|
491
513
|
|
492
514
|
def config_namespace(namespace)
|
493
515
|
# skip if string is empty
|
494
|
-
if namespace.nil? or namespace.chomp.
|
516
|
+
if namespace_optional? and (namespace.nil? or namespace.chomp.blank?)
|
495
517
|
paragraph{ info "You may create a namespace later through 'rhc domain create'" }
|
496
518
|
return true
|
497
519
|
end
|
498
520
|
|
499
521
|
begin
|
500
522
|
domain = rest_client.add_domain(namespace)
|
523
|
+
options.namespace = namespace
|
501
524
|
|
502
525
|
success "Your domain name '#{domain.id}' has been successfully created"
|
503
526
|
rescue RHC::Rest::ValidationException => e
|
@@ -513,9 +536,7 @@ module RHC
|
|
513
536
|
namespace = nil
|
514
537
|
paragraph do
|
515
538
|
begin
|
516
|
-
namespace = ask "Please enter a namespace (letters and numbers only) |<none
|
517
|
-
#q.validate = lambda{ |p| RHC::check_namespace p }
|
518
|
-
#q.responses[:not_valid] = 'The namespace value must contain only letters and/or numbers (A-Za-z0-9):'
|
539
|
+
namespace = ask "Please enter a namespace (letters and numbers only)#{namespace_optional? ? " |<none>|" : ""}: " do |q|
|
519
540
|
q.responses[:ask_on_error] = ''
|
520
541
|
end
|
521
542
|
end while !config_namespace(namespace)
|
@@ -557,21 +578,9 @@ We recommend these free applications:
|
|
557
578
|
|
558
579
|
EOF
|
559
580
|
end
|
560
|
-
|
561
|
-
def debug?
|
562
|
-
@debug
|
563
|
-
end
|
564
|
-
|
565
|
-
def hostname
|
566
|
-
Socket.gethostname
|
567
|
-
end
|
568
|
-
|
569
|
-
protected
|
570
|
-
attr_writer :rest_client
|
571
581
|
end
|
572
582
|
|
573
583
|
class RerunWizard < Wizard
|
574
|
-
|
575
584
|
def finalize_stage
|
576
585
|
section :top => 1 do
|
577
586
|
success "Your client tools are now configured."
|
@@ -580,11 +589,36 @@ EOF
|
|
580
589
|
end
|
581
590
|
end
|
582
591
|
|
592
|
+
class EmbeddedWizard < Wizard
|
593
|
+
def stages
|
594
|
+
super - APP_STAGES - KEY_STAGES - [:setup_test_stage]
|
595
|
+
end
|
596
|
+
|
597
|
+
def finalize_stage
|
598
|
+
true
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
class DomainWizard < Wizard
|
603
|
+
def initialize(*args)
|
604
|
+
client = args.length == 3 ? args.pop : nil
|
605
|
+
super *args
|
606
|
+
self.rest_client = client || new_client_for_options
|
607
|
+
end
|
608
|
+
|
609
|
+
def stages
|
610
|
+
[:config_namespace_stage]
|
611
|
+
end
|
612
|
+
|
613
|
+
protected
|
614
|
+
def namespace_optional?
|
615
|
+
false
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
583
619
|
class SSHWizard < Wizard
|
584
|
-
STAGES = [:config_ssh_key_stage,
|
585
|
-
:upload_ssh_key_stage]
|
586
620
|
def stages
|
587
|
-
|
621
|
+
KEY_STAGES
|
588
622
|
end
|
589
623
|
|
590
624
|
def initialize(rest_client, config, options)
|