rhc 1.0.4 → 1.1.11

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.
@@ -526,8 +526,13 @@ class CheckRunner < Test::Unit::UI::Console::TestRunner
526
526
  end
527
527
  end
528
528
 
529
- Test::Unit::AutoRunner::RUNNERS[:console] = proc do |r|
530
- CheckRunner
529
+ # Need to register the default runner differently using the standard test-unit and the gem
530
+ proc{|*r| CheckRunner}.tap do |_proc|
531
+ if Test::Unit::AutoRunner.respond_to?(:register_runner)
532
+ Test::Unit::AutoRunner.register_runner(:console, _proc)
533
+ else
534
+ Test::Unit::AutoRunner::RUNNERS[:console] = _proc
535
+ end
531
536
  end
532
537
 
533
538
  ############################
@@ -1,6 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- # print deprecation warning
3
- RHC::Helpers.deprecated_command('rhc-domain-info',true)
4
2
 
5
3
  args = ""
6
4
  ARGV.each do|a|
@@ -22,3 +22,13 @@ Feature: Single Cartridge Tests
22
22
  | running | restarted | running |
23
23
  | running | stopped | stopped |
24
24
  | stopped | started | running |
25
+
26
+ Scenario Outline: Cartridge List
27
+ When we list cartridges
28
+ Then the list should contain the cartridge <cart> with display name "<name>"
29
+
30
+ Examples:
31
+ | cart | name |
32
+ | php-5.3 | PHP 5.3 |
33
+ | mongodb-2.2 | MongoDB NoSQL |
34
+ | cron-1.4 | Cron 1.4 |
@@ -7,6 +7,7 @@ module RHCHelper
7
7
  #
8
8
  class Cartridge
9
9
  extend Runnable
10
+ extend Commandify
10
11
  extend Persistable
11
12
  include Loggable
12
13
  include Runnable
@@ -19,19 +20,25 @@ module RHCHelper
19
20
  # Create the data structure for a test cartridge
20
21
  def initialize(app, name)
21
22
  @name = name
22
- @app_name = app.name
23
+ @app_name = app.name unless app.nil?
23
24
  @hostname = "#{@app_name}-#{$namespace}.#{$domain}"
24
25
  @file = "#{TEMP_DIR}/#{$namespace}.json"
25
26
  end
26
27
 
27
28
  def rhc_cartridge(cmd)
28
- full_cmd = "rhc cartridge #{cmd} -l #{$username} -p #{$password} -a #{@app_name}"
29
+ full_cmd = "rhc cartridge #{cmd} -l #{$username} -p #{$password} #{@app_name ? "-a #{@app_name}" : ""}"
29
30
  full_cmd += " #{@name}" if cmd != "list"
30
31
  run(full_cmd, nil) do |exitstatus, out, err, arg|
31
32
  yield exitstatus, out, err, arg if block_given?
32
33
  end
33
34
  end
34
35
 
36
+ def self.list
37
+ rhc_cartridge_list do |exitstatus, out, err, arg|
38
+ return [exitstatus, out, err, arg]
39
+ end
40
+ end
41
+
35
42
  def add
36
43
  rhc_cartridge('add') do |exitstatus, out, err, arg|
37
44
  yield exitstatus, out, err, arg if block_given?
@@ -11,7 +11,7 @@ module RHCHelper
11
11
  cmd = get_cmd(sym)
12
12
 
13
13
  # Get any blocks that should be run after processing
14
- cmd_callback = get_cmd_callback(cmd, args[0])
14
+ cmd_callback = get_cmd_callback(cmd, args[0]) || block
15
15
 
16
16
  # Add arguments to the command
17
17
  cmd << get_args(cmd, args[0])
@@ -85,8 +85,7 @@ module RHCHelper
85
85
  raise "No alias set" unless @alias
86
86
  args << "--alias #{@alias} "
87
87
  when /cartridge/
88
- raise "No cartridge supplied" unless arg0
89
- args << "-c #{arg0}"
88
+ args << "-c #{arg0}" if arg0
90
89
  when /sshkey/
91
90
  # in RHCHelper::Sshkey, we pass *args to method_missing here, so that
92
91
  # we _know_ that arg0 is an Array.
@@ -47,6 +47,10 @@ When /^the (\w+) scaling value is set to (.*)$/ do |minmax,value|
47
47
  @exitcode = @app.cartridge(@cartridge_name).send(:scale,"--#{minmax} #{value}")
48
48
  end
49
49
 
50
+ When /^we list cartridges$/ do
51
+ @exitcode, @cartridge_output = Cartridge.list
52
+ end
53
+
50
54
  Then /^the (\w+) scaling value should be (.*)$/ do |minmax,value|
51
55
  expected = {
52
56
  :min => "Minimum",
@@ -64,3 +68,9 @@ end
64
68
  Then /^it should fail with code (\d+)$/ do |code|
65
69
  @exitcode.should == code.to_i
66
70
  end
71
+
72
+ Then /^the list should contain the cartridge ([^\s]+) with display name "([^"]+)"$/ do |name, display_name|
73
+ line = @cartridge_output.each_line.find{ |s| s.include?(name) }
74
+ line.should_not be_nil
75
+ line.should match(display_name)
76
+ end
@@ -471,9 +471,7 @@ end
471
471
  # Check if host exists
472
472
  #
473
473
  def self.hostexist?(host)
474
- dns = Resolv::DNS.new
475
- resp = dns.getresources(host, Resolv::DNS::Resource::IN::A)
476
- return resp.any?
474
+ RHC::Helpers.host_exists?(host)
477
475
  end
478
476
 
479
477
  def self.create_app(libra_server, net_http, user_info, app_name, app_type, rhlogin, password, repo_dir=nil, no_dns=false, no_git=false, is_embedded_jenkins=false, gear_size='small',scale=false)
@@ -1,5 +1,6 @@
1
1
  module RHC
2
2
  module CartridgeHelpers
3
+
3
4
  def find_cartridge(rest_obj, cartridge_name, type="embedded")
4
5
  carts = rest_obj.find_cartridges :regex => cart_regex(cartridge_name), :type => type
5
6
 
@@ -35,10 +35,6 @@ module RHC
35
35
  return
36
36
  end
37
37
  global_option('-v', '--version', 'Display version information') { say version; return }
38
- global_option('--timeout seconds', Integer, 'Set the timeout in seconds for network commands') do |value|
39
- # FIXME: Refactor so we don't have to use a global var here
40
- $rest_timeout = value
41
- end
42
38
 
43
39
  # remove these because we monkey patch Commands to process all options
44
40
  # at once, avoiding conflicts between the global and command options
@@ -71,9 +67,9 @@ module RHC
71
67
  OptionParser::MissingArgument => e
72
68
 
73
69
  help_bindings = CommandHelpBindings.new(active_command, commands, Commander::Runner.instance.options)
74
- usage = RHC::HelpFormatter.new(self).render_command(help_bindings)
70
+ usage = RHC::HelpFormatter.new(self).render_command_syntax(help_bindings)
75
71
  RHC::Helpers.error e.message
76
- say "\n#{usage}"
72
+ say "#{usage}"
77
73
  1
78
74
  rescue RHC::Exception, RHC::Rest::Exception => e
79
75
  RHC::Helpers.error e.message
@@ -100,18 +96,16 @@ module RHC
100
96
  c.syntax = 'rhc help <command>'
101
97
  c.description = 'Display global or <command> help documentation.'
102
98
  c.when_called do |args, options|
99
+ cmd = (1..args.length).reverse_each.map{ |n| args[0,n].join(' ') }.find{ |cmd| command_exists?(cmd) }
100
+
103
101
  if args.empty?
104
102
  say help_formatter.render
103
+ elsif cmd.nil?
104
+ RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
105
+ say "See '#{program :name} help' for a list of valid commands."
106
+ next
105
107
  else
106
- command = command args.join(' ')
107
- begin
108
- require_valid_command command
109
- rescue InvalidCommandError => e
110
- RHC::Helpers.error "The command '#{program :name} #{provided_arguments.join(' ')}' is not recognized.\n"
111
- say "See '#{program :name} help' for a list of valid commands."
112
- next
113
- end
114
-
108
+ command = command(cmd)
115
109
  help_bindings = CommandHelpBindings.new command, commands, Commander::Runner.instance.options
116
110
  say help_formatter.render_command help_bindings
117
111
  end
@@ -66,7 +66,10 @@ module RHC
66
66
  options.help or
67
67
  config.has_local_config? or
68
68
  config.has_opts_config?)
69
- RHC::Wizard.new(config).run
69
+
70
+ RHC::Helpers.warn(
71
+ "You have not yet configured the OpenShift client tools. Please run 'rhc setup'.",
72
+ :stderr => true)
70
73
  end
71
74
  end
72
75
 
@@ -1,7 +1,7 @@
1
1
  require 'rhc/commands/base'
2
2
  require 'resolv'
3
3
  require 'rhc/git_helper'
4
- require 'rhc/cartridge_helper'
4
+ require 'rhc/cartridge_helpers'
5
5
 
6
6
  module RHC::Commands
7
7
  class App < Base
@@ -11,24 +11,26 @@ module RHC::Commands
11
11
  default_action :help
12
12
 
13
13
  summary "Create an application and adds it to a domain"
14
- syntax "<name> <cartridge> [... <other cartridges>][--namespace namespace]"
15
- option ["-n", "--namespace namespace"], "Namespace to add your application to", :context => :namespace_context, :required => true
16
- option ["-g", "--gear-size size"], "The size of the gear for this app. Available gear sizes depend on the type of account you have."
17
- option ["-s", "--scaling"], "Enable scaling for this application"
18
- option ["-r", "--repo dir"], "Git Repo path (defaults to ./$app_name) (applicable to the create command)"
19
- option ["--[no-]git"], "Only create remote space, don't pull it locally"
20
- option ["--nogit"], "DEPRECATED! Only create remote space, don't pull it locally", :deprecated => {:key => :git, :value => false}
21
- option ["--[no-]dns"], "Skip DNS check. Must be used in combination with --no-git"
22
- option ["--enable-jenkins [server_name]"], "Indicates to create a Jenkins application (if not already available) and embed the Jenkins client into this application. The default name will be 'jenkins' if not specified. Note that --no-dns is ignored for the creation of the Jenkins application."
23
- argument :name, "The name you wish to give your application", ["-a", "--app name"]
24
- argument :cartridge, "The first cartridge added to the application. Usually a web framework", ["-t", "--type cartridge"]
25
- argument :additional_cartridges, "A list of other cartridges such as databases you wish to add. Cartridges can also be added later using 'rhc cartridge add'", [], :arg_type => :list
26
- def create(name, cartridge, additional_cartridges)
14
+ description "Create an application in your domain. You can see a list of all valid cartridge types by running 'rhc cartridge list'."
15
+ syntax "<name> <cartridge> [-n namespace]"
16
+ option ["-n", "--namespace namespace"], "Namespace for the application", :context => :namespace_context, :required => true
17
+ option ["-g", "--gear-size size"], "Gear size controls how much memory and CPU your cartridges can use."
18
+ option ["-s", "--scaling"], "Enable scaling for the web cartridge."
19
+ option ["-r", "--repo dir"], "Path to the Git repository (defaults to ./$app_name)"
20
+ option ["--[no-]git"], "Skip creating the local Git repository."
21
+ option ["--nogit"], "DEPRECATED: Skip creating the local Git repository.", :deprecated => {:key => :git, :value => false}
22
+ option ["--[no-]dns"], "Skip waiting for the application DNS name to resolve. Must be used in combination with --no-git"
23
+ option ["--enable-jenkins [server_name]"], "Enable Jenkins builds for this application (will create a Jenkins application if not already available). The default name will be 'jenkins' if not specified."
24
+ argument :name, "Name for your application", ["-a", "--app name"]
25
+ argument :cartridges, "The web framework this application should use", ["-t", "--type cartridge"], :arg_type => :list
26
+ #argument :additional_cartridges, "A list of other cartridges such as databases you wish to add. Cartridges can also be added later using 'rhc cartridge add'", [], :arg_type => :list
27
+ def create(name, cartridges)
28
+ cartridge = check_cartridges(cartridges).first
29
+
27
30
  options.default \
28
31
  :dns => true,
29
32
  :git => true
30
33
 
31
- warnings = []
32
34
  header "Creating application '#{name}'"
33
35
  paragraph do
34
36
  table({"Namespace:" => options.namespace,
@@ -72,7 +74,7 @@ module RHC::Commands
72
74
  # error downloading Jenkins /jnlpJars/jenkins-cli.jar
73
75
  attempts += 1
74
76
  debug "Jenkins server could not be contacted, sleep and then retry: attempt #{attempts}\n #{e.message}"
75
- sleep(10)
77
+ Kernel.sleep(10)
76
78
  end
77
79
  exit_code = e.code
78
80
  exit_message = e.message
@@ -269,6 +271,42 @@ module RHC::Commands
269
271
  include RHC::GitHelpers
270
272
  include RHC::CartridgeHelpers
271
273
 
274
+ def standalone_cartridges
275
+ @standalone_cartridges ||= rest_client.cartridges.select{ |c| c.type == 'standalone' }
276
+ end
277
+
278
+ def check_cartridges(cartridge_names)
279
+ cartridge_names = Array(cartridge_names).map{ |s| s.strip if s && s.length > 0 }.compact
280
+
281
+ unless cartridge_name = cartridge_names.first
282
+ section(:bottom => 1){ list_cartridges }
283
+ raise ArgumentError.new "Every application needs a web cartridge to handle incoming web requests. Please provide the short name of one of the carts listed above."
284
+ end
285
+
286
+ unless standalone_cartridges.find{ |c| c.name == cartridge_name }
287
+ matching_cartridges = standalone_cartridges.select{ |c| c.name.include?(cartridge_name) }
288
+ if matching_cartridges.length == 1
289
+ cartridge_names[0] = use_cart(matching_cartridges.first, cartridge_name)
290
+ elsif matching_cartridges.present?
291
+ paragraph { list_cartridges(matching_cartridges) }
292
+ raise RHC::MultipleCartridgesException.new("There are multiple web cartridges named '#{cartridge_name}'. Please provide the short name of your desired cart.")
293
+ end
294
+ end
295
+ cartridge_names.first(1)
296
+ end
297
+
298
+ def use_cart(cart, for_cartridge_name)
299
+ info "Using #{cart.name}#{cart.display_name ? " (#{cart.display_name})" : ''} instead of '#{for_cartridge_name}'"
300
+ cart.name
301
+ end
302
+
303
+ def list_cartridges(cartridges=standalone_cartridges)
304
+ carts = cartridges.map{ |c| [c.name, c.display_name || ''] }.sort{ |a,b| a[1].downcase <=> b[1].downcase }
305
+ carts.unshift ['==========', '=========']
306
+ carts.unshift ['Short Name', 'Full name']
307
+ say table(carts).join("\n")
308
+ end
309
+
272
310
  def app_action(app, action, *args)
273
311
  rest_domain = rest_client.find_domain(options.namespace)
274
312
  rest_app = rest_domain.find_application(app)
@@ -282,16 +320,17 @@ module RHC::Commands
282
320
  app_options[:scale] = scale if scale
283
321
  app_options[:debug] = true if @debug
284
322
 
285
- debug "Creating application '#{name}' with these options - #{app_options}.inspect"
286
-
287
- rest_cartridge = find_cartridge rest_client, cartridge, "standalone"
288
- app_options[:cartridge] = rest_cartridge.name
289
-
323
+ debug "Creating application '#{name}' with these options - #{app_options.inspect}"
290
324
  rest_app = rest_domain.add_application name, app_options
291
-
292
325
  debug "'#{rest_app.name}' created"
293
326
 
294
327
  rest_app
328
+ rescue RHC::Rest::Exception => e
329
+ if e.code == 109
330
+ paragraph{ say "Valid cartridge types:" }
331
+ paragraph{ list_cartridges }
332
+ end
333
+ raise
295
334
  end
296
335
 
297
336
  def dns_propagated?(host, sleep_time=2)
@@ -307,7 +346,7 @@ module RHC::Commands
307
346
 
308
347
  # Now start checking for DNS
309
348
  for i in 0..MAX_RETRIES-1
310
- found = host_exist?(host)
349
+ found = host_exists?(host)
311
350
  break if found
312
351
 
313
352
  say " retry # #{i+1} - Waiting for DNS: #{host}"
@@ -320,13 +359,6 @@ module RHC::Commands
320
359
  found
321
360
  end
322
361
 
323
- def host_exist?(host)
324
- # :nocov:
325
- dns = Resolv::DNS.new
326
- dns.getresources(host, Resolv::DNS::Resource::IN::A).any?
327
- # :nocov:
328
- end
329
-
330
362
  def check_sshkeys!
331
363
  wizard = RHC::SSHWizard.new(rest_client)
332
364
  wizard.run
@@ -59,7 +59,7 @@ class RHC::Commands::Base
59
59
  end
60
60
  end
61
61
 
62
- raise ArgumentError.new("Too many arguments passed in.") unless fill_args.empty?
62
+ raise ArgumentError.new("Too many arguments passed in: #{fill_args.reverse.join(" ")}") unless fill_args.empty?
63
63
 
64
64
  arg_slots
65
65
  end
@@ -1,5 +1,5 @@
1
1
  require 'rhc/commands/base'
2
- require 'rhc/cartridge_helper'
2
+ require 'rhc/cartridge_helpers'
3
3
 
4
4
  module RHC::Commands
5
5
  class Cartridge < Base
@@ -11,8 +11,25 @@ module RHC::Commands
11
11
  summary "List supported embedded cartridges"
12
12
  alias_action :"app cartridge list", :root_command => true, :deprecated => true
13
13
  def list
14
- carts = rest_client.find_cartridges(:type => 'embedded').collect { |c| c.name }
15
- results { say "#{carts.join(', ')}" }
14
+ rest_client = RHC::Rest::Client.new(openshift_rest_node, nil, nil)
15
+ list = rest_client.cartridges.
16
+ map{ |c| [c.name, c.display_name || '', c.type == 'standalone' ? 'Y' : ''] }.
17
+ sort do |a,b|
18
+ if a[2] == 'Y' && b[2] == ''
19
+ -1
20
+ elsif a[2] == '' && b[2] == 'Y'
21
+ 1
22
+ else
23
+ a[1].downcase <=> b[1].downcase
24
+ end
25
+ end
26
+ list.unshift ['==========', '=========', '=============']
27
+ list.unshift ['Short Name', 'Full name', 'New apps only']
28
+
29
+ paragraph{ say "Use the short name of a cartridge when interacting with your applications." }
30
+
31
+ say table(list).join("\n")
32
+
16
33
  0
17
34
  end
18
35
 
@@ -176,14 +193,14 @@ module RHC::Commands
176
193
  end
177
194
 
178
195
  private
179
- include RHC::CartridgeHelpers
180
-
181
- def cartridge_action(cartridge, action)
182
- rest_domain = rest_client.find_domain(options.namespace)
183
- rest_app = rest_domain.find_application(options.app)
184
- rest_cartridge = find_cartridge rest_app, cartridge
185
- result = rest_cartridge.send action
186
- [result, rest_cartridge, rest_app, rest_domain]
187
- end
196
+ include RHC::CartridgeHelpers
197
+
198
+ def cartridge_action(cartridge, action)
199
+ rest_domain = rest_client.find_domain(options.namespace)
200
+ rest_app = rest_domain.find_application(options.app)
201
+ rest_cartridge = find_cartridge rest_app, cartridge
202
+ result = rest_cartridge.send action
203
+ [result, rest_cartridge, rest_app, rest_domain]
204
+ end
188
205
  end
189
206
  end
@@ -13,11 +13,12 @@ module RHC::Commands
13
13
  summary 'Display all the SSH keys for the user account'
14
14
  syntax ''
15
15
  def list
16
+ keys = rest_client.sshkeys
17
+
16
18
  results do
17
- result = rest_client.sshkeys.inject('') do |r, key|
19
+ result = keys.inject('') do |r, key|
18
20
  r += format(key, erb)
19
21
  end
20
-
21
22
  say result
22
23
  end
23
24
 
@@ -5,6 +5,9 @@ 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_command_syntax command
9
+ template(:command_syntax_help).result command.get_binding
10
+ end
8
11
  end
9
12
  # TODO: class ManPageHelpFormatter
10
13
  end
@@ -4,6 +4,8 @@ require 'rhc/config'
4
4
  require 'rhc/commands'
5
5
  require 'rhc/output_helpers'
6
6
 
7
+ require 'resolv'
8
+
7
9
  OptionParser.accept(URI) {|s,| URI.parse(s) if s}
8
10
 
9
11
  module RHC
@@ -80,6 +82,10 @@ module RHC
80
82
  global_option '-p', '--password password', "OpenShift password"
81
83
  global_option '-d', '--debug', "Turn on debugging"
82
84
 
85
+ global_option('--timeout seconds', Integer, 'Set the timeout in seconds for network commands') do |value|
86
+ # FIXME: Refactor so we don't have to use a global var here
87
+ $rest_timeout = value
88
+ end
83
89
  global_option '--noprompt', "Suppress the interactive setup wizard from running before a command"
84
90
  global_option '--config FILE', "Path of a different config file"
85
91
  def config
@@ -113,6 +119,8 @@ module RHC
113
119
  end
114
120
 
115
121
  def deprecated(msg,short = false)
122
+ HighLine::use_color = false if windows? # handle deprecated commands that does not start through highline
123
+
116
124
  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 may be removed in future releases."
117
125
 
118
126
  msg << info unless short
@@ -123,18 +131,29 @@ module RHC
123
131
  end
124
132
  end
125
133
 
126
- def say(msg)
127
- super
134
+ def say(msg, *args)
135
+ if Hash[*args][:stderr]
136
+ $stderr.puts msg
137
+ else
138
+ super(msg)
139
+ end
128
140
  msg
129
141
  end
142
+
130
143
  def success(msg, *args)
131
- say color(msg, :green)
144
+ say color(msg, :green), *args
132
145
  end
146
+
147
+ def info(msg, *args)
148
+ say color(msg, :cyan), *args
149
+ end
150
+
133
151
  def warn(msg, *args)
134
- say color(msg, :yellow)
152
+ say color(msg, :yellow), *args
135
153
  end
154
+
136
155
  def error(msg, *args)
137
- say color(msg, :red)
156
+ say color(msg, :red), *args
138
157
  end
139
158
 
140
159
  def color(s, color)
@@ -306,5 +325,15 @@ Fingerprint: <%= key.fingerprint %>
306
325
  FORMAT
307
326
  end
308
327
 
328
+ #
329
+ # Check if host exists
330
+ #
331
+ def host_exists?(host)
332
+ # :nocov:
333
+ # Patch for BZ840938 to support Ruby 1.8 on machines without /etc/resolv.conf
334
+ dns = Resolv::DNS.new((Resolv::DNS::Config.default_config_hash || {}))
335
+ dns.getresources(host, Resolv::DNS::Resource::IN::A).any?
336
+ # :nocov:
337
+ end
309
338
  end
310
339
  end