rhc 1.9.6 → 1.10.7
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/features/lib/rhc_helper.rb +0 -4
- data/features/lib/rhc_helper/app.rb +10 -10
- data/features/lib/rhc_helper/commandify.rb +6 -24
- data/features/support/before_hooks.rb +1 -1
- data/features/support/env.rb +9 -2
- data/features/support/platform_support.rb +11 -1
- data/lib/rhc/auth/basic.rb +4 -1
- data/lib/rhc/cartridge_helpers.rb +4 -8
- data/lib/rhc/commands.rb +6 -3
- data/lib/rhc/commands/alias.rb +1 -0
- data/lib/rhc/commands/app.rb +104 -67
- data/lib/rhc/commands/authorization.rb +2 -1
- data/lib/rhc/commands/base.rb +8 -1
- data/lib/rhc/commands/cartridge.rb +39 -16
- data/lib/rhc/commands/git_clone.rb +2 -1
- data/lib/rhc/commands/port_forward.rb +4 -6
- data/lib/rhc/commands/ssh.rb +54 -0
- data/lib/rhc/exceptions.rb +12 -7
- data/lib/rhc/git_helpers.rb +4 -5
- data/lib/rhc/help_formatter.rb +11 -6
- data/lib/rhc/helpers.rb +24 -3
- data/lib/rhc/highline_extensions.rb +31 -6
- data/lib/rhc/output_helpers.rb +0 -29
- data/lib/rhc/rest.rb +16 -1
- data/lib/rhc/rest/application.rb +7 -3
- data/lib/rhc/rest/base.rb +7 -2
- data/lib/rhc/rest/client.rb +7 -14
- data/lib/rhc/rest/gear_group.rb +10 -1
- data/lib/rhc/rest/mock.rb +34 -8
- data/lib/rhc/ssh_helpers.rb +144 -1
- data/lib/rhc/usage_templates/command_help.erb +16 -2
- data/spec/coverage_helper.rb +10 -7
- data/spec/rhc/commands/alias_spec.rb +28 -0
- data/spec/rhc/commands/app_spec.rb +64 -45
- data/spec/rhc/commands/authorization_spec.rb +16 -0
- data/spec/rhc/commands/cartridge_spec.rb +59 -3
- data/spec/rhc/commands/port_forward_spec.rb +6 -6
- data/spec/rhc/commands/ssh_spec.rb +125 -0
- data/spec/rhc/commands/tail_spec.rb +4 -3
- data/spec/rhc/helpers_spec.rb +70 -42
- data/spec/rhc/highline_extensions_spec.rb +23 -1
- data/spec/rhc/rest_client_spec.rb +6 -9
- data/spec/rhc/rest_spec.rb +41 -2
- data/spec/spec_helper.rb +38 -0
- metadata +336 -373
data/lib/rhc/rest.rb
CHANGED
@@ -97,7 +97,22 @@ module RHC
|
|
97
97
|
|
98
98
|
#I/O Exceptions Connection timeouts, etc
|
99
99
|
class ConnectionException < Exception; end
|
100
|
-
class TimeoutException < ConnectionException
|
100
|
+
class TimeoutException < ConnectionException
|
101
|
+
def initialize(message, nested=nil)
|
102
|
+
super(message)
|
103
|
+
@nested = nested
|
104
|
+
end
|
105
|
+
|
106
|
+
def on_receive?
|
107
|
+
@nested.is_a? HTTPClient::ReceiveTimeoutError
|
108
|
+
end
|
109
|
+
def on_connect?
|
110
|
+
@nested.is_a? HTTPClient::ConnectTimeoutError
|
111
|
+
end
|
112
|
+
def on_send?
|
113
|
+
@nested.is_a? HTTPClient::SendTimeoutError
|
114
|
+
end
|
115
|
+
end
|
101
116
|
|
102
117
|
class SSLConnectionFailed < ConnectionException
|
103
118
|
attr_reader :reason
|
data/lib/rhc/rest/application.rb
CHANGED
@@ -63,11 +63,15 @@ module RHC
|
|
63
63
|
rest_method "GET_GEAR_GROUPS"
|
64
64
|
end
|
65
65
|
|
66
|
+
def gears
|
67
|
+
gear_groups.map{ |group| group.gears }.flatten
|
68
|
+
end
|
69
|
+
|
66
70
|
def gear_ssh_url(gear_id)
|
67
|
-
gear =
|
71
|
+
gear = gears.find{ |g| g['id'] == gear_id }
|
68
72
|
|
69
|
-
raise ArgumentError
|
70
|
-
gear['ssh_url'] or raise
|
73
|
+
raise ArgumentError, "Gear #{gear_id} not found" if gear.nil?
|
74
|
+
gear['ssh_url'] or raise NoPerGearOperations
|
71
75
|
end
|
72
76
|
|
73
77
|
def tidy
|
data/lib/rhc/rest/base.rb
CHANGED
@@ -23,11 +23,16 @@ module RHC
|
|
23
23
|
url = url.gsub(/:\w+/) { |s| options[:params][s] } if options[:params]
|
24
24
|
method = options[:method] || link['method']
|
25
25
|
|
26
|
-
client.request(options.merge({
|
26
|
+
result = client.request(options.merge({
|
27
27
|
:url => url,
|
28
28
|
:method => method,
|
29
29
|
:payload => payload,
|
30
30
|
}))
|
31
|
+
if result.is_a?(Hash) && (result['messages'] || result['errors'])
|
32
|
+
attributes['messages'] = Array(result['messages'])
|
33
|
+
result = self
|
34
|
+
end
|
35
|
+
result
|
31
36
|
end
|
32
37
|
|
33
38
|
def links
|
@@ -60,4 +65,4 @@ module RHC
|
|
60
65
|
end
|
61
66
|
end
|
62
67
|
end
|
63
|
-
end
|
68
|
+
end
|
data/lib/rhc/rest/client.rb
CHANGED
@@ -175,7 +175,7 @@ module RHC
|
|
175
175
|
# The list may not necessarily be sorted; we will select the last
|
176
176
|
# matching one supported by the server.
|
177
177
|
# See #api_version_negotiated
|
178
|
-
CLIENT_API_VERSIONS = [1.1, 1.2, 1.3, 1.4]
|
178
|
+
CLIENT_API_VERSIONS = [1.1, 1.2, 1.3, 1.4, 1.5]
|
179
179
|
|
180
180
|
def initialize(*args)
|
181
181
|
options = args[0].is_a?(Hash) && args[0] || {}
|
@@ -207,8 +207,6 @@ module RHC
|
|
207
207
|
self.headers.merge!(options.delete(:headers)) if options[:headers]
|
208
208
|
self.options.merge!(options)
|
209
209
|
|
210
|
-
update_http_proxy_env
|
211
|
-
|
212
210
|
debug "Connecting to #{@end_point}"
|
213
211
|
end
|
214
212
|
|
@@ -262,7 +260,7 @@ module RHC
|
|
262
260
|
"Connection to server timed out. "\
|
263
261
|
"It is possible the operation finished without being able "\
|
264
262
|
"to report success. Use 'rhc domain show' or 'rhc app show' "\
|
265
|
-
"to see the status of your applications.")
|
263
|
+
"to see the status of your applications.", e)
|
266
264
|
rescue EOFError => e
|
267
265
|
raise ConnectionException.new(
|
268
266
|
"Connection to server got interrupted: #{e.message}")
|
@@ -306,6 +304,9 @@ module RHC
|
|
306
304
|
raise ConnectionException.new(
|
307
305
|
"Unable to connect to the server (#{e.message})."\
|
308
306
|
"#{client.proxy.present? ? " Check that you have correctly specified your proxy server '#{client.proxy}' as well as your OpenShift server '#{args[1]}'." : " Check that you have correctly specified your OpenShift server '#{args[1]}'."}")
|
307
|
+
rescue Errno::ECONNRESET => e
|
308
|
+
raise ConnectionException.new(
|
309
|
+
"The server has closed the connection unexpectedly (#{e.message}). Your last operation may still be running on the server; please check before retrying your last request.")
|
309
310
|
rescue RHC::Rest::Exception
|
310
311
|
raise
|
311
312
|
rescue => e
|
@@ -438,11 +439,11 @@ module RHC
|
|
438
439
|
def parse_response(response)
|
439
440
|
result = RHC::Json.decode(response)
|
440
441
|
type = result['type']
|
441
|
-
data = result['data']
|
442
|
+
data = result['data'] || {}
|
442
443
|
|
443
444
|
# Copy messages to each object
|
444
445
|
messages = Array(result['messages']).map do |m|
|
445
|
-
m['text'] if m['field'].nil? or m['field'] == 'result'
|
446
|
+
m['text'] if m['field'].nil? or m['field'] == 'result' or m['severity'] == 'result'
|
446
447
|
end.compact
|
447
448
|
data.each{ |d| d['messages'] = messages } if data.is_a?(Array)
|
448
449
|
data['messages'] = messages if data.is_a?(Hash)
|
@@ -559,14 +560,6 @@ module RHC
|
|
559
560
|
keys = messages.group_by{ |m| m['field'] }.keys.compact.sort.map(&:to_sym) rescue []
|
560
561
|
[messages_to_error(messages), keys]
|
561
562
|
end
|
562
|
-
|
563
|
-
def update_http_proxy_env
|
564
|
-
# Set the http_proxy env variable, read by
|
565
|
-
# HTTPClient, being sure to add the http protocol
|
566
|
-
# if not specified already
|
567
|
-
proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
|
568
|
-
ENV['http_proxy'] = "http://#{proxy}" if proxy.present? && proxy !~ /^(\w+):\/\//
|
569
|
-
end
|
570
563
|
end
|
571
564
|
end
|
572
565
|
end
|
data/lib/rhc/rest/gear_group.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
module RHC
|
2
2
|
module Rest
|
3
3
|
class GearGroup < Base
|
4
|
-
define_attr :gears, :cartridges, :gear_profile
|
4
|
+
define_attr :gears, :cartridges, :gear_profile, :additional_gear_storage, :base_gear_storage
|
5
|
+
|
6
|
+
def name(gear)
|
7
|
+
gear['name'] ||= "#{group.cartridges.collect{ |c| c['name'] }.join('+')}:#{gear['id']}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def quota
|
11
|
+
return nil unless base_gear_storage
|
12
|
+
((additional_gear_storage || 0) + base_gear_storage) * 1024 * 1024 * 1024
|
13
|
+
end
|
5
14
|
end
|
6
15
|
end
|
7
16
|
end
|
data/lib/rhc/rest/mock.rb
CHANGED
@@ -52,7 +52,7 @@ module RHC::Rest::Mock
|
|
52
52
|
to_return({
|
53
53
|
:body => {
|
54
54
|
:data => mock_response_links(authorizations ? mock_api_with_authorizations : mock_real_client_links),
|
55
|
-
:supported_api_versions => [1.0, 1.1, 1.2, 1.3, 1.4],
|
55
|
+
:supported_api_versions => [1.0, 1.1, 1.2, 1.3, 1.4, 1.5],
|
56
56
|
}.to_json
|
57
57
|
})
|
58
58
|
end
|
@@ -208,6 +208,21 @@ module RHC::Rest::Mock
|
|
208
208
|
})
|
209
209
|
end
|
210
210
|
|
211
|
+
def stub_application_cartridges(domain_name, app_name, cartridges, status = 200)
|
212
|
+
url = client_links['LIST_DOMAINS']['relative'] rescue "broker/rest/domains"
|
213
|
+
stub_api_request(:any, "#{url}/#{domain_name}/applications/#{app_name}/cartridges").
|
214
|
+
to_return({
|
215
|
+
:body => {
|
216
|
+
:type => 'cartridges',
|
217
|
+
:data => cartridges.map{ |c| c.is_a?(String) ? {:name => c} : c }.map do |cart|
|
218
|
+
cart[:links] ||= mock_response_links(mock_cart_links(domain_name,app_name, cart[:name]))
|
219
|
+
cart
|
220
|
+
end
|
221
|
+
}.to_json,
|
222
|
+
:status => status
|
223
|
+
})
|
224
|
+
end
|
225
|
+
|
211
226
|
def stub_simple_carts
|
212
227
|
stub_api_request(:get, 'broker/rest/cartridges', mock_user_auth).to_return(simple_carts)
|
213
228
|
end
|
@@ -324,7 +339,7 @@ module RHC::Rest::Mock
|
|
324
339
|
|
325
340
|
def mock_app_links(domain_id='test_domain',app_id='test_app')
|
326
341
|
[['ADD_CARTRIDGE', "domains/#{domain_id}/apps/#{app_id}/carts/add", 'post'],
|
327
|
-
['LIST_CARTRIDGES', "domains/#{domain_id}/
|
342
|
+
['LIST_CARTRIDGES', "broker/rest/domains/#{domain_id}/applications/#{app_id}/cartridges",'get' ],
|
328
343
|
['GET_GEAR_GROUPS', "domains/#{domain_id}/apps/#{app_id}/gear_groups", 'get' ],
|
329
344
|
['START', "domains/#{domain_id}/apps/#{app_id}/start", 'post'],
|
330
345
|
['STOP', "domains/#{domain_id}/apps/#{app_id}/stop", 'post'],
|
@@ -333,14 +348,14 @@ module RHC::Rest::Mock
|
|
333
348
|
['ADD_ALIAS', "domains/#{domain_id}/apps/#{app_id}/event", 'post'],
|
334
349
|
['REMOVE_ALIAS', "domains/#{domain_id}/apps/#{app_id}/event", 'post'],
|
335
350
|
['LIST_ALIASES', "domains/#{domain_id}/apps/#{app_id}/aliases", 'get'],
|
336
|
-
['DELETE', "domains/#{domain_id}/
|
351
|
+
['DELETE', "broker/rest/domains/#{domain_id}/applications/#{app_id}", 'DELETE']]
|
337
352
|
end
|
338
353
|
|
339
354
|
def mock_cart_links(domain_id='test_domain',app_id='test_app',cart_id='test_cart')
|
340
355
|
[['START', "domains/#{domain_id}/apps/#{app_id}/carts/#{cart_id}/start", 'post'],
|
341
356
|
['STOP', "domains/#{domain_id}/apps/#{app_id}/carts/#{cart_id}/stop", 'post'],
|
342
357
|
['RESTART', "domains/#{domain_id}/apps/#{app_id}/carts/#{cart_id}/restart", 'post'],
|
343
|
-
['DELETE', "domains/#{domain_id}/
|
358
|
+
['DELETE', "broker/rest/domains/#{domain_id}/applications/#{app_id}/cartridges/#{cart_id}", 'DELETE']]
|
344
359
|
end
|
345
360
|
|
346
361
|
def mock_client_links
|
@@ -487,6 +502,8 @@ module RHC::Rest::Mock
|
|
487
502
|
MockRestCartridge.new(self, "mock_cart-2", "embedded"),
|
488
503
|
MockRestCartridge.new(self, "unique_mock_cart-1", "embedded"),
|
489
504
|
MockRestCartridge.new(self, "jenkins-client-1.4", "embedded"),
|
505
|
+
MockRestCartridge.new(self, "embcart-1", "embedded"),
|
506
|
+
MockRestCartridge.new(self, "embcart-2", "embedded"),
|
490
507
|
premium_embedded
|
491
508
|
]
|
492
509
|
end
|
@@ -601,11 +618,14 @@ module RHC::Rest::Mock
|
|
601
618
|
|
602
619
|
class MockRestGearGroup < RHC::Rest::GearGroup
|
603
620
|
include Helpers
|
604
|
-
def initialize(client=nil)
|
621
|
+
def initialize(client=nil, carts=['name' => 'fake_geargroup_cart-0.1'], count=1)
|
605
622
|
super({}, client)
|
606
|
-
@cartridges =
|
607
|
-
@gears =
|
623
|
+
@cartridges = carts
|
624
|
+
@gears = count.times.map do |i|
|
625
|
+
{'state' => 'started', 'id' => "fakegearid#{i}", 'ssh_url' => "ssh://fakegearid#{i}@fakesshurl.com"}
|
626
|
+
end
|
608
627
|
@gear_profile = 'small'
|
628
|
+
@base_gear_storage = 1
|
609
629
|
end
|
610
630
|
end
|
611
631
|
|
@@ -710,7 +730,13 @@ module RHC::Rest::Mock
|
|
710
730
|
|
711
731
|
def gear_groups
|
712
732
|
# we don't have heavy interaction with gear groups yet so keep this simple
|
713
|
-
@gear_groups ||=
|
733
|
+
@gear_groups ||= begin
|
734
|
+
if @scalable
|
735
|
+
cartridges.map{ |c| MockRestGearGroup.new(client, [c.name], c.current_scale) if c.name != 'haproxy-1.4' }.compact
|
736
|
+
else
|
737
|
+
[MockRestGearGroup.new(client, cartridges.map{ |c| {'name' => c.name} }, 1)]
|
738
|
+
end
|
739
|
+
end
|
714
740
|
end
|
715
741
|
|
716
742
|
def cartridges
|
data/lib/rhc/ssh_helpers.rb
CHANGED
@@ -20,6 +20,134 @@ require 'rhc/vendor/sshkey'
|
|
20
20
|
|
21
21
|
module RHC
|
22
22
|
module SSHHelpers
|
23
|
+
|
24
|
+
class MultipleGearTask
|
25
|
+
def initialize(command, over, opts={})
|
26
|
+
requires_ssh_multi!
|
27
|
+
|
28
|
+
@command = command
|
29
|
+
@over = over
|
30
|
+
@opts = opts
|
31
|
+
end
|
32
|
+
|
33
|
+
def run(&block)
|
34
|
+
out = nil
|
35
|
+
|
36
|
+
Net::SSH::Multi.start(
|
37
|
+
:concurrent_connections => @opts[:limit],
|
38
|
+
:on_error => lambda{ |server| $stderr.puts "Unable to connect to gear #{server}" }
|
39
|
+
) do |session|
|
40
|
+
|
41
|
+
@over.each do |item|
|
42
|
+
case item
|
43
|
+
when RHC::Rest::GearGroup
|
44
|
+
item.gears.each do |gear|
|
45
|
+
session.use ssh_host_for(gear), :properties => {:gear => gear, :group => item}
|
46
|
+
end
|
47
|
+
#when RHC::Rest::Gear
|
48
|
+
# session.use ssh_host_for(item), :properties => {:gear => item}
|
49
|
+
#end
|
50
|
+
else
|
51
|
+
raise "Cannot establish an SSH session to this type"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
session.exec @command, &(
|
55
|
+
case
|
56
|
+
when @opts[:raw]
|
57
|
+
lambda { |ch, dest, data|
|
58
|
+
(dest == :stdout ? $stdout : $stderr).puts data
|
59
|
+
}
|
60
|
+
when @opts[:as] == :table
|
61
|
+
out = []
|
62
|
+
lambda { |ch, dest, data|
|
63
|
+
label = label_for(ch)
|
64
|
+
data.chomp.each_line do |line|
|
65
|
+
row = out.find{ |row| row[0] == label } || (out << [label, []])[-1]
|
66
|
+
row[1] << line
|
67
|
+
end
|
68
|
+
}
|
69
|
+
when @opts[:as] == :gear
|
70
|
+
lambda { |ch, dest, data| (ch.connection.properties[:gear]['data'] ||= "") << data }
|
71
|
+
else
|
72
|
+
width = 0
|
73
|
+
lambda { |ch, dest, data|
|
74
|
+
label = label_for(ch)
|
75
|
+
io = dest == :stdout ? $stdout : $stderr
|
76
|
+
data.chomp!
|
77
|
+
|
78
|
+
if data.each_line.to_a.count < 2
|
79
|
+
io.puts "[#{label}] #{data}"
|
80
|
+
elsif @opts[:always_prefix]
|
81
|
+
data.each_line do |line|
|
82
|
+
io.puts "[#{label}] #{line}"
|
83
|
+
end
|
84
|
+
else
|
85
|
+
io.puts "=== #{label}"
|
86
|
+
io.puts data
|
87
|
+
end
|
88
|
+
}
|
89
|
+
end)
|
90
|
+
session.loop
|
91
|
+
end
|
92
|
+
|
93
|
+
if block_given? && !@opts[:raw]
|
94
|
+
case
|
95
|
+
when @opts[:as] == :gear
|
96
|
+
out = []
|
97
|
+
@over.each do |item|
|
98
|
+
case item
|
99
|
+
when RHC::Rest::GearGroup then item.gears.each{ |gear| out << yield(gear, gear['data'], item) }
|
100
|
+
#when RHC::Rest::Gear then out << yield(gear, gear['data'], nil)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
out
|
107
|
+
end
|
108
|
+
protected
|
109
|
+
def ssh_host_for(gear)
|
110
|
+
RHC::Helpers.ssh_string(gear['ssh_url']) or raise NoPerGearOperations
|
111
|
+
end
|
112
|
+
|
113
|
+
def label_for(channel)
|
114
|
+
channel.properties[:label] ||=
|
115
|
+
begin
|
116
|
+
group = channel.connection.properties[:group]
|
117
|
+
"#{key_for(channel)} #{group.cartridges.map{ |c| c['name'] }.join('+')}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def key_for(channel)
|
122
|
+
channel.connection.properties[:gear]['id']
|
123
|
+
end
|
124
|
+
|
125
|
+
def requires_ssh_multi!
|
126
|
+
begin
|
127
|
+
require 'net/ssh/multi'
|
128
|
+
rescue LoadError
|
129
|
+
raise RHC::OperationNotSupportedException, "You must install Net::SSH::Multi to use the --gears option. Most systems: 'gem install net-ssh-multi'"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def run_on_gears(command, gears, opts={}, &block)
|
135
|
+
debug "Executing #{command} on each of #{gears.inspect}"
|
136
|
+
MultipleGearTask.new(command, gears, {:limit => options.limit, :always_prefix => options.always_prefix, :raw => options.raw}.merge(opts)).run(&block)
|
137
|
+
end
|
138
|
+
|
139
|
+
def table_from_gears(command, groups, opts={}, &block)
|
140
|
+
cells = run_on_gears(command, groups, {:as => :table}.merge(opts), &block)
|
141
|
+
cells.each{ |r| r.concat(r.pop.first.split(opts[:split_cells_on])) } if !block_given? && opts[:split_cells_on]
|
142
|
+
say table cells, opts unless options.raw
|
143
|
+
end
|
144
|
+
|
145
|
+
def ssh_command_for_op(operation)
|
146
|
+
#case operation
|
147
|
+
raise RHC::OperationNotSupportedException, "The operation #{operation} is not supported."
|
148
|
+
#end
|
149
|
+
end
|
150
|
+
|
23
151
|
# Public: Run ssh command on remote host
|
24
152
|
#
|
25
153
|
# host - The String of the remote hostname to ssh to.
|
@@ -100,7 +228,6 @@ module RHC
|
|
100
228
|
end
|
101
229
|
end
|
102
230
|
|
103
|
-
|
104
231
|
# For Net::SSH versions (< 2.0.11) that does not have
|
105
232
|
# Net::SSH::KeyFactory.load_public_key, we drop to shell to get
|
106
233
|
# the key's fingerprint
|
@@ -147,6 +274,22 @@ module RHC
|
|
147
274
|
ssh_key_triple_for(RHC::Config.ssh_pub_key_file_path)
|
148
275
|
end
|
149
276
|
|
277
|
+
# check the version of SSH that is installed
|
278
|
+
def ssh_version
|
279
|
+
@ssh_version ||= `ssh -V 2>&1`.strip
|
280
|
+
end
|
281
|
+
|
282
|
+
# return whether or not SSH is installed
|
283
|
+
def has_ssh?
|
284
|
+
@has_ssh ||= begin
|
285
|
+
@ssh_version = nil
|
286
|
+
ssh_version
|
287
|
+
$?.success?
|
288
|
+
rescue
|
289
|
+
false
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
150
293
|
private
|
151
294
|
|
152
295
|
def ssh_add
|
@@ -1,7 +1,20 @@
|
|
1
1
|
Usage: <%= Array(program :name).first %> <%= @command.name %> <%= @command.syntax %>
|
2
2
|
|
3
3
|
<%= @command.description || @command.summary %>
|
4
|
-
<% if @actions.blank? -%>
|
4
|
+
<% if @actions.blank? or @command.root? and @command.info[:method].present? -%>
|
5
|
+
|
6
|
+
<% unless @command.info[:args].blank? or @command.options.all?{ |o| o[:hide] or o[:switches].present? } -%>
|
7
|
+
|
8
|
+
Arguments
|
9
|
+
<%= table(
|
10
|
+
@command.info[:args].select do |opt|
|
11
|
+
not opt[:hide] and not opt[:switches].present?
|
12
|
+
end.map do |opt|
|
13
|
+
[opt[:name], opt[:description]]
|
14
|
+
end,
|
15
|
+
table_args(' ', 25)
|
16
|
+
).join("\n") %>
|
17
|
+
<% end -%>
|
5
18
|
<% unless @command.options.blank? or @command.options.all?{ |o| o[:hide] } -%>
|
6
19
|
|
7
20
|
Options
|
@@ -26,7 +39,8 @@ Global Options
|
|
26
39
|
).join("\n") %>
|
27
40
|
|
28
41
|
See 'rhc help options' for a full list of global options.
|
29
|
-
<%
|
42
|
+
<% end -%>
|
43
|
+
<% if @actions.present? -%>
|
30
44
|
|
31
45
|
List of Actions
|
32
46
|
<%= table(@actions.map{ |a| [a[:name], a[:summary]] }, table_args(' ', 13)).join("\n") %>
|
data/spec/coverage_helper.rb
CHANGED
@@ -16,19 +16,22 @@ unless RUBY_VERSION < '1.9'
|
|
16
16
|
def print_missed_lines
|
17
17
|
@files.each do |file|
|
18
18
|
file.missed_lines.each do |line|
|
19
|
-
puts "MISSED #{file.filename}:#{line.number}"
|
19
|
+
STDERR.puts "MISSED #{file.filename}:#{line.number}"
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
original_stderr = $stderr # in case helpers don't properly cleanup
|
26
25
|
SimpleCov.at_exit do
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
begin
|
27
|
+
SimpleCov.result.format!
|
28
|
+
if SimpleCov.result.covered_percent < 100.0
|
29
|
+
SimpleCov.result.print_missed_lines if SimpleCov.result.covered_percent > 98.0
|
30
|
+
STDERR.puts "Coverage not 100%, build failed."
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
rescue Exception => e
|
34
|
+
STDERR.puts "Exception at exit, #{e.message}"
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|