rhc 1.4.8 → 1.5.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/features/application.feature +1 -0
  2. data/features/lib/rhc_helper/app.rb +5 -3
  3. data/features/lib/rhc_helper/commandify.rb +2 -1
  4. data/features/step_definitions/application_steps.rb +2 -1
  5. data/features/support/env.rb +4 -1
  6. data/lib/rhc/auth/basic.rb +18 -13
  7. data/lib/rhc/auth/token.rb +98 -0
  8. data/lib/rhc/auth/token_store.rb +51 -0
  9. data/lib/rhc/auth.rb +3 -1
  10. data/lib/rhc/command_runner.rb +1 -0
  11. data/lib/rhc/commands/account.rb +47 -1
  12. data/lib/rhc/commands/alias.rb +2 -4
  13. data/lib/rhc/commands/app.rb +23 -18
  14. data/lib/rhc/commands/authorization.rb +93 -0
  15. data/lib/rhc/commands/base.rb +11 -3
  16. data/lib/rhc/commands/cartridge.rb +8 -16
  17. data/lib/rhc/commands/git_clone.rb +2 -3
  18. data/lib/rhc/commands/port_forward.rb +10 -11
  19. data/lib/rhc/commands/setup.rb +4 -1
  20. data/lib/rhc/commands/snapshot.rb +4 -3
  21. data/lib/rhc/commands/tail.rb +3 -4
  22. data/lib/rhc/commands/threaddump.rb +1 -2
  23. data/lib/rhc/commands.rb +37 -3
  24. data/lib/rhc/config.rb +10 -1
  25. data/lib/rhc/context_helper.rb +5 -1
  26. data/lib/rhc/core_ext.rb +10 -0
  27. data/lib/rhc/exceptions.rb +0 -12
  28. data/lib/rhc/git_helpers.rb +12 -0
  29. data/lib/rhc/helpers.rb +31 -1
  30. data/lib/rhc/output_helpers.rb +19 -3
  31. data/lib/rhc/rest/api.rb +2 -1
  32. data/lib/rhc/rest/application.rb +5 -4
  33. data/lib/rhc/rest/authorization.rb +10 -0
  34. data/lib/rhc/rest/base.rb +6 -1
  35. data/lib/rhc/rest/client.rb +243 -122
  36. data/lib/rhc/rest/domain.rb +0 -15
  37. data/lib/rhc/rest/gear_group.rb +0 -1
  38. data/lib/rhc/rest/mock.rb +118 -16
  39. data/lib/rhc/rest/user.rb +0 -1
  40. data/lib/rhc/rest.rb +28 -8
  41. data/lib/rhc/ssh_helpers.rb +5 -2
  42. data/lib/rhc/tar_gz.rb +16 -5
  43. data/lib/rhc/usage_templates/help.erb +1 -1
  44. data/lib/rhc/wizard.rb +54 -10
  45. data/spec/coverage_helper.rb +9 -0
  46. data/spec/rhc/auth_spec.rb +229 -22
  47. data/spec/rhc/cli_spec.rb +15 -0
  48. data/spec/rhc/command_spec.rb +100 -8
  49. data/spec/rhc/commands/account_spec.rb +75 -1
  50. data/spec/rhc/commands/app_spec.rb +23 -5
  51. data/spec/rhc/commands/authorization_spec.rb +120 -0
  52. data/spec/rhc/commands/domain_spec.rb +2 -2
  53. data/spec/rhc/commands/git_clone_spec.rb +24 -0
  54. data/spec/rhc/commands/port_forward_spec.rb +22 -23
  55. data/spec/rhc/commands/server_spec.rb +2 -2
  56. data/spec/rhc/commands/setup_spec.rb +12 -0
  57. data/spec/rhc/config_spec.rb +7 -3
  58. data/spec/rhc/helpers_spec.rb +62 -9
  59. data/spec/rhc/rest_application_spec.rb +24 -0
  60. data/spec/rhc/rest_client_spec.rb +66 -56
  61. data/spec/rhc/rest_spec.rb +11 -2
  62. data/spec/rhc/wizard_spec.rb +61 -12
  63. data/spec/spec_helper.rb +125 -42
  64. data/spec/wizard_spec_helper.rb +1 -0
  65. metadata +9 -3
@@ -17,9 +17,8 @@ module RHC::Commands
17
17
  # TODO: Implement default values for arguments once ffranz has added context arguments
18
18
  # argument :directory, "The name of a new directory to clone into", [], :default => nil
19
19
  def run(app_name)
20
- domain = rest_client.find_domain(options.namespace)
21
- app = domain.find_application(app_name)
22
- git_clone_application(app)
20
+ rest_app = rest_client.find_application(options.namespace, app_name)
21
+ git_clone_application(rest_app)
23
22
 
24
23
  0
25
24
  end
@@ -14,21 +14,19 @@ module RHC::Commands
14
14
  @service = service
15
15
  @remote_host = remote_host
16
16
  @port_to = port_to
17
- @host_from = mac? ? "localhost" : remote_host # forward locally on a Mac
17
+ @host_from = '127.0.0.1'
18
18
  @port_from = port_from || port_to # match ports if possible
19
19
  @bound = false
20
20
  end
21
21
 
22
22
  def to_cmd_arg
23
23
  # string to be used in a direct SSH command
24
- mac? ? "-L #{port_from}:#{remote_host}:#{port_to}" : "-L #{remote_host}:#{port_from}:#{remote_host}:#{port_to}"
24
+ "-L #{port_from}:#{remote_host}:#{port_to}"
25
25
  end
26
26
 
27
27
  def to_fwd_args
28
28
  # array of arguments to be passed to Net::SSH::Service::Forward#local
29
- args = [port_from.to_i, remote_host, port_to.to_i]
30
- args.unshift(remote_host) unless mac?
31
- args
29
+ [port_from.to_i, remote_host, port_to.to_i]
32
30
  end
33
31
 
34
32
  def bound?
@@ -75,9 +73,7 @@ module RHC::Commands
75
73
  option ["-n", "--namespace namespace"], "Namespace of the application you are port forwarding to", :context => :namespace_context, :required => true
76
74
  argument :app, "Application you are port forwarding to (required)", ["-a", "--app app"]
77
75
  def run(app)
78
-
79
- rest_domain = rest_client.find_domain options.namespace
80
- rest_app = rest_domain.find_application app
76
+ rest_app = rest_client.find_application(options.namespace, app)
81
77
 
82
78
  ssh_uri = URI.parse(rest_app.ssh_url)
83
79
  say "Using #{rest_app.ssh_url}..." if options.debug
@@ -134,8 +130,8 @@ module RHC::Commands
134
130
  debug args.inspect
135
131
  ssh.forward.local(*args)
136
132
  fs.bound = true
137
- rescue Errno::EADDRINUSE
138
- debug "trying local port #{fs.port_from}"
133
+ rescue Errno::EADDRINUSE, Errno::EACCES => e
134
+ warn "#{e} while forwarding port #{fs.port_from}. Trying local port #{fs.port_from+1}"
139
135
  fs.port_from += 1
140
136
  rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
141
137
  given_up = true
@@ -145,10 +141,13 @@ module RHC::Commands
145
141
 
146
142
  bound_ports = forwarding_specs.select(&:bound?)
147
143
  if bound_ports.length > 0
144
+ paragraph {
145
+ say "To connect to a service running on OpenShift, use the Local address"
146
+ }
148
147
  items = bound_ports.map do |fs|
149
148
  [fs.service, "#{fs.host_from}:#{fs.port_from}", " => ", "#{fs.remote_host}:#{fs.port_to.to_s}"]
150
149
  end
151
- table(items, :header => ["Service", "Connect to", " ", "Forward to"]).each { |s| success " #{s}" }
150
+ table(items, :header => ["Service", "Local", " ", "OpenShift"]).each { |s| success " #{s}" }
152
151
  end
153
152
 
154
153
  # for failed port forwarding attempts
@@ -16,14 +16,17 @@ module RHC::Commands
16
16
  .openshift/express.conf file in your home directory. If you run
17
17
  setup at a later time, any previous configuration will be reused.
18
18
 
19
-
20
19
  Pass the --clean option to ignore your saved configuration and only
21
20
  use options you pass on the command line. Pass --config FILE to use
22
21
  default values from another config (the values will still be written
23
22
  to .openshift/express.conf).
23
+
24
+ If the server supports authorization tokens, you may pass the
25
+ --create-token option to instruct the wizard to generate a key for you.
24
26
  DESC
25
27
  option ["--server NAME"], "Hostname of an OpenShift server", :context => :server_context, :required => true
26
28
  option ['--clean'], "Ignore any saved configuration options"
29
+ option ['--[no-]create-token'], "Create an authorization token for this server"
27
30
  def run
28
31
  raise OptionParser::InvalidOption, "Setup can not be run with the --noprompt option" if options.noprompt
29
32
  RHC::RerunWizard.new(config, options).run ? 0 : 1
@@ -14,7 +14,8 @@ module RHC::Commands
14
14
  argument :app, "Application you are saving a snapshot (required)", ["-a", "--app app"]
15
15
  alias_action :"app snapshot save", :root_command => true, :deprecated => true
16
16
  def save(app)
17
- ssh_uri = URI.parse(rest_client.find_domain(options.namespace).find_application(app).ssh_url)
17
+ rest_app = rest_client.find_application(options.namespace, app)
18
+ ssh_uri = URI.parse(rest_app.ssh_url)
18
19
  filename = options.filepath ? options.filepath : "#{app}.tar.gz"
19
20
 
20
21
  ssh_cmd = "ssh #{ssh_uri.user}@#{ssh_uri.host} 'snapshot' > #{filename}"
@@ -64,8 +65,8 @@ module RHC::Commands
64
65
  if File.exists? filename
65
66
 
66
67
  include_git = RHC::Helpers.windows? ? true : RHC::TarGz.contains(filename, './*/git')
67
-
68
- ssh_uri = URI.parse(rest_client.find_domain(options.namespace).find_application(app).ssh_url)
68
+ rest_app = rest_client.find_application(options.namespace, app)
69
+ ssh_uri = URI.parse(rest_app.ssh_url)
69
70
 
70
71
  ssh_cmd = "cat #{filename} | ssh #{ssh_uri.user}@#{ssh_uri.host} 'restore#{include_git ? ' INCLUDE_GIT' : ''}'"
71
72
 
@@ -12,13 +12,12 @@ module RHC::Commands
12
12
  option ["-n", "--namespace namespace"], "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
+ #option ["-c", "--cartridge name"], "Tail only a specific cartridge"
15
16
  alias_action :"app tail", :root_command => true, :deprecated => true
16
17
  def run(app_name)
17
- domain = rest_client.find_domain(options.namespace)
18
- app = domain.find_application(app_name)
19
- cartridges = app.cartridges
18
+ rest_app = rest_client.find_application(options.namespace, app_name, :include => :cartridges)
20
19
 
21
- tail(cartridges.first.name, URI(app.ssh_url), options)
20
+ tail('*', URI(rest_app.ssh_url), options)
22
21
 
23
22
  0
24
23
  end
@@ -6,8 +6,7 @@ module RHC::Commands
6
6
  option ["-n", "--namespace namespace"], "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
- rest_domain = rest_client.find_domain(options.namespace)
10
- rest_app = rest_domain.find_application(app)
9
+ rest_app = rest_client.find_application(options.namespace, app)
11
10
  rest_app.threaddump.messages.each { |m| say m }
12
11
 
13
12
  0
data/lib/rhc/commands.rb CHANGED
@@ -40,6 +40,8 @@ module Commander
40
40
  if sw = opts.send(:search, :long, key.to_s.gsub(/_/, '-'))
41
41
  _, cb, val = sw.send(:conv_arg, nil, value) {|*exc| raise(*exc) }
42
42
  cb.call(val) if cb
43
+ else
44
+ proxy_options << [key, value]
43
45
  end
44
46
  end
45
47
  end
@@ -62,13 +64,34 @@ end
62
64
  #
63
65
  module Commander
64
66
  class Command
67
+ remove_const(:Options)
65
68
  class Options
66
69
  def initialize(init=nil)
67
70
  @table = {}
68
71
  default(init) if init
69
72
  end
73
+ def respond_to?(meth)
74
+ super || meth.to_s =~ /^\w+(=)?$/
75
+ end
70
76
  def method_missing meth, *args, &block
71
- meth.to_s =~ /=$/ ? self[meth.to_s.chop] = args.first : self[meth]
77
+ if meth.to_s =~ /^\w+=$/
78
+ raise ArgumentError, "Options does not support #{meth} without a single argument" if args.length != 1
79
+ self[meth.to_s.chop] = args.first
80
+ elsif meth.to_s =~ /^\w+$/
81
+ if !@table.has_key?(meth)
82
+ begin; return super; rescue NoMethodError; nil; end
83
+ end
84
+ raise ArgumentError, "Options does not support #{meth} with arguments" if args.length != 0
85
+ self[meth]
86
+ else
87
+ super
88
+ end
89
+ end
90
+ def respond_to_missing?(meth, private_method = false)
91
+ meth.to_s =~ /^\w+(=)?$/
92
+ end
93
+ def ==(other)
94
+ __hash__ == other.__hash__
72
95
  end
73
96
  def []=(meth, value)
74
97
  @table[meth.to_sym] = value
@@ -84,6 +107,9 @@ module Commander
84
107
  def __replace__(options)
85
108
  @table = __to_hash__(options).dup
86
109
  end
110
+ def __hash__
111
+ @table
112
+ end
87
113
  def __to_hash__(obj)
88
114
  Options === obj ? obj.__hash__ : obj
89
115
  end
@@ -105,7 +131,7 @@ module RHC
105
131
  commands[opts[:name]] = opts
106
132
  end
107
133
  def self.global_option(*args, &block)
108
- global_options << [args, block]
134
+ global_options << [args.freeze, block]
109
135
  end
110
136
 
111
137
  def self.deprecated?
@@ -134,6 +160,7 @@ module RHC
134
160
 
135
161
  def self.to_commander(instance=Commander::Runner.instance)
136
162
  global_options.each do |args, block|
163
+ args = args.dup
137
164
  opts = (args.pop if Hash === args.last) || {}
138
165
  option = instance.global_option(*args, &block).last
139
166
  option.merge!(opts)
@@ -148,7 +175,7 @@ module RHC
148
175
  (options_metadata = opts[:options] || []).each do |o|
149
176
  option_data = [o[:switches], o[:description]].flatten(1)
150
177
  c.option *option_data
151
- o[:arg] = Commander::Runner.switch_to_sym(o[:switches].last)
178
+ o[:arg] = Commander::Runner.switch_to_sym(Array(o[:switches]).last)
152
179
  end
153
180
 
154
181
  deprecated[name.to_sym] = opts[:deprecated] unless opts[:deprecated].nil?
@@ -202,6 +229,13 @@ module RHC
202
229
  end
203
230
 
204
231
  def self.fill_arguments(cmd, options, args_metadata, options_metadata, args)
232
+ Commander::Runner.instance.options.each do |opt|
233
+ if opt[:context]
234
+ arg = Commander::Runner.switch_to_sym(opt[:switches].last)
235
+ options[arg] ||= lambda{ cmd.send(opt[:context]) }
236
+ end
237
+ end
238
+
205
239
  # process options
206
240
  options_metadata.each do |option_meta|
207
241
  arg = option_meta[:arg]
data/lib/rhc/config.rb CHANGED
@@ -52,6 +52,8 @@ module RHC
52
52
  :server => ['libra_server', nil, 'The OpenShift server to connect to'],
53
53
  :rhlogin => ['default_rhlogin', nil, 'Your OpenShift login name'],
54
54
  :password => nil,
55
+ :use_authorization_tokens =>
56
+ [nil, :boolean, 'If true, the server will attempt to create and use authorization tokens to connect to the server'],
55
57
  :timeout => [nil, :integer, 'The default timeout for network operations'],
56
58
  :insecure => [nil, :boolean, "If true, certificate errors will be ignored.\nWARNING: This may allow others to eavesdrop on your communication with OpenShift."],
57
59
  :ssl_version => [nil, nil, 'The SSL protocol version to use when connecting to this server'],
@@ -133,7 +135,14 @@ module RHC
133
135
  opts = Array(opts)
134
136
  value = self[opts[0] || name.to_s]
135
137
  if value
136
- value = value unless value.blank?
138
+ value = case opts[1]
139
+ when :integer
140
+ Integer(value)
141
+ when :boolean
142
+ !!(value =~ /^\s*(y|yes|1|t|true)\s*$/i)
143
+ else
144
+ value unless value.blank?
145
+ end
137
146
  h[name] = value unless value.nil?
138
147
  end
139
148
  h
@@ -12,6 +12,10 @@ 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
+
15
19
  def app_context
16
20
  debug "Getting app context"
17
21
 
@@ -38,7 +42,7 @@ module RHC
38
42
  # right now we don't have any logic since we only support one domain
39
43
  # TODO: add domain lookup based on uuid
40
44
  domain = rest_client.domains.first
41
- raise RHC::DomainNotFoundException, "No domains configured for this user. You may create one using 'rhc domain create'." if domain.nil?
45
+ raise RHC::Rest::DomainNotFoundException, "No domains configured for this user. You may create one using 'rhc domain create'." if domain.nil?
42
46
 
43
47
  domain.id
44
48
  end
data/lib/rhc/core_ext.rb CHANGED
@@ -49,6 +49,16 @@ unless HTTP::Message.method_defined? :ok?
49
49
  #:nocov:
50
50
  end
51
51
 
52
+ unless DateTime.method_defined? :to_time
53
+ #:nocov:
54
+ class DateTime
55
+ def to_time
56
+ Time.parse(to_s)
57
+ end
58
+ end
59
+ #:nocov:
60
+ end
61
+
52
62
  #
53
63
  # Allow http => https redirection, see
54
64
  # http://bugs.ruby-lang.org/issues/859 to 1.8.7 for rough
@@ -13,18 +13,6 @@ module RHC
13
13
  end
14
14
  end
15
15
 
16
- class DomainNotFoundException < Exception
17
- def initialize(message="Domain not found")
18
- super message, 127
19
- end
20
- end
21
-
22
- class ApplicationNotFoundException < Exception
23
- def initialize(message="Application not found")
24
- super message, 101
25
- end
26
- end
27
-
28
16
  class CartridgeNotFoundException < Exception
29
17
  def initialize(message="Cartridge not found")
30
18
  super message, 154
@@ -1,4 +1,5 @@
1
1
  require 'open4'
2
+ require 'fileutils'
2
3
 
3
4
  module RHC
4
5
  module GitHelpers
@@ -16,6 +17,15 @@ module RHC
16
17
  end
17
18
  end
18
19
 
20
+ def git_clone_deploy_hooks(repo_dir)
21
+ debug "Deploy default hooks"
22
+ Dir.chdir(repo_dir) do |dir|
23
+ Dir.glob(".openshift/git_hooks/*") do |hook|
24
+ FileUtils.cp(hook, ".git/hooks/")
25
+ end
26
+ end
27
+ end
28
+
19
29
  def git_clone_application(app)
20
30
  repo_dir = options.repo || app.name
21
31
 
@@ -29,6 +39,8 @@ module RHC
29
39
  git_config_set "rhc.domain-name", app.domain_id
30
40
  end
31
41
 
42
+ git_clone_deploy_hooks(repo_dir)
43
+
32
44
  true
33
45
  end
34
46
 
data/lib/rhc/helpers.rb CHANGED
@@ -47,7 +47,7 @@ module RHC
47
47
 
48
48
  def date(s)
49
49
  now = Date.today
50
- d = datetime_rfc3339(s)
50
+ d = datetime_rfc3339(s).to_time
51
51
  if now.year == d.year
52
52
  return d.strftime('%l:%M %p').strip if now.yday == d.yday
53
53
  d.strftime('%b %d %l:%M %p')
@@ -58,6 +58,29 @@ module RHC
58
58
  "Unknown date"
59
59
  end
60
60
 
61
+ def distance_of_time_in_words(from_time, to_time = 0)
62
+ from_time = from_time.to_time if from_time.respond_to?(:to_time)
63
+ to_time = to_time.to_time if to_time.respond_to?(:to_time)
64
+ distance_in_minutes = (((to_time - from_time).abs)/60).round
65
+ distance_in_seconds = ((to_time - from_time).abs).round
66
+
67
+ case distance_in_minutes
68
+ when 0..1
69
+ return distance_in_minutes == 0 ?
70
+ "less than 1 minute" :
71
+ "#{distance_in_minutes} minute"
72
+
73
+ when 2..44 then "#{distance_in_minutes} minutes"
74
+ when 45..89 then "about 1 hour"
75
+ when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
76
+ when 1440..2519 then "about 1 day"
77
+ when 2520..43199 then "#{(distance_in_minutes.to_f / 1440.0).round} days"
78
+ when 43200..86399 then "about 1 month"
79
+ else
80
+ "about #{(distance_in_minutes.to_f / 43200.0).round} months"
81
+ end
82
+ end
83
+
61
84
  def datetime_rfc3339(s)
62
85
  DateTime.strptime(s, '%Y-%m-%dT%H:%M:%S%z')
63
86
  # Replace with d = DateTime.rfc3339(s)
@@ -74,8 +97,11 @@ module RHC
74
97
  #
75
98
  # Global config
76
99
  #
100
+
77
101
  global_option '-l', '--rhlogin LOGIN', "OpenShift login"
78
102
  global_option '-p', '--password PASSWORD', "OpenShift password"
103
+ global_option '--token TOKEN', "An authorization token for accessing your account.", :context => :token_context
104
+
79
105
  global_option '-d', '--debug', "Turn on debugging", :hide => true
80
106
 
81
107
  global_option '--server NAME', String, 'An OpenShift server hostname (default: openshift.redhat.com)'
@@ -160,6 +186,9 @@ module RHC
160
186
  def debug(msg)
161
187
  $stderr.puts "DEBUG: #{msg}" if debug?
162
188
  end
189
+ def debug_error(e)
190
+ debug "#{e.message} (#{e.class})\n #{e.backtrace.join("\n ")}"
191
+ end
163
192
  def debug?
164
193
  false
165
194
  end
@@ -296,6 +325,7 @@ module RHC
296
325
  # Predefined headings (or parts of headings)
297
326
  headings.merge!({
298
327
  :creation_time => "Created",
328
+ :expires_in_seconds => "Expires In",
299
329
  :uuid => "UUID",
300
330
  :current_scale => "Current",
301
331
  :scales_from => "Minimum",
@@ -120,6 +120,17 @@ module RHC
120
120
  )
121
121
  end
122
122
 
123
+ def display_authorization(auth, default=nil)
124
+ say_table(
125
+ auth.note || "<no description>",
126
+ get_properties(auth, :token, :scopes, :creation_time, :expires_in_seconds),
127
+ {
128
+ :delete => true,
129
+ :color => (:green if auth.token == default),
130
+ }
131
+ )
132
+ end
133
+
123
134
  def format_key_header(key)
124
135
  [
125
136
  key.name,
@@ -177,9 +188,12 @@ module RHC
177
188
  def get_properties(object,*properties)
178
189
  properties.map do |prop|
179
190
  # Either send the property to the object or yield it
180
- value = block_given? ? yield(prop) : object.send(prop)
181
- # Some values (like date) need some special handling
182
-
191
+ value = begin
192
+ block_given? ? yield(prop) : object.send(prop)
193
+ rescue ::Exception => e
194
+ debug_error(e)
195
+ "<error>"
196
+ end
183
197
  [prop, format_value(prop,value)]
184
198
  end
185
199
  end
@@ -205,6 +219,8 @@ module RHC
205
219
  ((value.nil? or value == 0) ? "None" : "#{value}GB")
206
220
  when :aliases
207
221
  value.join ', '
222
+ when :expires_in_seconds
223
+ distance_of_time_in_words(value)
208
224
  else
209
225
  case value
210
226
  when Array then value.join(', ')
data/lib/rhc/rest/api.rb CHANGED
@@ -24,7 +24,8 @@ module RHC
24
24
  @server_api_versions, links = api_info({
25
25
  :url => client.url,
26
26
  :method => :get,
27
- :headers => {'Accept' => "application/json; version=#{api_version_negotiated}"},
27
+ :accept => :json,
28
+ :api_version => api_version_negotiated,
28
29
  :lazy_auth => true,
29
30
  })
30
31
  end
@@ -3,8 +3,6 @@ require 'uri'
3
3
  module RHC
4
4
  module Rest
5
5
  class Application < Base
6
- include Rest
7
-
8
6
  define_attr :domain_id, :name, :creation_time, :uuid, :aliases,
9
7
  :git_url, :app_url, :gear_profile, :framework,
10
8
  :scalable, :health_check_path, :embedded, :gear_count,
@@ -142,12 +140,15 @@ module RHC
142
140
  end
143
141
 
144
142
  def host
145
- @host ||= URI(app_url).host
143
+ @host ||= URI.parse(app_url).host rescue nil
146
144
  end
147
145
 
148
146
  def ssh_string
149
- uri = URI(ssh_url)
147
+ uri = URI.parse(ssh_url)
150
148
  "#{uri.user}@#{uri.host}"
149
+ rescue => e
150
+ RHC::Helpers.debug_error(e)
151
+ ssh_url
151
152
  end
152
153
 
153
154
  def <=>(other)
@@ -0,0 +1,10 @@
1
+ require 'rhc/rest/base'
2
+
3
+ module RHC
4
+ module Rest
5
+ class Authorization < Base
6
+ define_attr :token, :note, :expires_in, :expires_in_seconds, :scopes, :created_at
7
+ alias_method :creation_time, :created_at
8
+ end
9
+ end
10
+ end
data/lib/rhc/rest/base.rb CHANGED
@@ -20,7 +20,8 @@ module RHC
20
20
  link = links[link_name.to_s]
21
21
  raise "No link defined for #{link_name}" unless link
22
22
  url = link['href']
23
- method = link['method']
23
+ url = url.gsub(/:\w+/) { |s| options[:params][s] } if options[:params]
24
+ method = options[:method] || link['method']
24
25
 
25
26
  client.request(options.merge({
26
27
  :url => url,
@@ -33,6 +34,10 @@ module RHC
33
34
  attributes['links'] || {}
34
35
  end
35
36
 
37
+ def supports?(sym)
38
+ links.has_key?(sym.to_s) || links.has_key?(sym.to_s.upcase)
39
+ end
40
+
36
41
  protected
37
42
  attr_reader :client
38
43