rhc 0.97.17 → 0.98.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/bin/rhc +9 -9
  2. data/bin/rhc-port-forward +3 -0
  3. data/bin/rhc-sshkey +3 -0
  4. data/features/README.md +163 -35
  5. data/features/application.feature +24 -0
  6. data/features/cartridge.feature +24 -0
  7. data/features/client.feature +11 -0
  8. data/features/domain.feature +29 -0
  9. data/features/lib/rhc_helper.rb +14 -0
  10. data/features/lib/rhc_helper/app.rb +2 -8
  11. data/features/lib/rhc_helper/cartridge.rb +1 -7
  12. data/features/lib/rhc_helper/commandify.rb +37 -6
  13. data/features/lib/rhc_helper/domain.rb +5 -1
  14. data/features/lib/rhc_helper/httpify.rb +124 -60
  15. data/features/lib/rhc_helper/loggable.rb +0 -2
  16. data/features/lib/rhc_helper/persistable.rb +12 -2
  17. data/features/lib/rhc_helper/sshkey.rb +29 -0
  18. data/features/multiple_cartridge.feature +17 -0
  19. data/features/sshkey.feature +58 -0
  20. data/features/step_definitions/application_steps.rb +60 -52
  21. data/features/step_definitions/cartridge_steps.rb +22 -24
  22. data/features/step_definitions/client_steps.rb +9 -2
  23. data/features/step_definitions/domain_steps.rb +4 -0
  24. data/features/step_definitions/sshkey_steps.rb +56 -0
  25. data/features/support/assumptions.rb +37 -0
  26. data/features/support/before_hooks.rb +25 -0
  27. data/features/support/env.rb +84 -39
  28. data/features/support/key1 +27 -0
  29. data/features/support/key1.pub +1 -0
  30. data/features/support/key2 +27 -0
  31. data/features/support/key2.pub +1 -0
  32. data/features/support/key3.pub +1 -0
  33. data/features/support/ssh.sh +2 -0
  34. data/features/verify.feature +18 -159
  35. data/lib/rhc-common.rb +8 -21
  36. data/lib/rhc.rb +9 -5
  37. data/lib/rhc/autocomplete.rb +68 -0
  38. data/lib/rhc/autocomplete_templates/rhc.erb +33 -0
  39. data/lib/rhc/cli.rb +9 -6
  40. data/lib/rhc/command_runner.rb +108 -0
  41. data/lib/rhc/commands.rb +66 -132
  42. data/lib/rhc/commands/base.rb +95 -24
  43. data/lib/rhc/commands/domain.rb +33 -50
  44. data/lib/rhc/commands/port-forward.rb +81 -0
  45. data/lib/rhc/commands/setup.rb +1 -1
  46. data/lib/rhc/commands/sshkey.rb +95 -0
  47. data/lib/rhc/config.rb +108 -103
  48. data/lib/rhc/context_helper.rb +19 -0
  49. data/lib/rhc/coverage_helper.rb +1 -1
  50. data/lib/rhc/exceptions.rb +55 -4
  51. data/lib/rhc/help_formatter.rb +2 -3
  52. data/lib/rhc/helpers.rb +31 -23
  53. data/lib/{rhc-rest.rb → rhc/rest.rb} +95 -23
  54. data/lib/{rhc-rest → rhc/rest}/application.rb +1 -1
  55. data/lib/{rhc-rest → rhc/rest}/cartridge.rb +1 -1
  56. data/lib/{rhc-rest → rhc/rest}/client.rb +40 -9
  57. data/lib/{rhc-rest → rhc/rest}/domain.rb +1 -1
  58. data/lib/{rhc-rest → rhc/rest}/key.rb +11 -1
  59. data/lib/{rhc-rest → rhc/rest}/user.rb +1 -1
  60. data/lib/rhc/ssh_key_helpers.rb +10 -1
  61. data/lib/rhc/targz.rb +7 -8
  62. data/lib/rhc/usage_templates/command_help.erb +7 -6
  63. data/lib/rhc/usage_templates/help.erb +6 -9
  64. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  65. data/lib/rhc/version.rb +2 -2
  66. data/lib/rhc/wizard.rb +4 -9
  67. data/spec/coverage_helper.rb +2 -2
  68. data/spec/rest_spec_helper.rb +66 -16
  69. data/spec/rhc/cli_spec.rb +16 -5
  70. data/spec/rhc/command_spec.rb +61 -6
  71. data/spec/rhc/commands/domain_spec.rb +50 -27
  72. data/spec/rhc/commands/port-forward_spec.rb +133 -0
  73. data/spec/rhc/commands/setup_spec.rb +2 -2
  74. data/spec/rhc/commands/sshkey_spec.rb +141 -0
  75. data/spec/rhc/common_spec.rb +1 -1
  76. data/spec/rhc/config_spec.rb +6 -4
  77. data/spec/rhc/helpers_spec.rb +0 -21
  78. data/spec/rhc/rest_application_spec.rb +7 -7
  79. data/spec/rhc/rest_client_spec.rb +87 -24
  80. data/spec/rhc/rest_spec.rb +36 -36
  81. data/spec/rhc/wizard_spec.rb +3 -3
  82. data/spec/spec.opts +1 -0
  83. data/spec/spec_helper.rb +3 -3
  84. metadata +61 -31
  85. data/lib/rhc-rest/exceptions/exceptions.rb +0 -75
  86. data/test/functional/application_test.rb +0 -71
  87. data/test/functional/domain_test.rb +0 -123
  88. data/test/functional/test_credentials.rb +0 -5
  89. data/test/sample-usage.rb +0 -122
  90. data/test/support/server.rb +0 -14
  91. data/test/support/testcase.rb +0 -3
  92. data/test/test_helper.rb +0 -4
  93. data/test/unit/command_test.rb +0 -19
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env bash
2
+ ssh -o StrictHostKeyChecking=no -- "$@"
@@ -1,159 +1,18 @@
1
- Feature: Client Integration Tests
2
- @init
3
- Scenario: Setup Wizard
4
- Given the libra client tools
5
- When the setup wizard is run
6
- Then the client tools should be setup
7
-
8
- @init
9
- Scenario: Domain Creation
10
- Given the libra client tools
11
- When a new domain is needed and created
12
- Then the domain should be reserved
13
-
14
- Scenario: Domain Update
15
- Given the libra client tools
16
- And an existing domain
17
- When domain is updated
18
- Then the domain should be reserved
19
-
20
- Scenario: Domain Show
21
- Given the libra client tools
22
- And an existing domain
23
- When rhc domain is run
24
- When rhc domain show is run
25
- Then the default domain action output should equal the show action output
26
-
27
- Scenario: Domain Create Fails
28
- Given the libra client tools
29
- And an existing domain
30
- When rhc domain create is called
31
- Then the domain command should fail with an exitcode of 128
32
-
33
- Scenario: Domain Delete
34
- Given the libra client tools
35
- And an existing domain
36
- When domain is deleted
37
- Then domains should be empty
38
-
39
- Scenario: Domain Update Fails
40
- Given the libra client tools
41
- And given domains is empty
42
- When domain is updated
43
- Then the domain command should fail with an exitcode of 127
44
-
45
- @init
46
- Scenario: Domain Creation for Apps
47
- Given the libra client tools
48
- When a new domain is needed and created
49
- Then the domain should be reserved
50
-
51
- Scenario: Application Creation
52
- Given the libra client tools
53
- When 1 php-5.3 applications are created
54
- Then the applications should be accessible
55
-
56
- Scenario: Application Stopping
57
- Given the libra client tools
58
- And an existing php-5.3 application
59
- When the application is stopped
60
- Then the application should not be accessible
61
-
62
- Scenario: Application Starting
63
- Given the libra client tools
64
- And an existing php-5.3 application
65
- When the application is started
66
- Then the application should be accessible
67
-
68
- Scenario: Application Restarting
69
- Given the libra client tools
70
- And an existing php-5.3 application
71
- When the application is restarted
72
- Then the application should be accessible
73
-
74
- Scenario: Application Snapshot
75
- Given the libra client tools
76
- And an existing php-5.3 application
77
- When the application is snapshot
78
- Then the snapshot should be found
79
-
80
- Scenario: Application Tidy
81
- Given the libra client tools
82
- And an existing php-5.3 application
83
- When the application is tidied
84
- Then it should succeed
85
-
86
- Scenario: Application Show
87
- Given the libra client tools
88
- And an existing php-5.3 application
89
- When the application is shown
90
- Then it should succeed
91
-
92
- Scenario: Cartridge Add
93
- Given the libra client tools
94
- And an existing php-5.3 application
95
- When the mysql-5.1 cartridge is added
96
- Then the mysql-5.1 cartridge should be running
97
-
98
- Scenario: Cartridge Stop
99
- Given the libra client tools
100
- And an existing php-5.3 application with an embedded mysql-5.1 cartridge
101
- When the mysql-5.1 cartridge is stopped
102
- Then the mysql-5.1 cartridge should be stopped
103
-
104
- Scenario: Cartridge Start
105
- Given the libra client tools
106
- And an existing php-5.3 application with an embedded mysql-5.1 cartridge
107
- When the mysql-5.1 cartridge is started
108
- Then the mysql-5.1 cartridge should be running
109
-
110
- Scenario: Cartridge Restart
111
- Given the libra client tools
112
- And an existing php-5.3 application with an embedded mysql-5.1 cartridge
113
- When the mysql-5.1 cartridge is restarted
114
- Then the mysql-5.1 cartridge should be running
115
-
116
- Scenario: Supporting Cartridge Added
117
- Given the libra client tools
118
- And an existing php-5.3 application with an embedded mysql-5.1 cartridge
119
- When the phpmyadmin-3.4 cartridge is added
120
- Then the phpmyadmin-3.4 cartridge should be running
121
-
122
- Scenario: Conflicting Cartridge Fails
123
- Given the libra client tools
124
- And an existing php-5.3 application with embedded mysql-5.1 and phpmyadmin-3.4 cartridges
125
- Then adding the postgresql-8.5 cartridge should fail
126
-
127
- Scenario: Cartridge Removed
128
- Given the libra client tools
129
- And an existing php-5.3 application with embedded mysql-5.1 and phpmyadmin-3.4 cartridges
130
- When the phpmyadmin-3.4 cartridge is removed
131
- When the mysql-5.1 cartridge is removed
132
- Then the phpmyadmin-3.4 cartridge should be removed
133
- Then the mysql-5.1 cartridge should be removed
134
-
135
- Scenario: Add Alias
136
- Scenario: Remove Alias
137
-
138
- Scenario: Application Destroy
139
- Given the libra client tools
140
- And an existing php-5.3 application
141
- When the application is destroyed
142
- Then the application should not be accessible
143
-
144
- @init
145
- Scenario: Template Creation
146
- Scenario: Domain Changed
147
- Scenario: Template Deleted
148
- Scenario: Domain Changed Again
149
- Scenario: Domain Deleted
150
-
151
- @init
152
- Scenario: Key Added
153
- Scenario: Additional Key Added
154
- Scenario: Default Key Deleted
155
- Scenario: Key Overwritten
156
- Scenario: Key Deleted
157
-
158
- @init
159
- Scenario: Get Server Status
1
+ # these were defined before refactoring and have not been implemented yet
2
+ #Feature: Client Integration Tests
3
+ # Scenario: Add Alias
4
+ # Scenario: Remove Alias
5
+ #
6
+ # @init
7
+ # Scenario: Template Creation
8
+ # Scenario: Domain Changed
9
+ # Scenario: Template Deleted
10
+ # Scenario: Domain Changed Again
11
+ # Scenario: Domain Deleted
12
+ #
13
+ # @init
14
+ # Scenario: Key Added
15
+ # Scenario: Additional Key Added
16
+ # Scenario: Default Key Deleted
17
+ # Scenario: Key Overwritten
18
+ # Scenario: Key Deleted
data/lib/rhc-common.rb CHANGED
@@ -9,7 +9,7 @@ require 'resolv'
9
9
  require 'uri'
10
10
  require 'highline/import'
11
11
  require 'rhc'
12
- require 'rhc-rest'
12
+ require 'rhc/rest'
13
13
  require 'rhc/helpers'
14
14
  require 'rhc/config'
15
15
  require 'rhc/wizard'
@@ -337,7 +337,7 @@ end
337
337
  tempfile = `mktemp /tmp/openshift.XXXXXXXX`
338
338
  `echo "#{type} #{key}" > #{tempfile}`
339
339
  ssh_keys['keys'][name]['fingerprint'] = `ssh-keygen -lf #{tempfile}`.split(' ')[1]
340
- rescue NotImplementedError, Net::SSH::Exception
340
+ rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
341
341
  # Could be a new unsupported key type or invalid data on the server
342
342
  ssh_keys['keys'][name]['fingerprint'] = 'Key type is not recognized. Please check this key is valid.'
343
343
  end
@@ -509,7 +509,7 @@ end
509
509
  # API in order to access the rest of the logic in this function
510
510
  if scale
511
511
  end_point = "https://#{libra_server}/broker/rest/api"
512
- client = Rhc::Rest::Client.new(end_point, rhlogin, password)
512
+ client = RHC::Rest::Client.new(end_point, rhlogin, password)
513
513
 
514
514
  domain = client.find_domain(user_info['user_info']['domains'][0]['namespace'])
515
515
 
@@ -526,12 +526,12 @@ end
526
526
  health_check_path = application.health_check_path
527
527
 
528
528
  puts "DEBUG: '#{app_name}' creation returned success." if @mydebug
529
- rescue Rhc::Rest::ConnectionException, Rhc::Rest::ResourceAccessException => e
529
+ rescue RHC::Rest::ConnectionException, RHC::Rest::ResourceAccessException => e
530
530
  print_response_err(Struct::FakeResponse.new(e.message,e.code))
531
- rescue Rhc::Rest::ValidationException => e
531
+ rescue RHC::Rest::ValidationException => e
532
532
  validation_error_code = (e.code.nil?) ? 406 : e.code
533
533
  print_response_err(Struct::FakeResponse.new(e.message, validation_error_code))
534
- rescue Rhc::Rest::ServerErrorException => e
534
+ rescue RHC::Rest::ServerErrorException => e
535
535
  error_code = (e.code.nil?) ? 500 : e.code
536
536
  print_response_err(Struct::FakeResponse.new(e.message, error_code))
537
537
  end
@@ -642,9 +642,9 @@ WARNING
642
642
  unless no_git
643
643
  puts "Pulling new repo down" if @mydebug
644
644
 
645
- puts "git clone --quiet #{git_url} #{repo_dir}" if @mydebug
646
645
  quiet = (@mydebug ? ' ' : '--quiet ')
647
- git_clone = %x<git clone #{quiet} #{git_url} #{repo_dir}>
646
+ puts "git clone #{quiet}#{git_url} #{repo_dir}" if @mydebug
647
+ git_clone = %x[git clone #{quiet} #{git_url} #{repo_dir} 2>&1]
648
648
  if $?.exitstatus != 0
649
649
 
650
650
  if RHC::Helpers.windows?
@@ -1221,16 +1221,3 @@ end
1221
1221
  def get_var(key)
1222
1222
  RHC::Config[key]
1223
1223
  end
1224
-
1225
- # Public: convinience function for running the wizard
1226
- #
1227
- # Returns: false if wizard did not need to run
1228
- # true if wizard ran successfuly
1229
- # nil of there was an error
1230
- #
1231
- def default_setup_wizard
1232
- w = RHC::Wizard.new(RHC::Config)
1233
- return w.run if w.needs_configuration?
1234
-
1235
- false
1236
- end
data/lib/rhc.rb CHANGED
@@ -7,15 +7,19 @@ require 'logger'
7
7
 
8
8
  # Extend core methods
9
9
  require 'rhc/core_ext'
10
- require 'rhc/version'
11
10
 
12
11
  module RHC
13
- module Commands; end
14
-
15
- autoload :Helpers, 'rhc/helpers'
12
+ autoload :Helpers, 'rhc/helpers'
13
+ autoload :Rest, 'rhc/rest'
14
+ autoload :HelpFormatter, 'rhc/help_formatter'
15
+ autoload :CommandRunner, 'rhc/command_runner'
16
+ autoload :VERSION, 'rhc/version'
17
+ autoload :Commands, 'rhc/commands'
18
+ autoload :Config, 'rhc/config'
16
19
  end
17
20
 
21
+ require 'rhc/exceptions'
22
+
18
23
  # Replace me with proper autoloads on the module RHC
19
24
  require 'rhc-common'
20
- require 'rhc-rest'
21
25
 
@@ -0,0 +1,68 @@
1
+ require 'rhc'
2
+ require 'commander'
3
+ require 'commander/runner'
4
+ require 'commander/delegates'
5
+ require 'rhc/commands'
6
+
7
+ module RHC
8
+ class AutoCompleteBindings
9
+ attr_reader :top_level_opts, :commands
10
+ def initialize(top_level_opts, commands)
11
+ @top_level_opts = top_level_opts
12
+ @commands = commands
13
+ end
14
+ end
15
+
16
+ class AutoComplete
17
+ def initialize(script="rhc")
18
+ @script_erb = ERB.new(File.read(File.join(File.dirname(__FILE__), 'autocomplete_templates', "#{script}.erb")), nil, '-')
19
+ cli_init
20
+ # :name => {:actions => [], :switches => []}
21
+ @command_data = {}
22
+ @top_level_commands = []
23
+ @global_switches = []
24
+ Commander::Runner.instance.options.each { |o| @global_switches << o[:switches][-1] }
25
+ end
26
+
27
+ def gen()
28
+ process_data
29
+ gen_script
30
+ end
31
+
32
+ private
33
+ def cli_init
34
+ runner = RHC::CommandRunner.new([])
35
+ Commander::Runner.instance_variable_set :@singleton, runner
36
+ RHC::Commands.load.to_commander
37
+ end
38
+
39
+ def process_data
40
+ Commander::Runner.instance.commands.each_pair do |name, cmd|
41
+ next if cmd.summary.nil?
42
+
43
+ if name.rindex(' ').nil?
44
+ @top_level_commands << name
45
+ else
46
+ commands = name.split ' '
47
+ action = commands.pop
48
+ id = commands.join(' ')
49
+ data = @command_data[:"#{id}"] || {:actions => [],
50
+ :switches => []}
51
+ data[:actions] << action
52
+ @command_data[:"#{id}"] = data
53
+ end
54
+
55
+ switches = []
56
+ cmd.options { |o| switches << o[:switches][-1] if o[:switches] }
57
+ data = @command_data[:"#{name}"] || {:actions => [],
58
+ :switches => []}
59
+ data[:switches] = switches.concat(@global_switches)
60
+ @command_data[:"#{name}"] = data
61
+ end
62
+ end
63
+
64
+ def gen_script
65
+ @script_erb.result AutoCompleteBindings.new(@top_level_commands.join(' '), @command_data).get_binding
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # This is the bash auto completion script for the rhc command
3
+ #
4
+ _rhc()
5
+ {
6
+ local cur opts prev
7
+ COMPREPLY=()
8
+ cur="${COMP_WORDS[COMP_CWORD]}"
9
+ if [ $COMP_CWORD -eq 1 ]; then
10
+ opts=<%= "\"%s\"" % @top_level_opts %>
11
+ else
12
+ prev="${COMP_WORDS[@]:0:COMP_CWORD}"
13
+ SAVE_IFS=$IFS
14
+ IFS=" "
15
+ case "${prev[*]}" in
16
+ <%- for name, data in @commands %>
17
+ <%= "\"rhc %s\")" % name %>
18
+ if [[ "$cur" == -* ]]; then
19
+ opts=<%= "\"%s\"" % data[:switches].join(" ") %>
20
+ else
21
+ opts=<%= "\"%s\"" % data[:actions].join(" ") %>
22
+ fi
23
+ ;;
24
+ <%- end %>
25
+ esac
26
+ IFS=$SAVE_IFS
27
+ fi
28
+
29
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
30
+ return 0
31
+ }
32
+
33
+ complete -o default -F _rhc rhc
data/lib/rhc/cli.rb CHANGED
@@ -3,7 +3,6 @@ require 'commander'
3
3
  require 'commander/runner'
4
4
  require 'commander/delegates'
5
5
  require 'rhc/commands'
6
- require 'rhc/help_formatter'
7
6
 
8
7
  include Commander::UI
9
8
  include Commander::UI::AskForClass
@@ -22,16 +21,20 @@ module RHC
22
21
 
23
22
  def self.set_terminal
24
23
  $terminal.wrap_at = HighLine::SystemExtensions.terminal_size.first - 5 rescue 80 if $stdin.tty?
24
+ # FIXME: ANSI terminals are not default on windows but we may just be
25
+ # hitting a bug in highline if windows does support another method.
26
+ # This is a safe fix for now but needs more research.
27
+ HighLine::use_color = false if RHC::Helpers.windows?
25
28
  end
26
29
 
27
30
  def self.start(args)
28
- runner = RHC::Commands::Runner.new(args)
31
+ runner = RHC::CommandRunner.new(args)
29
32
  Commander::Runner.instance_variable_set :@singleton, runner
30
33
 
31
- program :name, 'rhc'
32
- program :version, RHC::VERSION::STRING
33
- program :description, 'Command line interface for OpenShift.'
34
- program :help_formatter, RHC::UsageHelpFormatter
34
+ program :name, 'rhc'
35
+ program :description, 'Command line interface for OpenShift.'
36
+ program :version, RHC::VERSION::STRING
37
+ program :help_formatter, RHC::HelpFormatter
35
38
 
36
39
  RHC::Commands.load.to_commander
37
40
  exit(run! || 0)
@@ -0,0 +1,108 @@
1
+ module RHC
2
+ class CommandRunner < Commander::Runner
3
+ # regex fix from git - match on word boundries
4
+ def valid_command_names_from *args
5
+ arg_string = args.delete_if { |value| value =~ /^-/ }.join ' '
6
+ commands.keys.find_all { |name| name if /^#{name}\b/.match arg_string }
7
+ end
8
+
9
+ # override so we can do our own error handling
10
+ def run!
11
+ trace = false
12
+ require_program :version, :description
13
+
14
+ trap('INT') { abort program(:int_message) } if program(:int_message)
15
+ trap('INT') { program(:int_block).call } if program(:int_block)
16
+
17
+ global_option('-h', '--help', 'Display help documentation') do
18
+ args = @args - %w[-h --help]
19
+ command(:help).run(*args)
20
+ return
21
+ end
22
+ global_option('-v', '--version', 'Display version information') { say version; return }
23
+ global_option('-t', '--trace', 'Display backtrace when an error occurs') { trace = true }
24
+
25
+ parse_global_options
26
+ remove_global_options options, @args
27
+
28
+ unless trace
29
+ begin
30
+ run_active_command
31
+ rescue InvalidCommandError => e
32
+ if provided_arguments.empty?
33
+ say RHC::HelpFormatter.new(self).render
34
+ else
35
+ RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
36
+ say "See '#{program :name} help' for a list of valid commands."
37
+ end
38
+ 1
39
+ rescue \
40
+ ArgumentError,
41
+ OptionParser::InvalidOption,
42
+ OptionParser::InvalidArgument,
43
+ OptionParser::MissingArgument => e
44
+
45
+ help_bindings = CommandHelpBindings.new(active_command, commands, Commander::Runner.instance.options)
46
+ usage = RHC::HelpFormatter.new(self).render_command(help_bindings)
47
+ RHC::Helpers.error e.message
48
+ say "\n#{usage}"
49
+ 1
50
+ rescue RHC::Exception, RHC::Rest::Exception => e
51
+ RHC::Helpers.error e.message
52
+ e.code.nil? ? 128 : e.code
53
+ end
54
+ else
55
+ run_active_command
56
+ end
57
+ end
58
+
59
+ def provided_arguments
60
+ @args[0, @args.find_index { |arg| arg.start_with?('-') } || @args.length]
61
+ end
62
+
63
+ def global_option(*args, &block)
64
+ opts = args.pop if Hash === args.last
65
+ super(*args, &block).tap do |options|
66
+ options.last.merge!(opts) if opts
67
+ end
68
+ end
69
+
70
+ def create_default_commands
71
+ command :help do |c|
72
+ c.syntax = 'rhc help <command>'
73
+ c.description = 'Display global or <command> help documentation.'
74
+ c.when_called do |args, options|
75
+ if args.empty?
76
+ say help_formatter.render
77
+ else
78
+ command = command args.join(' ')
79
+ begin
80
+ require_valid_command command
81
+ rescue InvalidCommandError => e
82
+ RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
83
+ say "See '#{program :name} help' for a list of valid commands."
84
+ next
85
+ end
86
+
87
+ help_bindings = CommandHelpBindings.new command, commands, Commander::Runner.instance.options
88
+ say help_formatter.render_command help_bindings
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ class CommandHelpBindings
96
+ def initialize(command, instance_commands, global_options)
97
+ @command = command
98
+ @actions = instance_commands.collect do |command_name, command_class|
99
+ next if command_class.summary.nil?
100
+ m = /^#{command.name} ([^ ]+)/.match(command_name)
101
+ # if we have a match and it is not an alias then we can use it
102
+ m and command_name == command_class.name ? {:name => m[1], :summary => command_class.summary || ""} : nil
103
+ end
104
+ @actions.compact!
105
+ @global_options = global_options
106
+ end
107
+ end
108
+ end