rhc 1.5.13 → 1.6.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/features/application.feature +1 -1
  2. data/features/cartridge.feature +10 -9
  3. data/features/geared_application.feature +3 -6
  4. data/features/lib/rhc_helper/app.rb +2 -2
  5. data/features/multiple_cartridge.feature +9 -8
  6. data/features/scaled_application.feature +5 -5
  7. data/features/step_definitions/application_steps.rb +4 -3
  8. data/features/step_definitions/cartridge_steps.rb +8 -1
  9. data/features/support/before_hooks.rb +12 -6
  10. data/features/support/env.rb +8 -1
  11. data/features/support/platform_support.rb +29 -0
  12. data/lib/rhc/command_runner.rb +33 -21
  13. data/lib/rhc/commands/account.rb +1 -1
  14. data/lib/rhc/commands/alias.rb +90 -7
  15. data/lib/rhc/commands/app.rb +15 -11
  16. data/lib/rhc/commands/cartridge.rb +9 -2
  17. data/lib/rhc/exceptions.rb +6 -0
  18. data/lib/rhc/helpers.rb +3 -0
  19. data/lib/rhc/output_helpers.rb +12 -3
  20. data/lib/rhc/rest.rb +3 -0
  21. data/lib/rhc/rest/alias.rb +50 -0
  22. data/lib/rhc/rest/application.rb +26 -2
  23. data/lib/rhc/rest/cartridge.rb +16 -1
  24. data/lib/rhc/rest/client.rb +24 -4
  25. data/lib/rhc/rest/mock.rb +66 -2
  26. data/lib/rhc/ssh_helpers.rb +2 -3
  27. data/lib/rhc/wizard.rb +6 -3
  28. data/spec/rhc/assets/cert.crt +22 -0
  29. data/spec/rhc/assets/cert_key_rsa +27 -0
  30. data/spec/rhc/assets/empty.txt +0 -0
  31. data/spec/rhc/cli_spec.rb +5 -0
  32. data/spec/rhc/commands/account_spec.rb +6 -6
  33. data/spec/rhc/commands/alias_spec.rb +179 -5
  34. data/spec/rhc/commands/app_spec.rb +2 -1
  35. data/spec/rhc/commands/authorization_spec.rb +9 -0
  36. data/spec/rhc/commands/cartridge_spec.rb +27 -0
  37. data/spec/rhc/commands/setup_spec.rb +2 -0
  38. data/spec/rhc/commands/sshkey_spec.rb +20 -1
  39. data/spec/rhc/helpers_spec.rb +1 -2
  40. data/spec/rhc/rest_client_spec.rb +26 -5
  41. data/spec/rhc/wizard_spec.rb +22 -0
  42. data/spec/spec_helper.rb +25 -2
  43. data/spec/wizard_spec_helper.rb +1 -1
  44. metadata +153 -144
@@ -12,25 +12,25 @@ module RHC::Commands
12
12
 
13
13
  summary "Create an application"
14
14
  description <<-DESC
15
- Create an application. Every OpenShift application must have one
15
+ Create an application. Every OpenShift application must have one
16
16
  web cartridge which serves web requests, and can have a number of
17
- other cartridges which provide capabilities like databases,
17
+ other cartridges which provide capabilities like databases,
18
18
  scheduled jobs, or continuous integration.
19
19
 
20
- You can see a list of all valid cartridge types by running
20
+ You can see a list of all valid cartridge types by running
21
21
  'rhc cartridge list'.
22
22
 
23
23
  When your application is created, a domain name that is a combination
24
- of the name of your app and the namespace of your domain will be
24
+ of the name of your app and the namespace of your domain will be
25
25
  registered in DNS. A copy of the code for your application
26
- will be checked out locally into a folder with the same name as
26
+ will be checked out locally into a folder with the same name as
27
27
  your application. Note that different types of applications may
28
28
  require different structures - check the README provided with the
29
29
  cartridge if you have questions.
30
30
 
31
- OpenShift runs the components of your application on small virtual
31
+ OpenShift runs the components of your application on small virtual
32
32
  servers called "gears". Each account or plan is limited to a number
33
- of gears which you can use across multiple applications. Some
33
+ of gears which you can use across multiple applications. Some
34
34
  accounts or plans provide access to gears with more memory or more
35
35
  CPU. Run 'rhc account' to see the number and sizes of gears available
36
36
  to you. When creating an application the --gear-size parameter
@@ -51,7 +51,7 @@ module RHC::Commands
51
51
  argument :cartridges, "The web framework this application should use", ["-t", "--type cartridge"], :arg_type => :list
52
52
  #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
53
53
  def create(name, cartridges)
54
- cartridges = check_cartridges(cartridges, &require_one_web_cart)
54
+ cartridges = check_cartridges(cartridges, &require_one_web_cart)
55
55
 
56
56
  options.default \
57
57
  :dns => true,
@@ -63,10 +63,14 @@ module RHC::Commands
63
63
  rest_domain = rest_client.find_domain(options.namespace)
64
64
  rest_app = nil
65
65
 
66
+ cart_names = cartridges.collect do |c|
67
+ c.usage_rate? ? "#{c.name} (addtl. costs may apply)" : c.name
68
+ end.join(', ')
69
+
66
70
  paragraph do
67
71
  header "Application Options"
68
72
  table([["Namespace:", options.namespace],
69
- ["Cartridges:", cartridges.map(&:name).join(', ')],
73
+ ["Cartridges:", cart_names],
70
74
  (["Source Code:", options.from_code] if options.from_code),
71
75
  ["Gear Size:", options.gear_size || "default"],
72
76
  ["Scaling:", options.scaling ? "yes" : "no"],
@@ -312,7 +316,7 @@ module RHC::Commands
312
316
  private
313
317
  include RHC::GitHelpers
314
318
  include RHC::CartridgeHelpers
315
-
319
+
316
320
  def require_one_web_cart
317
321
  lambda{ |carts|
318
322
  match, ambiguous = carts.partition{ |c| not c.is_a?(Array) }
@@ -320,7 +324,7 @@ module RHC::Commands
320
324
  possible_web = ambiguous.flatten.any?(&:only_in_new?)
321
325
  if not (selected_web or possible_web)
322
326
  section(:bottom => 1){ list_cartridges(standalone_cartridges) }
323
- raise RHC::CartridgeNotFoundException, "Every application needs a web cartridge to handle incoming web requests. Please provide the short name of one of the carts listed above."
327
+ raise RHC::CartridgeNotFoundException, "Every application needs a web cartridge to handle incoming web requests. Please provide the short name of one of the carts listed above."
324
328
  end
325
329
  if selected_web
326
330
  carts.map! &other_carts_only
@@ -22,15 +22,20 @@ module RHC::Commands
22
22
  underline("#{name} (#{c.only_in_new? ? 'web' : 'addon'})"),
23
23
  c.description,
24
24
  tags.present? ? "\nTagged with: #{tags.sort.join(', ')}" : nil,
25
+ c.usage_rate? ? "\n#{format_usage_message(c)}" : nil,
25
26
  ].compact << "\n"
26
27
  end.flatten
27
28
  else
28
- table(carts.map{ |c| [c.name, c.display_name, c.only_in_new? ? 'web' : 'addon'] })
29
+ table(carts.collect do |c|
30
+ [c.usage_rate? ? "#{c.name} (*)" : c.name,
31
+ c.display_name,
32
+ c.only_in_new? ? 'web' : 'addon']
33
+ end)
29
34
  end
30
35
 
31
-
32
36
  say list.join("\n")
33
37
  paragraph{ say "Note: Web cartridges can only be added to new applications." }
38
+ paragraph{ say "(*) denotes a cartridge with additional usage costs." } if carts.any? { |c| c.usage_rate? }
34
39
 
35
40
  0
36
41
  end
@@ -46,6 +51,8 @@ module RHC::Commands
46
51
 
47
52
  say "Adding #{cart.name} to application '#{options.app}' ... "
48
53
 
54
+ say format_usage_message(cart) if cart.usage_rate?
55
+
49
56
  rest_app = rest_client.find_application(options.namespace, options.app, :include => :cartridges)
50
57
  rest_cartridge = rest_app.add_cartridge(cart.name)
51
58
 
@@ -19,6 +19,12 @@ module RHC
19
19
  end
20
20
  end
21
21
 
22
+ class AliasNotFoundException < Exception
23
+ def initialize(message="Alias not found")
24
+ super message, 156
25
+ end
26
+ end
27
+
22
28
  class MultipleCartridgesException < Exception
23
29
  def initialize(message="Multiple cartridge found")
24
30
  super message, 155
@@ -297,6 +297,9 @@ module RHC
297
297
  align = opts[:align] || []
298
298
  join = opts[:join] || ' '
299
299
  if opts[:header]
300
+ opts[:header].each_with_index do |s, i|
301
+ widths[i] = [widths[i] || 0, s.length].max
302
+ end
300
303
  sep = opts[:separator] || "="
301
304
  ary = Array.new(opts[:header].length)
302
305
  items.unshift ary.each_with_index {|obj, idx| ary[idx] = sep.to_s * (widths[idx] || 1)}
@@ -106,6 +106,11 @@ module RHC
106
106
  concat(cart.properties.map{ |p| ["#{table_heading(p['name'])}:", p['value']] }.sort{ |a,b| a[0] <=> b[0] }),
107
107
  :delete => true
108
108
  display_no_info("cartridge") unless @table_displayed
109
+
110
+ if cart.usage_rate?
111
+ say "\n"
112
+ say format_usage_message(cart)
113
+ end
109
114
  end
110
115
 
111
116
  def display_key(key, *properties)
@@ -151,6 +156,10 @@ module RHC
151
156
  end
152
157
  end
153
158
 
159
+ def format_usage_message(cart)
160
+ "This gear costs an additional $#{cart.usage_rate} per gear after the first 3 gears."
161
+ end
162
+
154
163
  #---------------------------
155
164
  # Misc information
156
165
  #---------------------------
@@ -203,8 +212,8 @@ module RHC
203
212
  case prop
204
213
  when :plan_id
205
214
  case value
206
- when 'freeshift' then 'FreeShift'
207
- when 'megashift' then 'MegaShift'
215
+ when 'free' then 'Free'
216
+ when 'silver' then 'Silver'
208
217
  else value && value.capitalize || nil
209
218
  end
210
219
  when :visible_to_ssh?
@@ -218,7 +227,7 @@ module RHC
218
227
  when :base_gear_storage,:additional_gear_storage
219
228
  ((value.nil? or value == 0) ? "None" : "#{value}GB")
220
229
  when :aliases
221
- value.join ', '
230
+ value.kind_of?(Array) ? value.join(', ') : value
222
231
  when :expires_in_seconds
223
232
  distance_of_time_in_words(value)
224
233
  else
@@ -13,6 +13,7 @@ module RHC
13
13
  autoload :Key, 'rhc/rest/key'
14
14
  autoload :User, 'rhc/rest/user'
15
15
  autoload :GearGroup, 'rhc/rest/gear_group'
16
+ autoload :Alias, 'rhc/rest/alias'
16
17
 
17
18
  class Exception < RuntimeError
18
19
  attr_reader :code
@@ -112,6 +113,8 @@ module RHC
112
113
 
113
114
  class MultipleCartridgeCreationNotSupported < Exception; end
114
115
 
116
+ class SslCertificatesNotSupported < Exception; end
117
+
115
118
  class AuthorizationsNotSupported < Exception
116
119
  def initialize(message="The server does not support setting, retrieving, or authenticating with authorization tokens.")
117
120
  super(message, 1)
@@ -0,0 +1,50 @@
1
+ require 'rhc/rest/base'
2
+
3
+ module RHC
4
+ module Rest
5
+ class Alias < Base
6
+
7
+ define_attr :id, :has_private_ssl_certificate, :certificate_added_at
8
+
9
+ def has_private_ssl_certificate?
10
+ has_private_ssl_certificate
11
+ end
12
+
13
+ def destroy
14
+ debug "Deleting alias #{self.id}"
15
+ rest_method "DELETE"
16
+ end
17
+ alias :delete :destroy
18
+
19
+ def add_certificate(ssl_certificate_content, private_key_content, pass_phrase)
20
+ debug "Running add_certificate for alias #{@id}"
21
+ if (client.api_version_negotiated >= 1.4)
22
+ foo = rest_method "UPDATE", {
23
+ :ssl_certificate => ssl_certificate_content,
24
+ :private_key => private_key_content,
25
+ :pass_phrase => pass_phrase
26
+ }
27
+ else
28
+ raise RHC::Rest::SslCertificatesNotSupported, "The server does not support SSL certificates for custom aliases."
29
+ end
30
+ end
31
+
32
+ def delete_certificate
33
+ debug "Running delete_certificate for alias #{@id}"
34
+ if (client.api_version_negotiated >= 1.4)
35
+ rest_method "UPDATE", {}
36
+ else
37
+ raise RHC::Rest::SslCertificatesNotSupported, "The server does not support SSL certificates for custom aliases."
38
+ end
39
+ end
40
+
41
+ def <=>(a)
42
+ return self.name <=> a.name
43
+ end
44
+
45
+ def to_s
46
+ self.id
47
+ end
48
+ end
49
+ end
50
+ end
@@ -3,7 +3,7 @@ require 'uri'
3
3
  module RHC
4
4
  module Rest
5
5
  class Application < Base
6
- define_attr :domain_id, :name, :creation_time, :uuid, :aliases,
6
+ define_attr :domain_id, :name, :creation_time, :uuid,
7
7
  :git_url, :app_url, :gear_profile, :framework,
8
8
  :scalable, :health_check_path, :embedded, :gear_count,
9
9
  :ssh_url, :building_app, :cartridges, :initial_git_url
@@ -97,7 +97,31 @@ module RHC
97
97
 
98
98
  def remove_alias(app_alias)
99
99
  debug "Running remove_alias for #{name}"
100
- rest_method "REMOVE_ALIAS", :event => "remove-alias", :alias => app_alias
100
+ if (client.api_version_negotiated >= 1.4)
101
+ find_alias(app_alias).destroy
102
+ else
103
+ rest_method "REMOVE_ALIAS", :event => "remove-alias", :alias => app_alias
104
+ end
105
+ end
106
+
107
+ def aliases
108
+ debug "Getting all aliases for application #{name}"
109
+ if (client.api_version_negotiated >= 1.4)
110
+ rest_method "LIST_ALIASES"
111
+ else
112
+ attributes['aliases']
113
+ end
114
+ end
115
+
116
+ def find_alias(name, options={})
117
+ debug "Finding alias #{name} in app #{@name}"
118
+
119
+ if name.is_a?(Hash)
120
+ options = name
121
+ name = options[:name]
122
+ end
123
+ aliases.each { |a| return a if a.is_a?(String) || a.id == name }
124
+ raise RHC::AliasNotFoundException.new("Alias #{name} can't be found in application #{@name}.")
101
125
  end
102
126
 
103
127
  #Find Cartridge by name
@@ -31,6 +31,21 @@ module RHC
31
31
  attribute(:display_name) || name
32
32
  end
33
33
 
34
+ def usage_rate?
35
+ rate = usage_rate
36
+ rate && rate > 0.0
37
+ end
38
+
39
+ def usage_rate
40
+ rate = attribute(:usage_rate_usd)
41
+
42
+ if attribute(:usage_rates)
43
+ rate ||= attribute(:usage_rates).inject(0) { |total, rate| total + rate['usd'].to_f }
44
+ end
45
+
46
+ rate.to_f rescue 0.0
47
+ end
48
+
34
49
  def scaling
35
50
  {
36
51
  :current_scale => current_scale,
@@ -56,7 +71,7 @@ module RHC
56
71
  rest_method "START", :event => "start"
57
72
  end
58
73
 
59
- def stop()
74
+ def stop
60
75
  debug "Stopping cartridge #{name}"
61
76
  rest_method "STOP", :event => "stop"
62
77
  end
@@ -3,6 +3,7 @@ require 'rhc/helpers'
3
3
  require 'uri'
4
4
  require 'logger'
5
5
  require 'httpclient'
6
+ require 'benchmark'
6
7
 
7
8
  module RHC
8
9
  module Rest
@@ -75,6 +76,14 @@ module RHC
75
76
  })
76
77
  end
77
78
 
79
+ def find_application_aliases(domain, application, options={})
80
+ response = request({
81
+ :url => link_show_application_by_domain_name(domain, application, "aliases"),
82
+ :method => "GET",
83
+ :payload => options
84
+ })
85
+ end
86
+
78
87
  def link_show_application_by_domain_name(domain, application, *args)
79
88
  [
80
89
  api.links['LIST_DOMAINS']['href'],
@@ -188,7 +197,15 @@ module RHC
188
197
  # The list may not necessarily be sorted; we will select the last
189
198
  # matching one supported by the server.
190
199
  # See #api_version_negotiated
191
- CLIENT_API_VERSIONS = [1.1, 1.2, 1.3]
200
+ CLIENT_API_VERSIONS = [1.1, 1.2, 1.3, 1.4]
201
+
202
+ # Set the http_proxy env variable, read by
203
+ # HTTPClient, being sure to add the http protocol
204
+ # if not specified already
205
+ proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
206
+ if proxy && proxy !~ /^(\w+):\/\// then
207
+ ENV['http_proxy'] = "http://#{proxy}"
208
+ end
192
209
 
193
210
  def initialize(*args)
194
211
  options = args[0].is_a?(Hash) && args[0] || {}
@@ -232,7 +249,7 @@ module RHC
232
249
  end
233
250
 
234
251
  def api
235
- @api ||= RHC::Rest::Api.new(self, @preferred_api_versions).tap do |api|
252
+ @api ||= RHC::Rest::Api.new(self, @preferred_api_versions).tap do |api|
236
253
  self.current_api_version = api.api_version_negotiated
237
254
  end
238
255
  end
@@ -247,10 +264,11 @@ module RHC
247
264
  begin
248
265
  client, args = new_request(options.dup)
249
266
  auth = options[:auth] || self.auth
267
+ response = nil
250
268
 
251
269
  debug "Request #{args[0].to_s.upcase} #{args[1]}" if debug?
252
- response = client.request(*(args << true))
253
- debug " code #{response.status}" if debug? && response
270
+ time = Benchmark.realtime{ response = client.request(*(args << true)) }
271
+ debug " code %s %4i ms" % [response.status, (time*1000).to_i] if debug? && response
254
272
 
255
273
  next if retry_proxy(response, i, args, client)
256
274
  auth.retry_auth?(response, self) and next if auth
@@ -489,6 +507,8 @@ module RHC
489
507
  Key.new(data, self)
490
508
  when 'gear_groups'
491
509
  data.map{ |json| GearGroup.new(json, self) }
510
+ when 'aliases'
511
+ data.map{ |json| Alias.new(json, self) }
492
512
  else
493
513
  data
494
514
  end
@@ -54,7 +54,7 @@ module RHC::Rest::Mock
54
54
  to_return({
55
55
  :body => {
56
56
  :data => mock_response_links(authorizations ? mock_api_with_authorizations : mock_real_client_links),
57
- :supported_api_versions => [1.0, 1.1, 1.2, 1.3],
57
+ :supported_api_versions => [1.0, 1.1, 1.2, 1.3, 1.4],
58
58
  }.to_json
59
59
  })
60
60
  end
@@ -255,6 +255,7 @@ module RHC::Rest::Mock
255
255
  {:name => 'mock_standalone_cart-1', :type => 'standalone', :tags => ['cartridge'], :display_name => 'Mock1 Cart'},
256
256
  {:name => 'mock_standalone_cart-2', :type => 'standalone', :description => 'Mock2 description'},
257
257
  {:name => 'mock_embedded_cart-1', :type => 'embedded', :tags => ['scheduled'], :display_name => 'Mock1 Embedded Cart'},
258
+ {:name => 'premium_cart-1', :type => 'standalone', :tags => ['premium'], :display_name => 'Premium Cart', :usage_rate_usd => '0.02'},
258
259
  ],
259
260
  }.to_json
260
261
  }
@@ -333,6 +334,7 @@ module RHC::Rest::Mock
333
334
  ['THREAD_DUMP', "domains/#{domain_id}/apps/#{app_id}/event", 'post'],
334
335
  ['ADD_ALIAS', "domains/#{domain_id}/apps/#{app_id}/event", 'post'],
335
336
  ['REMOVE_ALIAS', "domains/#{domain_id}/apps/#{app_id}/event", 'post'],
337
+ ['LIST_ALIASES', "domains/#{domain_id}/apps/#{app_id}/aliases", 'get'],
336
338
  ['DELETE', "domains/#{domain_id}/apps/#{app_id}/delete", 'post']]
337
339
  end
338
340
 
@@ -381,6 +383,12 @@ module RHC::Rest::Mock
381
383
  ['LIST_KEYS', 'user/keys/', 'get' ]]
382
384
  end
383
385
 
386
+ def mock_alias_links(domain_id='test_domain',app_id='test_app',alias_id='test.foo.com')
387
+ [['DELETE', "domains/#{domain_id}/apps/#{app_id}/aliases/#{alias_id}/delete", 'post'],
388
+ ['GET', "domains/#{domain_id}/apps/#{app_id}/aliases/#{alias_id}", 'get' ],
389
+ ['UPDATE', "domains/#{domain_id}/apps/#{app_id}/aliases/#{alias_id}/update", 'post' ]]
390
+ end
391
+
384
392
  def mock_cartridge_response(cart_count=1)
385
393
  carts = []
386
394
  while carts.length < cart_count
@@ -450,6 +458,9 @@ module RHC::Rest::Mock
450
458
  end
451
459
 
452
460
  def cartridges
461
+ premium_embedded = MockRestCartridge.new(self, "premium_cart", "embedded")
462
+ premium_embedded.usage_rate = 0.05
463
+
453
464
  [MockRestCartridge.new(self, "mock_cart-1", "embedded"), # code should sort this to be after standalone
454
465
  MockRestCartridge.new(self, "mock_standalone_cart-1", "standalone"),
455
466
  MockRestCartridge.new(self, "mock_standalone_cart-2", "standalone"),
@@ -457,7 +468,9 @@ module RHC::Rest::Mock
457
468
  MockRestCartridge.new(self, "jenkins-1.4", "standalone"),
458
469
  MockRestCartridge.new(self, "mock_cart-2", "embedded"),
459
470
  MockRestCartridge.new(self, "unique_mock_cart-1", "embedded"),
460
- MockRestCartridge.new(self, "jenkins-client-1.4", "embedded")]
471
+ MockRestCartridge.new(self, "jenkins-client-1.4", "embedded"),
472
+ premium_embedded
473
+ ]
461
474
  end
462
475
 
463
476
  def add_domain(id)
@@ -577,6 +590,41 @@ module RHC::Rest::Mock
577
590
  end
578
591
  end
579
592
 
593
+ class MockRestAlias < RHC::Rest::Alias
594
+ include Helpers
595
+
596
+ def initialize(client, id, has_private_ssl_certificate=false, certificate_added_at=nil)
597
+ super({}, client)
598
+ @id = id
599
+ @has_private_ssl_certificate = has_private_ssl_certificate
600
+ @certificate_added_at = certificate_added_at
601
+ end
602
+
603
+ def add_certificate(ssl_certificate_content, private_key_content, pass_phrase)
604
+ if (client.api_version_negotiated >= 1.4)
605
+ @has_private_ssl_certificate = true
606
+ @certificate_added_at = Time.now
607
+ else
608
+ raise RHC::Rest::SslCertificatesNotSupported, "The server does not support SSL certificates for custom aliases."
609
+ end
610
+ end
611
+
612
+ def delete_certificate
613
+ if (client.api_version_negotiated >= 1.4)
614
+ @has_private_ssl_certificate = false
615
+ @certificate_added_at = nil
616
+ else
617
+ raise RHC::Rest::SslCertificatesNotSupported, "The server does not support SSL certificates for custom aliases."
618
+ end
619
+ end
620
+
621
+ def destroy
622
+ puts @application.inspect
623
+ puts self.inspect
624
+ @application.aliases.delete self
625
+ end
626
+ end
627
+
580
628
  class MockRestApplication < RHC::Rest::Application
581
629
  include Helpers
582
630
  def fakeuuid
@@ -656,10 +704,25 @@ module RHC::Rest::Mock
656
704
  def tidy
657
705
  @app
658
706
  end
707
+
708
+ def add_alias(app_alias)
709
+ @aliases << MockRestAlias.new(@client, app_alias)
710
+ end
711
+
712
+ def remove_alias(app_alias)
713
+ @aliases.delete_if {|x| x.id == app_alias}
714
+ end
715
+
716
+ def aliases
717
+ @aliases
718
+ end
659
719
  end
660
720
 
661
721
  class MockRestCartridge < RHC::Rest::Cartridge
662
722
  include Helpers
723
+
724
+ attr_accessor :usage_rate
725
+
663
726
  def initialize(client, name, type, app=nil, properties=[{'type' => 'cart_data', 'name' => 'connection_url', 'value' => "http://fake.url" }])
664
727
  super({}, client)
665
728
  @name = name
@@ -672,6 +735,7 @@ module RHC::Rest::Mock
672
735
  @current_scale = 1
673
736
  @gear_profile = 'small'
674
737
  @additional_gear_storage = 5
738
+ @usage_rate = 0.0
675
739
  end
676
740
 
677
741
  def destroy