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/commands/sshkey.rb
CHANGED
@@ -4,11 +4,23 @@ module RHC::Commands
|
|
4
4
|
class Sshkey < Base
|
5
5
|
include RHC::SSHHelpers
|
6
6
|
|
7
|
-
summary '
|
7
|
+
summary 'Add and remove keys for Git and SSH'
|
8
8
|
syntax '<action>'
|
9
|
+
description <<-DESC
|
10
|
+
OpenShift uses public keys to securely access your application source
|
11
|
+
code and to control access to your application gears via SSH. Your
|
12
|
+
account may have one or more public SSH keys associated with it, and
|
13
|
+
any computer with the private SSH key will be able to download code
|
14
|
+
from Git or SSH to the application.
|
15
|
+
|
16
|
+
Depending on your operating system, you may have to ensure that both
|
17
|
+
Git and the local SSH installation have access to your keys. Running
|
18
|
+
the 'setup' command is any easy way to get your first key created and
|
19
|
+
uploaded.
|
20
|
+
DESC
|
9
21
|
default_action :list
|
10
22
|
|
11
|
-
summary 'Display all the SSH keys for
|
23
|
+
summary 'Display all the SSH keys for your account'
|
12
24
|
syntax ''
|
13
25
|
def list
|
14
26
|
keys = rest_client.sshkeys.each{ |key| paragraph{ display_key(key) } }
|
@@ -18,7 +30,7 @@ module RHC::Commands
|
|
18
30
|
0
|
19
31
|
end
|
20
32
|
|
21
|
-
summary '
|
33
|
+
summary 'Show the SSH key with the given name'
|
22
34
|
syntax '<name>'
|
23
35
|
argument :name, 'SSH key to display', []
|
24
36
|
def show(name)
|
@@ -28,7 +40,7 @@ module RHC::Commands
|
|
28
40
|
0
|
29
41
|
end
|
30
42
|
|
31
|
-
summary 'Add SSH key to
|
43
|
+
summary 'Add SSH key to your account'
|
32
44
|
syntax '<name> <path to SSH key file>'
|
33
45
|
argument :name, 'Name for this key', []
|
34
46
|
argument :key, 'SSH public key filepath', []
|
@@ -54,13 +66,15 @@ module RHC::Commands
|
|
54
66
|
0
|
55
67
|
end
|
56
68
|
|
57
|
-
summary 'Remove SSH key from
|
69
|
+
summary 'Remove SSH key from your account'
|
58
70
|
syntax '<name>'
|
59
71
|
alias_action :delete
|
60
|
-
argument :name, 'SSH key to remove'
|
72
|
+
argument :name, 'Name of SSH key to remove'
|
61
73
|
def remove(name)
|
74
|
+
say "Removing the key '#{name} ... "
|
62
75
|
rest_client.delete_key(name)
|
63
|
-
|
76
|
+
|
77
|
+
success "removed"
|
64
78
|
|
65
79
|
0
|
66
80
|
end
|
data/lib/rhc/commands/tail.rb
CHANGED
@@ -8,8 +8,8 @@ module RHC::Commands
|
|
8
8
|
|
9
9
|
summary "Tail the logs of an application"
|
10
10
|
syntax "<application>"
|
11
|
-
argument :app, "Name of application you wish to view the logs of", ["-a", "--app
|
12
|
-
option ["-n", "--namespace
|
11
|
+
argument :app, "Name of application you wish to view the logs of", ["-a", "--app NAME"]
|
12
|
+
option ["-n", "--namespace NAME"], "Namespace of your application", :context => :namespace_context, :required => true
|
13
13
|
option ["-o", "--opts options"], "Options to pass to the server-side (linux based) tail command (applicable to tail command only) (-f is implicit. See the linux tail man page full list of options.) (Ex: --opts '-n 100')"
|
14
14
|
option ["-f", "--files files"], "File glob relative to app (default <application_name>/logs/*) (optional)"
|
15
15
|
#option ["-c", "--cartridge name"], "Tail only a specific cartridge"
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'rhc/commands/base'
|
2
2
|
module RHC::Commands
|
3
3
|
class Threaddump < Base
|
4
|
-
summary "Trigger a thread dump for JBoss and Ruby
|
4
|
+
summary "Trigger a thread dump for JBoss and Ruby apps"
|
5
5
|
syntax "<application>"
|
6
|
-
option ["-n", "--namespace
|
6
|
+
option ["-n", "--namespace NAME"], "Namespace of your application", :context => :namespace_context, :required => true
|
7
7
|
argument :app, "Name of the application on which to execute the thread dump", ["-a", "--app name"]
|
8
8
|
def run(app)
|
9
9
|
rest_app = rest_client.find_application(options.namespace, app)
|
data/lib/rhc/context_helper.rb
CHANGED
@@ -12,10 +12,6 @@ module RHC
|
|
12
12
|
ENV['LIBRA_SERVER'] || (!options.clean && config['libra_server']) || "openshift.redhat.com"
|
13
13
|
end
|
14
14
|
|
15
|
-
def token_context
|
16
|
-
token_store.get(options.rhlogin, options.server) if options.rhlogin
|
17
|
-
end
|
18
|
-
|
19
15
|
def app_context
|
20
16
|
debug "Getting app context"
|
21
17
|
|
data/lib/rhc/core_ext.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# From Rails core_ext/object.rb
|
2
2
|
require 'rhc/json'
|
3
3
|
require 'open-uri'
|
4
|
-
require 'highline'
|
5
4
|
require 'httpclient'
|
6
5
|
|
7
6
|
class Object
|
@@ -24,6 +23,23 @@ class Object
|
|
24
23
|
end
|
25
24
|
end
|
26
25
|
|
26
|
+
class Array
|
27
|
+
# From rails
|
28
|
+
def split(value = nil)
|
29
|
+
using_block = block_given?
|
30
|
+
|
31
|
+
inject([[]]) do |results, element|
|
32
|
+
if (using_block && yield(element)) || (value == element)
|
33
|
+
results << []
|
34
|
+
else
|
35
|
+
results.last << element
|
36
|
+
end
|
37
|
+
|
38
|
+
results
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
27
43
|
class File
|
28
44
|
def chunk(chunk_size=1024)
|
29
45
|
yield read(chunk_size) until eof?
|
@@ -37,6 +53,85 @@ class String
|
|
37
53
|
def wrap(wrap_length=80, char="\n")
|
38
54
|
scan(/.{#{wrap_length}}|.+/).join(char)
|
39
55
|
end
|
56
|
+
|
57
|
+
def strip_heredoc
|
58
|
+
indent = scan(/^[ \t]*(?=\S)/).min.size || 0
|
59
|
+
gsub(/^[ \t]{#{indent}}/, '').
|
60
|
+
gsub(/(\b|\S)[^\S\n]*\n(\S)/m, '\1 \2').
|
61
|
+
gsub(/\n+\Z/, '').
|
62
|
+
gsub(/\n{3,}/, "\n\n")
|
63
|
+
end
|
64
|
+
|
65
|
+
ANSI_ESCAPE_SEQUENCE = /\e\[(\d{1,2}(?:;\d{1,2})*[@-~])/
|
66
|
+
ANSI_ESCAPE_MATCH = '\e\[\d+(?:;\d+)*[@-~]'
|
67
|
+
CHAR_SKIP_ANSI = "(?:(?:#{ANSI_ESCAPE_MATCH})+.?|.(?:#{ANSI_ESCAPE_MATCH})*)"
|
68
|
+
|
69
|
+
#
|
70
|
+
# Split the given string at limit, treating ANSI escape sequences as
|
71
|
+
# zero characters in length. Will insert an ANSI reset code (\e[0m)
|
72
|
+
# at the end of each line containing an ANSI code, assuming that a
|
73
|
+
# reset was not in the wrapped segment.
|
74
|
+
#
|
75
|
+
# All newlines are preserved.
|
76
|
+
#
|
77
|
+
# Lines longer than limit without natural breaks will be forcibly
|
78
|
+
# split at the exact limit boundary.
|
79
|
+
#
|
80
|
+
# Returns an Array
|
81
|
+
#
|
82
|
+
def textwrap_ansi(limit, breakword=true)
|
83
|
+
re = breakword ? /
|
84
|
+
(
|
85
|
+
# Match substrings that end in whitespace shorter than limit
|
86
|
+
#{CHAR_SKIP_ANSI}{1,#{limit}} # up to limit
|
87
|
+
(?:\s+|$) # require the limit to end on whitespace
|
88
|
+
|
|
89
|
+
# Match substrings equal to the limit
|
90
|
+
#{CHAR_SKIP_ANSI}{1,#{limit}}
|
91
|
+
)
|
92
|
+
/x :
|
93
|
+
/
|
94
|
+
(
|
95
|
+
# Match substrings that end in whitespace shorter than limit
|
96
|
+
#{CHAR_SKIP_ANSI}{1,#{limit}}
|
97
|
+
(?:\s|$) # require the limit to end on whitespace
|
98
|
+
|
|
99
|
+
# Match all continguous whitespace strings
|
100
|
+
#{CHAR_SKIP_ANSI}+?
|
101
|
+
(?:\s|$)
|
102
|
+
(?:\s+|$)?
|
103
|
+
)
|
104
|
+
/x
|
105
|
+
escapes = []
|
106
|
+
|
107
|
+
split("\n",-1).inject([]) do |a, line|
|
108
|
+
if line.length < limit
|
109
|
+
a << line
|
110
|
+
else
|
111
|
+
line.scan(re) do |segment, other|
|
112
|
+
if escapes.present?
|
113
|
+
a << escapes.map{ |s| "\e[#{s}"}.join
|
114
|
+
a[-1] << segment.rstrip
|
115
|
+
else
|
116
|
+
a << segment.rstrip
|
117
|
+
end
|
118
|
+
|
119
|
+
segment.scan(ANSI_ESCAPE_SEQUENCE).map{ |e| e.first }.each do |e|
|
120
|
+
case e
|
121
|
+
when '0m' then escapes.clear
|
122
|
+
else escapes << e
|
123
|
+
end
|
124
|
+
end
|
125
|
+
a[-1] << "\e[0m" if escapes.present?
|
126
|
+
end
|
127
|
+
end
|
128
|
+
a
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def strip_ansi
|
133
|
+
gsub(ANSI_ESCAPE_SEQUENCE, '')
|
134
|
+
end
|
40
135
|
end
|
41
136
|
|
42
137
|
unless HTTP::Message.method_defined? :ok?
|
@@ -99,78 +194,3 @@ class Hash
|
|
99
194
|
merge!( other_hash ){|key,left,right| left }
|
100
195
|
end
|
101
196
|
end
|
102
|
-
|
103
|
-
# Some versions of highline get in an infinite loop when trying to wrap.
|
104
|
-
# Fixes BZ 866530.
|
105
|
-
class HighLine
|
106
|
-
|
107
|
-
def wrap_line(line)
|
108
|
-
wrapped_line = []
|
109
|
-
i = chars_in_line = 0
|
110
|
-
word = []
|
111
|
-
|
112
|
-
while i < line.length
|
113
|
-
# we have to give a length to the index because ruby 1.8 returns the
|
114
|
-
# byte code when using a single fixednum index
|
115
|
-
c = line[i, 1]
|
116
|
-
color_code = nil
|
117
|
-
# escape character probably means color code, let's check
|
118
|
-
if c == "\e"
|
119
|
-
color_code = line[i..i+6].match(/\e\[\d{1,2}m/)
|
120
|
-
if color_code
|
121
|
-
# first the existing word buffer then the color code
|
122
|
-
wrapped_line << word.join.wrap(@wrap_at) << color_code[0]
|
123
|
-
word.clear
|
124
|
-
|
125
|
-
i += color_code[0].length
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
# visible character
|
130
|
-
if !color_code
|
131
|
-
chars_in_line += 1
|
132
|
-
word << c
|
133
|
-
|
134
|
-
# time to wrap the line?
|
135
|
-
if chars_in_line == @wrap_at
|
136
|
-
if c == ' ' or line[i+1, 1] == ' ' or word.length == @wrap_at
|
137
|
-
wrapped_line << word.join
|
138
|
-
word.clear
|
139
|
-
end
|
140
|
-
|
141
|
-
wrapped_line[-1].rstrip!
|
142
|
-
wrapped_line << "\n"
|
143
|
-
|
144
|
-
# consume any spaces at the begining of the next line
|
145
|
-
word = word.join.lstrip.split(//)
|
146
|
-
chars_in_line = word.length
|
147
|
-
|
148
|
-
if line[i+1, 1] == ' '
|
149
|
-
i += 1 while line[i+1, 1] == ' '
|
150
|
-
end
|
151
|
-
|
152
|
-
else
|
153
|
-
if c == ' '
|
154
|
-
wrapped_line << word.join
|
155
|
-
word.clear
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
i += 1
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
wrapped_line << word.join
|
164
|
-
wrapped_line.join
|
165
|
-
end
|
166
|
-
|
167
|
-
def wrap(text)
|
168
|
-
wrapped_text = []
|
169
|
-
lines = text.split(/\r?\n/)
|
170
|
-
lines.each_with_index do |line, i|
|
171
|
-
wrapped_text << wrap_line(i == lines.length - 1 ? line : line.rstrip)
|
172
|
-
end
|
173
|
-
|
174
|
-
return wrapped_text.join("\n")
|
175
|
-
end
|
176
|
-
end
|
data/lib/rhc/exceptions.rb
CHANGED
@@ -134,4 +134,10 @@ module RHC
|
|
134
134
|
super message, 1
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
class ServerAPINotSupportedException < Exception
|
139
|
+
def initialize(min_version, current_version)
|
140
|
+
super "The server does not support this command (requires #{min_version}, found #{current_version})."
|
141
|
+
end
|
142
|
+
end
|
137
143
|
end
|
data/lib/rhc/help_formatter.rb
CHANGED
@@ -5,20 +5,37 @@ module RHC
|
|
5
5
|
def template(name)
|
6
6
|
ERB.new(File.read(File.join(File.dirname(__FILE__), 'usage_templates', "#{name}.erb")), nil, '-')
|
7
7
|
end
|
8
|
+
def render
|
9
|
+
template(:help).result RunnerHelpBindings.new(@runner).get_binding
|
10
|
+
end
|
8
11
|
def render_command_syntax command
|
9
12
|
template(:command_syntax_help).result command.get_binding
|
10
13
|
end
|
11
14
|
def render_options runner
|
12
|
-
template(:options_help).result runner.get_binding
|
15
|
+
template(:options_help).result RunnerHelpBindings.new(runner).get_binding
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class RunnerHelpBindings < SimpleDelegator
|
20
|
+
include RHC::Helpers
|
21
|
+
|
22
|
+
def commands
|
23
|
+
__getobj__.instance_variable_get(:@commands)
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_binding
|
27
|
+
binding
|
13
28
|
end
|
14
29
|
end
|
15
30
|
|
16
31
|
class CommandHelpBindings
|
32
|
+
include RHC::Helpers
|
33
|
+
|
17
34
|
def initialize(command, instance_commands, runner)
|
18
35
|
@command = command
|
19
36
|
@actions = instance_commands.collect do |command_name, command_class|
|
20
37
|
next if command_class.summary.nil?
|
21
|
-
m = /^#{command.name}
|
38
|
+
m = /^#{command.name}[\-]([^ ]+)/.match(command_name)
|
22
39
|
# if we have a match and it is not an alias then we can use it
|
23
40
|
m and command_name == command_class.name ? {:name => m[1], :summary => command_class.summary || ""} : nil
|
24
41
|
end
|
data/lib/rhc/helpers.rb
CHANGED
@@ -29,22 +29,15 @@ module RHC
|
|
29
29
|
MAX_RETRIES = 7
|
30
30
|
DEFAULT_DELAY_THROTTLE = 2.0
|
31
31
|
|
32
|
-
def disable_deprecated?
|
33
|
-
# 1) default for now is false
|
34
|
-
# 2) when releasing a 1.0 beta flip this to true
|
35
|
-
# 3) all deprecated aliases should be removed right before 1.0
|
36
|
-
disable = false
|
37
|
-
|
38
|
-
env_disable = ENV['DISABLE_DEPRECATED']
|
39
|
-
disable = true if env_disable == '1'
|
40
|
-
|
41
|
-
disable
|
42
|
-
end
|
43
|
-
|
44
32
|
def decode_json(s)
|
45
33
|
RHC::Vendor::OkJson.decode(s)
|
46
34
|
end
|
47
35
|
|
36
|
+
def system_path(path)
|
37
|
+
return path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if File.const_defined?('ALT_SEPARATOR') and File::ALT_SEPARATOR.present?
|
38
|
+
path
|
39
|
+
end
|
40
|
+
|
48
41
|
def date(s)
|
49
42
|
now = Date.today
|
50
43
|
d = datetime_rfc3339(s).to_time
|
@@ -100,7 +93,7 @@ module RHC
|
|
100
93
|
|
101
94
|
global_option '-l', '--rhlogin LOGIN', "OpenShift login"
|
102
95
|
global_option '-p', '--password PASSWORD', "OpenShift password"
|
103
|
-
global_option '--token TOKEN', "An authorization token for accessing your account."
|
96
|
+
global_option '--token TOKEN', "An authorization token for accessing your account."
|
104
97
|
|
105
98
|
global_option '-d', '--debug', "Turn on debugging", :hide => true
|
106
99
|
|
@@ -124,7 +117,7 @@ module RHC
|
|
124
117
|
global_option '--noprompt', "Suppress all interactive operations command", :hide => true do
|
125
118
|
$terminal.page_at = nil
|
126
119
|
end
|
127
|
-
global_option '--config FILE', "Path of a different config file", :hide => true
|
120
|
+
global_option '--config FILE', "Path of a different config file (default: #{system_path("~/.openshift/express.conf")})", :hide => true
|
128
121
|
global_option '--clean', "Ignore any saved configuration options", :hide => true
|
129
122
|
global_option '--mock', "Run in mock mode", :hide => true do
|
130
123
|
#:nocov:
|
@@ -154,6 +147,10 @@ module RHC
|
|
154
147
|
uri.path = '/broker/rest/api' if uri.path.blank? || uri.path == '/'
|
155
148
|
uri
|
156
149
|
end
|
150
|
+
|
151
|
+
def token_for_user
|
152
|
+
options.token or (token_store.get(options.rhlogin, options.server) if options.rhlogin)
|
153
|
+
end
|
157
154
|
|
158
155
|
def client_from_options(opts)
|
159
156
|
RHC::Rest::Client.new({
|
@@ -183,6 +180,10 @@ module RHC
|
|
183
180
|
# Output helpers
|
184
181
|
#
|
185
182
|
|
183
|
+
def interactive?
|
184
|
+
$stdout.tty? and not options.noprompt
|
185
|
+
end
|
186
|
+
|
186
187
|
def debug(msg)
|
187
188
|
$stderr.puts "DEBUG: #{msg}" if debug?
|
188
189
|
end
|
@@ -193,66 +194,23 @@ module RHC
|
|
193
194
|
false
|
194
195
|
end
|
195
196
|
|
196
|
-
def
|
197
|
-
|
197
|
+
def disable_deprecated?
|
198
|
+
ENV['DISABLE_DEPRECATED'] == '1'
|
198
199
|
end
|
199
200
|
|
200
|
-
def
|
201
|
-
deprecated("
|
201
|
+
def deprecated_command(correct, short=false)
|
202
|
+
deprecated("This command is deprecated. Please use '#{correct}' instead.", short)
|
202
203
|
end
|
203
204
|
|
204
|
-
def deprecated
|
205
|
-
|
206
|
-
|
207
|
-
info = " For porting and testing purposes you may switch this %s to %s by setting the DISABLE_DEPRECATED environment variable to %d. It is not recommended to do so in a production environment as this option will be removed in a future release."
|
208
|
-
msg << info unless short
|
205
|
+
def deprecated_option(deprecated, other)
|
206
|
+
deprecated("The option '#{deprecated}' is deprecated. Please use '#{other}' instead")
|
207
|
+
end
|
209
208
|
|
209
|
+
def deprecated(msg,short = false)
|
210
210
|
raise DeprecatedError.new(msg % ['an error','a warning',0]) if disable_deprecated?
|
211
|
-
|
212
211
|
warn "Warning: #{msg}\n" % ['a warning','an error',1]
|
213
212
|
end
|
214
213
|
|
215
|
-
@@indent = 0
|
216
|
-
@@last_line_open = false
|
217
|
-
def say(msg, *args)
|
218
|
-
output = if Hash[*args][:stderr]
|
219
|
-
$stderr
|
220
|
-
else
|
221
|
-
separate_blocks
|
222
|
-
$terminal.instance_variable_get(:@output)
|
223
|
-
end
|
224
|
-
|
225
|
-
Array(msg).each do |statement|
|
226
|
-
statement = statement.to_str
|
227
|
-
next unless statement.present?
|
228
|
-
|
229
|
-
template = ERB.new(statement, nil, "%")
|
230
|
-
statement = template.result(binding)
|
231
|
-
|
232
|
-
statement = $terminal.wrap(statement) unless $terminal.instance_variable_get(:@wrap_at).nil?
|
233
|
-
statement = $terminal.send(:page_print, statement) unless $terminal.instance_variable_get(:@page_at).nil?
|
234
|
-
|
235
|
-
output.print(' ' * @@indent * INDENT) unless @@last_line_open
|
236
|
-
|
237
|
-
@@last_line_open =
|
238
|
-
if statement[-1, 1] == " " or statement[-1, 1] == "\t"
|
239
|
-
output.print(statement)
|
240
|
-
output.flush
|
241
|
-
else
|
242
|
-
output.puts(statement)
|
243
|
-
end
|
244
|
-
end
|
245
|
-
|
246
|
-
msg
|
247
|
-
end
|
248
|
-
|
249
|
-
[:ask, :agree].each do |sym|
|
250
|
-
define_method(sym) do |*args, &block|
|
251
|
-
separate_blocks
|
252
|
-
super(*args, &block)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
214
|
def confirm_action(question)
|
257
215
|
return if options.confirm
|
258
216
|
return if !options.noprompt && paragraph{ agree("#{question} (yes|no): ") }
|
@@ -275,39 +233,19 @@ module RHC
|
|
275
233
|
say color(msg, :red), *args
|
276
234
|
end
|
277
235
|
|
278
|
-
|
279
|
-
|
236
|
+
# OVERRIDE: Replaces default commander behavior
|
237
|
+
def color(*args)
|
238
|
+
$terminal.color(*args)
|
280
239
|
end
|
281
240
|
|
282
|
-
|
283
|
-
|
241
|
+
[:pager, :indent, :paragraph, :section, :header, :table, :table_args].each do |sym|
|
242
|
+
define_method(sym) do |*args, &block|
|
243
|
+
$terminal.send(sym, *args, &block)
|
244
|
+
end
|
284
245
|
end
|
285
246
|
|
286
|
-
|
287
|
-
|
288
|
-
def table(items, opts={}, &block)
|
289
|
-
items = items.map &block if block_given?
|
290
|
-
widths = []
|
291
|
-
items.each do |item|
|
292
|
-
item.each_with_index do |s, i|
|
293
|
-
item[i] = s.to_s
|
294
|
-
widths[i] = [widths[i] || 0, item[i].length].max
|
295
|
-
end
|
296
|
-
end
|
297
|
-
align = opts[:align] || []
|
298
|
-
join = opts[:join] || ' '
|
299
|
-
if opts[:header]
|
300
|
-
opts[:header].each_with_index do |s, i|
|
301
|
-
widths[i] = [widths[i] || 0, s.length].max
|
302
|
-
end
|
303
|
-
sep = opts[:separator] || "="
|
304
|
-
ary = Array.new(opts[:header].length)
|
305
|
-
items.unshift ary.each_with_index {|obj, idx| ary[idx] = sep.to_s * (widths[idx] || 1)}
|
306
|
-
items.unshift(opts[:header])
|
307
|
-
end
|
308
|
-
items.map do |item|
|
309
|
-
item.each_with_index.map{ |s,i| s.send((align[i] == :right ? :rjust : :ljust), widths[i], ' ') }.join(join).rstrip
|
310
|
-
end
|
247
|
+
def pluralize(count, s)
|
248
|
+
count == 1 ? "#{count} #{s}" : "#{count} #{s}s"
|
311
249
|
end
|
312
250
|
|
313
251
|
# This will format table headings for a consistent look and feel
|
@@ -360,92 +298,6 @@ module RHC
|
|
360
298
|
end
|
361
299
|
end
|
362
300
|
|
363
|
-
#def tee(&block)
|
364
|
-
# original = [$stdout, $stderr]
|
365
|
-
# $stdout, $stderr = (tees = original.map{ |io| StringTee.new(io) })
|
366
|
-
# yield
|
367
|
-
#ensure
|
368
|
-
# $stdout, $stderr = original
|
369
|
-
# tees.each(&:close_write).map(&:string)
|
370
|
-
#end
|
371
|
-
|
372
|
-
def header(str,opts = {}, &block)
|
373
|
-
str = underline(str)
|
374
|
-
str = str.map{ |s| color(s, opts[:color]) } if opts[:color]
|
375
|
-
say str
|
376
|
-
if block_given?
|
377
|
-
indent &block
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
def underline(s)
|
382
|
-
[s, "-"*s.length]
|
383
|
-
end
|
384
|
-
|
385
|
-
INDENT = 2
|
386
|
-
def indent(&block)
|
387
|
-
@@indent += 1
|
388
|
-
begin
|
389
|
-
yield
|
390
|
-
ensure
|
391
|
-
@@indent -= 1
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
##
|
396
|
-
# section
|
397
|
-
#
|
398
|
-
# highline helper mixin which correctly formats block of say and ask
|
399
|
-
# output to have correct margins. section remembers the last margin
|
400
|
-
# used and calculates the relitive margin from the previous section.
|
401
|
-
# For example:
|
402
|
-
#
|
403
|
-
# section(bottom=1) do
|
404
|
-
# say "Hello"
|
405
|
-
# end
|
406
|
-
#
|
407
|
-
# section(top=1) do
|
408
|
-
# say "World"
|
409
|
-
# end
|
410
|
-
#
|
411
|
-
# Will output:
|
412
|
-
#
|
413
|
-
# > Hello
|
414
|
-
# >
|
415
|
-
# > World
|
416
|
-
#
|
417
|
-
# with only one newline between the two. Biggest margin wins.
|
418
|
-
#
|
419
|
-
# params:
|
420
|
-
# top - top margin specified in lines
|
421
|
-
# bottom - bottom margin specified in line
|
422
|
-
#
|
423
|
-
@@margin = nil
|
424
|
-
def section(params={}, &block)
|
425
|
-
top = params[:top] || 0
|
426
|
-
bottom = params[:bottom] || 0
|
427
|
-
|
428
|
-
# the first section cannot take a newline
|
429
|
-
top = 0 unless @@margin
|
430
|
-
@@margin = [top, @@margin || 0].max
|
431
|
-
|
432
|
-
value = block.call
|
433
|
-
|
434
|
-
say "\n" if @@last_line_open
|
435
|
-
@@margin = [bottom, @@margin].max
|
436
|
-
|
437
|
-
value
|
438
|
-
end
|
439
|
-
|
440
|
-
##
|
441
|
-
# paragraph
|
442
|
-
#
|
443
|
-
# highline helper which creates a section with margins of 1, 1
|
444
|
-
#
|
445
|
-
def paragraph(&block)
|
446
|
-
section(:top => 1, :bottom => 1, &block)
|
447
|
-
end
|
448
|
-
|
449
301
|
##
|
450
302
|
# results
|
451
303
|
#
|
@@ -465,11 +317,6 @@ module RHC
|
|
465
317
|
def unix? ; !jruby? && !windows? end
|
466
318
|
def mac? ; RbConfig::CONFIG['host_os'] =~ /^darwin/ end
|
467
319
|
|
468
|
-
def system_path(path)
|
469
|
-
return path.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if File.const_defined?('ALT_SEPARATOR') and File::ALT_SEPARATOR.present?
|
470
|
-
path
|
471
|
-
end
|
472
|
-
|
473
320
|
#
|
474
321
|
# Check if host exists
|
475
322
|
#
|
@@ -529,14 +376,5 @@ module RHC
|
|
529
376
|
|
530
377
|
[status, stdout, stderr]
|
531
378
|
end
|
532
|
-
|
533
|
-
private
|
534
|
-
|
535
|
-
def separate_blocks
|
536
|
-
if (@@margin ||= 0) > 0 && !@@last_line_open
|
537
|
-
$terminal.instance_variable_get(:@output).print "\n" * @@margin
|
538
|
-
@@margin = 0
|
539
|
-
end
|
540
|
-
end
|
541
379
|
end
|
542
380
|
end
|