rhc 1.4.8 → 1.5.13

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.
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