rhc 0.98.16 → 1.0.4

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 (94) hide show
  1. data/bin/rhc +7 -49
  2. data/bin/rhc-app +14 -3
  3. data/bin/rhc-chk +16 -16
  4. data/bin/rhc-create-app +2 -0
  5. data/bin/rhc-create-domain +1 -2
  6. data/bin/rhc-ctl-app +12 -3
  7. data/bin/rhc-ctl-domain +1 -2
  8. data/bin/rhc-domain +1 -2
  9. data/bin/rhc-domain-info +1 -2
  10. data/bin/rhc-port-forward +1 -2
  11. data/bin/rhc-snapshot +3 -0
  12. data/bin/rhc-sshkey +1 -2
  13. data/bin/rhc-tail-files +1 -1
  14. data/bin/rhc-user-info +1 -3
  15. data/features/application.feature +4 -1
  16. data/features/domain.feature +0 -4
  17. data/features/geared_application.feature +11 -0
  18. data/features/lib/rhc_helper/app.rb +16 -5
  19. data/features/lib/rhc_helper/cartridge.rb +25 -9
  20. data/features/lib/rhc_helper/commandify.rb +34 -7
  21. data/features/lib/rhc_helper/domain.rb +2 -2
  22. data/features/lib/rhc_helper/httpify.rb +24 -14
  23. data/features/lib/rhc_helper/persistable.rb +1 -1
  24. data/features/lib/rhc_helper/sshkey.rb +11 -7
  25. data/features/lib/rhc_helper.rb +5 -3
  26. data/features/multiple_cartridge.feature +1 -1
  27. data/features/scaled_application.feature +48 -0
  28. data/features/sshkey.feature +37 -31
  29. data/features/step_definitions/application_steps.rb +18 -7
  30. data/features/step_definitions/cartridge_steps.rb +29 -3
  31. data/features/step_definitions/domain_steps.rb +2 -2
  32. data/features/step_definitions/sshkey_steps.rb +34 -34
  33. data/features/support/assumptions.rb +21 -9
  34. data/features/support/before_hooks.rb +24 -6
  35. data/features/support/env.rb +45 -19
  36. data/lib/rhc/cartridge_helper.rb +27 -0
  37. data/lib/rhc/cli.rb +1 -1
  38. data/lib/rhc/command_runner.rb +31 -3
  39. data/lib/rhc/commands/alias.rb +38 -0
  40. data/lib/rhc/commands/app.rb +478 -0
  41. data/lib/rhc/commands/base.rb +42 -12
  42. data/lib/rhc/commands/cartridge.rb +189 -0
  43. data/lib/rhc/commands/domain.rb +11 -49
  44. data/lib/rhc/commands/port-forward.rb +0 -1
  45. data/lib/rhc/commands/setup.rb +2 -1
  46. data/lib/rhc/commands/snapshot.rb +118 -0
  47. data/lib/rhc/commands/sshkey.rb +24 -38
  48. data/lib/rhc/commands/tail.rb +24 -0
  49. data/lib/rhc/commands/threaddump.rb +16 -0
  50. data/lib/rhc/commands.rb +33 -7
  51. data/lib/rhc/config.rb +28 -12
  52. data/lib/rhc/context_helper.rb +19 -5
  53. data/lib/rhc/core_ext.rb +86 -0
  54. data/lib/rhc/exceptions.rb +44 -0
  55. data/lib/rhc/git_helper.rb +59 -0
  56. data/lib/rhc/helpers.rb +86 -5
  57. data/lib/rhc/output_helpers.rb +213 -0
  58. data/lib/rhc/rest/application.rb +134 -67
  59. data/lib/rhc/rest/base.rb +48 -0
  60. data/lib/rhc/rest/cartridge.rb +40 -44
  61. data/lib/rhc/rest/client.rb +127 -59
  62. data/lib/rhc/rest/domain.rb +29 -39
  63. data/lib/rhc/rest/gear_group.rb +10 -0
  64. data/lib/rhc/rest/key.rb +8 -23
  65. data/lib/rhc/rest/user.rb +8 -24
  66. data/lib/rhc/rest.rb +22 -11
  67. data/lib/rhc/ssh_key_helpers.rb +47 -0
  68. data/lib/rhc/usage_templates/help.erb +0 -1
  69. data/lib/rhc/version.rb +3 -3
  70. data/lib/rhc/wizard.rb +123 -225
  71. data/lib/rhc-common.rb +43 -62
  72. data/spec/rest_spec_helper.rb +159 -36
  73. data/spec/rhc/cli_spec.rb +29 -1
  74. data/spec/rhc/command_spec.rb +32 -35
  75. data/spec/rhc/commands/alias_spec.rb +123 -0
  76. data/spec/rhc/commands/app_spec.rb +414 -0
  77. data/spec/rhc/commands/cartridge_spec.rb +342 -0
  78. data/spec/rhc/commands/domain_spec.rb +8 -8
  79. data/spec/rhc/commands/setup_spec.rb +17 -6
  80. data/spec/rhc/commands/snapshot_spec.rb +140 -0
  81. data/spec/rhc/commands/sshkey_spec.rb +26 -4
  82. data/spec/rhc/commands/tail_spec.rb +34 -0
  83. data/spec/rhc/commands/threaddump_spec.rb +83 -0
  84. data/spec/rhc/config_spec.rb +39 -13
  85. data/spec/rhc/context_spec.rb +51 -0
  86. data/spec/rhc/helpers_spec.rb +52 -12
  87. data/spec/rhc/rest_application_spec.rb +16 -3
  88. data/spec/rhc/rest_client_spec.rb +144 -36
  89. data/spec/rhc/rest_spec.rb +1 -1
  90. data/spec/rhc/wizard_spec.rb +133 -232
  91. data/spec/spec_helper.rb +4 -3
  92. metadata +56 -31
  93. data/features/support/ssh.sh +0 -2
  94. data/spec/rhc/common_spec.rb +0 -49
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/threaddump'
4
+ require 'rhc/config'
5
+ describe RHC::Commands::Threaddump do
6
+ let(:client_links) { mock_response_links(mock_client_links) }
7
+ let(:domain_0_links) { mock_response_links(mock_domain_links('mock_domain_0')) }
8
+ let(:domain_1_links) { mock_response_links(mock_domain_links('mock_domain_1')) }
9
+ let(:app_0_links) { mock_response_links(mock_app_links('mock_domain_0', 'mock_app_0')) }
10
+ before(:each) do
11
+ RHC::Config.set_defaults
12
+ @rc = MockRestClient.new
13
+ @rc.add_domain("mock_domain_0").add_application("mock_app_0", "ruby-1.8.7")
14
+ stub_api_request(:any, client_links['LIST_DOMAINS']['relative']).with(:headers => {'Accept-Encoding'=>'gzip, deflate'}).
15
+ to_return({ :body => {
16
+ :type => 'domains',
17
+ :data =>
18
+ [{ :id => 'mock_domain_0',
19
+ :links => mock_response_links(mock_domain_links('mock_domain_0')),
20
+ },
21
+ { :id => 'mock_domain_1',
22
+ :links => mock_response_links(mock_domain_links('mock_domain_1')),
23
+ }]
24
+ }.to_json,
25
+ :status => 200
26
+ })
27
+ stub_api_request(:any, domain_0_links['LIST_APPLICATIONS']['relative']).with(:headers => {'Accept-Encoding'=>'gzip, deflate'}).
28
+ to_return({ :body => {
29
+ :type => 'applications',
30
+ :data =>
31
+ [{ :domain_id => 'mock_domain_0',
32
+ :name => 'mock_app_0',
33
+ :creation_time => Time.new.to_s,
34
+ :uuid => 1234,
35
+ :aliases => ['alias_1', 'alias_2'],
36
+ :server_identity => 'mock_server_identity',
37
+ :links => mock_response_links(mock_app_links('mock_domain_0','mock_app_0')),
38
+ }]
39
+ }.to_json,
40
+ :status => 200
41
+ })
42
+ stub_api_request(:any, app_0_links['THREAD_DUMP']['relative']).with(:body => {:event => 'thread-dump'}, :headers => {'Accept-Encoding'=>'gzip, deflate', 'Content-Length'=>'17', 'Content-Type'=>'application/x-www-form-urlencoded'}).
43
+ to_return({ :body => {
44
+ :type => 'application',
45
+ :data =>
46
+ { :domain_id => 'mock_domain_1',
47
+ :name => 'mock_app_0',
48
+ :creation_time => Time.new.to_s,
49
+ :uuid => 1234,
50
+ :aliases => ['alias_1', 'alias_2'],
51
+ :server_identity => 'mock_server_identity',
52
+ :links => mock_response_links(mock_app_links('mock_domain_1','mock_app_0')),
53
+ },
54
+ :messages => [{:text => 'Application test thread dump complete.: Success'}]
55
+ }.to_json,
56
+ :status => 200
57
+ })
58
+ end
59
+
60
+ describe 'help' do
61
+ let(:arguments) { ['threaddump', '--help'] }
62
+
63
+ context 'help is run' do
64
+ it "should display help" do
65
+ expect { run }.should exit_with_code(0)
66
+ end
67
+ it('should output usage') { run_output.should match("Usage: rhc threaddump") }
68
+ end
69
+ end
70
+
71
+ describe 'threaddump' do
72
+ let(:arguments) { ['threaddump', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password', 'mock_app_0'] }
73
+ context 'with no issues' do
74
+ it { expect { run }.should exit_with_code(0) }
75
+ end
76
+ end
77
+ describe 'threaddump no args' do
78
+ let(:arguments) { ['threaddump', '--noprompt', '--config', 'test.conf', '-l', 'test@test.foo', '-p', 'password'] }
79
+ context 'args not supplied' do
80
+ it { expect { run }.should exit_with_code(1) }
81
+ end
82
+ end
83
+ end
@@ -8,10 +8,10 @@ describe RHC::Config do
8
8
  ENV['http_proxy'] = nil
9
9
  mock_terminal
10
10
  FakeFS.activate!
11
+ FakeFS::FileSystem.clear
11
12
  end
12
13
 
13
14
  after(:all) do
14
- FakeFS::FileSystem.clear
15
15
  FakeFS.deactivate!
16
16
  end
17
17
 
@@ -254,22 +254,48 @@ describe RHC::Config do
254
254
  end
255
255
  end
256
256
 
257
- context "Odds and ends including error conditions" do
257
+ context "Proxy ENV variable parsing" do
258
+ before do
259
+ RHC::Config.initialize
260
+ ['http_proxy','HTTP_PROXY'].each do |var|
261
+ ENV[var] = nil
262
+ end
263
+ end
264
+
258
265
  it "should return a direct http connection" do
259
- proxy = RHC::Config.default_proxy
260
- proxy.should == Net::HTTP
266
+ RHC::Config.using_proxy?.should_not == true
261
267
  end
262
268
 
263
- it "should retrun a proxy http connection" do
264
- RHC::Config.initialize
265
- ENV['http_proxy'] = "fakeproxy.foo:8080"
266
- proxy = RHC::Config.default_proxy
267
- # returns a generic class so we check to make sure it is not a
268
- # Net::HTTP class and rely on simplecov to make sure the proxy
269
- # code path was run
270
- proxy.should_not == Net::HTTP
269
+ ['http_proxy','HTTP_PROXY'].each do |var|
270
+ it "should retrun a proxy http connection for #{var}" do
271
+ ENV[var] = "fakeproxy.foo:8080"
272
+ # returns a generic class so we check to make sure it is not a
273
+ # Net::HTTP class and rely on simplecov to make sure the proxy
274
+ # code path was run
275
+ RHC::Config.using_proxy?.should == true
276
+ end
271
277
  end
272
278
 
279
+ context "it should have the correct values" do
280
+ let(:vars){ RHC::Config.proxy_vars }
281
+ before do
282
+ ENV['http_proxy'] = "my_user:my_pass@fakeproxy.foo:8080"
283
+ end
284
+
285
+ {
286
+ :user => 'my_user',
287
+ :pass => 'my_pass',
288
+ :address => 'fakeproxy.foo',
289
+ :port => 8080
290
+ }.each do |var,expected|
291
+ it "for #{var}" do
292
+ vars[var].should == expected
293
+ end
294
+ end
295
+ end
296
+ end
297
+
298
+ context "Configuration file parsing" do
273
299
  it "should exit if config file can't be read" do
274
300
  ConfigHelper.write_out_config(ConfigHelper.global_config_path,
275
301
  "global.openshift.redhat.com",
@@ -325,6 +351,6 @@ class ConfigHelper
325
351
  f.write("libra_server = #{server}\n") unless server.nil?
326
352
  f.write("default_rhlogin = #{login}\n\n") unless login.nil?
327
353
  other.each { |key, value| f.write("#{key}=#{value}\n") }
354
+ end
328
355
  end
329
356
  end
330
- end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'rhc/commands/base'
3
+ require 'rhc/exceptions'
4
+
5
+ describe RHC::Commands::Base do
6
+ context 'when statically defined with context' do
7
+ subject do
8
+ Kernel.module_eval do
9
+ class Static < RHC::Commands::Base
10
+ suppress_wizard
11
+
12
+ def one_context
13
+ 1
14
+ end
15
+
16
+ def nil_context
17
+ nil
18
+ end
19
+
20
+ option ["--context-opt opt1"], "Test context option", :context => :one_context
21
+ summary "Test command execute with one_context"
22
+ def execute_with_one_context; return options.context_opt; end
23
+
24
+ option ["--context-opt opt1"], "Test context option", :context => :nil_context, :required => true
25
+ summary "Test command nil_context"
26
+ def execute_with_nil_context; return options.context_opt; end
27
+ end
28
+ end
29
+ Static
30
+ end
31
+
32
+ let(:instance) { subject.new }
33
+
34
+ context 'and when execute_with_one_context is called' do
35
+ it { expects_running('static', 'execute-with-one-context').should call(:one_context).on(instance).with(no_args) }
36
+ it { expects_running('static', 'execute-with-one-context').should exit_with_code(1) }
37
+ it { expects_running('static', 'execute-with-one-context', '--context-opt', 'opt').should call(:execute_with_one_context).on(instance).with(no_args) }
38
+ it { expects_running('static', 'execute-with-one-context', '--context-opt', 'opt').should exit_with_code('opt') }
39
+ end
40
+
41
+ context 'and when execute_with_nil_context is called' do
42
+ it { expects_running('static', 'execute-with-nil-context').should call(:nil_context).on(instance).with(no_args) }
43
+ it { expects_running('static', 'execute-with-nil-context', '--trace').should raise_error(ArgumentError) }
44
+ it { expects_running('static', 'execute-with-nil-context', '--context-opt', 'opt', '--trace').should call(:execute_with_nil_context).on(instance).with(no_args) }
45
+ it { expects_running('static', 'execute-with-nil-context', '--context-opt', 'opt', '--trace').should exit_with_code('opt') }
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+
@@ -4,13 +4,14 @@ require 'rhc/ssh_key_helpers'
4
4
  require 'rhc/core_ext'
5
5
  require 'highline/import'
6
6
  require 'rhc/config'
7
+ require 'rhc/helpers'
7
8
  require 'date'
8
9
 
9
10
  describe RHC::Helpers do
10
11
  before(:each) do
11
12
  mock_terminal
12
13
  RHC::Config.set_defaults
13
- @tests = HelperTests.new()
14
+ @tests = HelperTests.new
14
15
  end
15
16
 
16
17
  subject do
@@ -47,6 +48,12 @@ describe RHC::Helpers do
47
48
  end.should == ['10 2','3 40']
48
49
  end
49
50
 
51
+ it("should generate table rows"){ subject.send(:make_table, [1,2]).should == [1,2] }
52
+ it("should generate a table"){ subject.send(:make_table, 1).should == [1] }
53
+ it("should output a table") do
54
+ subject.send(:display_no_info, 'test').should == ['This test has no information to show']
55
+ end
56
+
50
57
  it "should parse an RFC3339 date" do
51
58
  d = subject.datetime_rfc3339('2012-06-24T20:48:20-04:00')
52
59
  d.day.should == 24
@@ -139,18 +146,12 @@ describe RHC::Helpers do
139
146
  end
140
147
 
141
148
  context "SSH Key Helpers" do
142
- before do
143
- FakeFS.activate!
144
- end
145
-
146
149
  it "should generate an ssh key then return nil when it tries to create another" do
147
- @tests.generate_ssh_key_ruby.should match("\.ssh/id_rsa\.pub")
148
- @tests.generate_ssh_key_ruby == nil
149
- end
150
-
151
- after do
152
- FakeFS::FileSystem.clear
153
- FakeFS.deactivate!
150
+ FakeFS do
151
+ FakeFS::FileSystem.clear
152
+ @tests.generate_ssh_key_ruby.should match("\.ssh/id_rsa\.pub")
153
+ @tests.generate_ssh_key_ruby == nil
154
+ end
154
155
  end
155
156
  end
156
157
 
@@ -254,3 +255,42 @@ describe OpenURI do
254
255
  specify('https to http') { OpenURI.redirectable?(URI.parse('https://foo.com'), URI.parse('http://foo.com')).should be_false }
255
256
  end
256
257
  end
258
+
259
+ describe HighLine do
260
+ it "should wrap the terminal" do
261
+ $terminal.wrap_at = 10
262
+ say "Lorem ipsum dolor sit amet"
263
+ output = $terminal.read
264
+ output.should match "Lorem\nipsum\ndolor sit\namet"
265
+ end
266
+ it "should wrap the terminal" do
267
+ $terminal.wrap_at = 16
268
+ say "Lorem ipsum dolor sit amet"
269
+ output = $terminal.read
270
+ output.should match "Lorem ipsum\ndolor sit amet"
271
+ end
272
+ it "should not wrap the terminal" do
273
+ $terminal.wrap_at = 50
274
+ say "Lorem ipsum dolor sit amet"
275
+ output = $terminal.read
276
+ output.should match "Lorem ipsum dolor sit amet"
277
+ end
278
+ it "should wrap the terminal when using color codes" do
279
+ $terminal.wrap_at = 10
280
+ say $terminal.color("Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet", :red)
281
+ output = $terminal.read
282
+ output.should match "Lorem\nipsum\ndolor sit\namet Lorem\nipsum\ndolor sit\namet"
283
+ end
284
+ it "should wrap the terminal with other escape characters" do
285
+ $terminal.wrap_at = 10
286
+ say "Lorem ipsum dolor sit am\eet"
287
+ output = $terminal.read
288
+ output.should match "Lorem\nipsum\ndolor sit\nam\eet"
289
+ end
290
+ it "should wrap the terminal when words are smaller than wrap length" do
291
+ $terminal.wrap_at = 3
292
+ say "Antidisestablishmentarianism"
293
+ output = $terminal.read
294
+ output.should match "Ant\nidi\nses\ntab\nlis\nhme\nnta\nria\nnis\nm"
295
+ end
296
+ end
@@ -30,7 +30,7 @@ module RHC
30
30
  it "returns an application object" do
31
31
  app = app_obj
32
32
  app.should be_an_instance_of RHC::Rest::Application
33
- app.instance_variable_get(:@links).length.should equal(app_links.length)
33
+ app.send(:links).length.should equal(app_links.length)
34
34
  end
35
35
  end
36
36
 
@@ -43,7 +43,7 @@ module RHC
43
43
  app = app_obj
44
44
  cart = app.add_cartridge('mock_cart_0')
45
45
  cart.should be_an_instance_of RHC::Rest::Cartridge
46
- cart.instance_variable_get(:@name).should == 'mock_cart_0'
46
+ cart.name.should == 'mock_cart_0'
47
47
  end
48
48
  end
49
49
 
@@ -59,7 +59,7 @@ module RHC
59
59
  carts.length.should equal(2)
60
60
  (0..1).each do |idx|
61
61
  carts[idx].should be_an_instance_of RHC::Rest::Cartridge
62
- carts[idx].instance_variable_get(:@name).should == "mock_cart_#{idx}"
62
+ carts[idx].name.should == "mock_cart_#{idx}"
63
63
  end
64
64
  end
65
65
  it "returns an empty list if the current app has no cartridges" do
@@ -70,6 +70,19 @@ module RHC
70
70
  end
71
71
  end
72
72
 
73
+ context "#gear_groups" do
74
+ before(:each) do
75
+ stub_api_request(:any, app_links['GET_GEAR_GROUPS']['relative']).
76
+ to_return(mock_gear_groups_response())
77
+ end
78
+ it "returns a list of all gear groups the current application" do
79
+ app = app_obj
80
+ gear_groups = app.gear_groups
81
+ gear_groups.length.should equal(1)
82
+ gear_groups[0].should be_an_instance_of RHC::Rest::GearGroup
83
+ end
84
+ end
85
+
73
86
  # These application control tests are subtle; the key lies in making sure the
74
87
  # webmock specifies the expected body that is sent in the request.
75
88
  # This is currently of the form "event=foo"
@@ -14,8 +14,8 @@ class MockClient < RHC::Rest::Client
14
14
  def logger
15
15
  Logger.new((@output = StringIO.new))
16
16
  end
17
- def debug
18
- @mydebug = true
17
+ def use_debug
18
+ @debug = true
19
19
  end
20
20
  def logged
21
21
  @output.string
@@ -28,13 +28,14 @@ module RHC
28
28
  let(:client_links) { mock_response_links(mock_client_links) }
29
29
  let(:domain_0_links) { mock_response_links(mock_domain_links('mock_domain_0')) }
30
30
  let(:domain_1_links) { mock_response_links(mock_domain_links('mock_domain_1')) }
31
+ let(:app_0_links) { mock_response_links(mock_app_links('mock_domain_0', 'mock_app')) }
31
32
  let(:user_links) { mock_response_links(mock_user_links) }
32
33
  let(:key_links) { mock_response_links(mock_key_links) }
33
34
 
34
35
  context "#new" do
35
36
  before do
36
37
  stub_api_request(:get, '').
37
- to_return({ :body => { :data => client_links }.to_json,
38
+ to_return({ :body => { :data => client_links, :supported_api_versions => [1.0, 1.1] }.to_json,
38
39
  :status => 200
39
40
  })
40
41
  stub_api_request(:get, 'api_error').
@@ -47,7 +48,7 @@ module RHC
47
48
  credentials = Base64.strict_encode64(mock_user + ":" + mock_pass)
48
49
  client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass)
49
50
  @@headers['Authorization'].should == "Basic #{credentials}"
50
- client.instance_variable_get(:@links).should == client_links
51
+ client.send(:links).should == client_links
51
52
  end
52
53
  it "does not add newlines to username and password > 60 characters" do
53
54
  username = "a" * 45
@@ -60,14 +61,68 @@ module RHC
60
61
  end
61
62
  it "raises a generic error for any other error condition" do
62
63
  lambda{ RHC::Rest::Client.new(mock_href('other_error'), mock_user, mock_pass) }.
63
- should raise_error("Resource could not be accessed:Other Error")
64
+ should raise_error("Failed to access resource: Other Error")
65
+ end
66
+ end
67
+
68
+ describe "#new" do
69
+ context "when server supports API versions [1.0, 1.1]" do
70
+ before :each do
71
+ stub_api_request(:get, '').
72
+ to_return({ :body => { :data => client_links, :supported_api_versions => [1.0, 1.1] }.to_json,
73
+ :status => 200
74
+ })
75
+ stub_api_request(:get, 'api_error').
76
+ to_raise(RestClient::ExceptionWithResponse.new('API Error'))
77
+ stub_api_request(:get, 'other_error').
78
+ to_raise(Exception.new('Other Error'))
79
+ end
80
+
81
+ context "when client is instantiated with [1.0, 1.1] as the preferred API versions" do
82
+ before :each do
83
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.0, 1.1])
84
+ end
85
+ it "settles on 1.1 as the API version" do
86
+ @client.api_version_negotiated.should == 1.1
87
+ end
88
+ end
89
+
90
+ context "when client is instantiated with [1.1, 1.0] as the preferred API versions" do
91
+ before :each do
92
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.1, 1.0])
93
+ end
94
+ it "settles on 1.0 as the API version" do
95
+ @client.api_version_negotiated.should == 1.0
96
+ end
97
+ end
98
+
99
+ context "when client is instantiated with [1.2, 1.3] as the preferred API versions" do
100
+ before :each do
101
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.2, 1.3])
102
+ end
103
+ it "fails to negotiate an agreeable API version" do
104
+ @client.api_version_negotiated.should be_nil
105
+ end
106
+ end
107
+
108
+ context "when client is instantiated with [1.1, 1.0, 1.3] as the preferred API versions" do
109
+ before :each do
110
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.1, 1.0, 1.3])
111
+ end
112
+ it "settles on 1.0 as the API version" do
113
+ @client.api_version_negotiated.should == 1.0
114
+ end
115
+ end
64
116
  end
65
117
  end
66
118
 
67
119
  context "with an instantiated client " do
68
120
  before(:each) do
69
121
  stub_api_request(:get, '').
70
- to_return({ :body => { :data => client_links }.to_json,
122
+ to_return({ :body => {
123
+ :data => client_links,
124
+ :supported_api_versions => [1.0, 1.1]
125
+ }.to_json,
71
126
  :status => 200
72
127
  })
73
128
  @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass)
@@ -78,6 +133,7 @@ module RHC
78
133
  stub_api_request(:any, client_links['ADD_DOMAIN']['relative']).
79
134
  to_return({ :body => {
80
135
  :type => 'domain',
136
+ :supported_api_versions => [1.0, 1.1],
81
137
  :data => {
82
138
  :id => 'mock_domain',
83
139
  :links => mock_response_links(mock_domain_links('mock_domain')),
@@ -88,9 +144,9 @@ module RHC
88
144
  end
89
145
  it "returns a domain object" do
90
146
  domain = @client.add_domain('mock_domain')
91
- domain.class.should == RHC::Rest::Domain
92
- domain.instance_variable_get(:@id).should == 'mock_domain'
93
- domain.instance_variable_get(:@links).should ==
147
+ domain.class.should == RHC::Rest::Domain
148
+ domain.id.should == 'mock_domain'
149
+ domain.send(:links).should ==
94
150
  mock_response_links(mock_domain_links('mock_domain'))
95
151
  end
96
152
  end
@@ -122,8 +178,8 @@ module RHC
122
178
  domains.length.should equal(2)
123
179
  (0..1).each do |idx|
124
180
  domains[idx].class.should == RHC::Rest::Domain
125
- domains[idx].instance_variable_get(:@id).should == "mock_domain_#{idx}"
126
- domains[idx].instance_variable_get(:@links).should ==
181
+ domains[idx].id.should == "mock_domain_#{idx}"
182
+ domains[idx].send(:links).should ==
127
183
  mock_response_links(mock_domain_links("mock_domain_#{idx}"))
128
184
  end
129
185
  end
@@ -214,9 +270,9 @@ module RHC
214
270
  domain.applications.each do |app|
215
271
  match = domain.find_application(app.name)
216
272
  match.class.should == RHC::Rest::Application
217
- match.instance_variable_get(:@name).should == 'mock_app'
218
- match.instance_variable_get(:@domain_id).should == "#{domain.id}"
219
- match.instance_variable_get(:@links).should ==
273
+ match.name.should == 'mock_app'
274
+ match.domain_id.should == "#{domain.id}"
275
+ match.send(:links).should ==
220
276
  mock_response_links(mock_app_links("#{domain.id}",'mock_app'))
221
277
  end
222
278
  end
@@ -254,9 +310,9 @@ module RHC
254
310
  carts.length.should equal(2)
255
311
  (0..1).each do |idx|
256
312
  carts[idx].class.should == RHC::Rest::Cartridge
257
- carts[idx].instance_variable_get(:@name).should == "mock_cart_#{idx}"
258
- carts[idx].instance_variable_get(:@type).should == "mock_cart_#{idx}_type"
259
- carts[idx].instance_variable_get(:@links).should ==
313
+ carts[idx].name.should == "mock_cart_#{idx}"
314
+ carts[idx].type.should == "mock_cart_#{idx}_type"
315
+ carts[idx].send(:links).should ==
260
316
  mock_response_links(mock_cart_links("mock_cart_#{idx}"))
261
317
  end
262
318
  end
@@ -295,9 +351,9 @@ module RHC
295
351
  matches = @client.find_cartridges('mock_cart_0')
296
352
  matches.length.should equal(1)
297
353
  matches[0].class.should == RHC::Rest::Cartridge
298
- matches[0].instance_variable_get(:@name).should == 'mock_cart_0'
299
- matches[0].instance_variable_get(:@type).should == 'mock_cart_0_type'
300
- matches[0].instance_variable_get(:@links).should ==
354
+ matches[0].name.should == 'mock_cart_0'
355
+ matches[0].type.should == 'mock_cart_0_type'
356
+ matches[0].send(:links).should ==
301
357
  mock_response_links(mock_cart_links('mock_cart_0'))
302
358
  end
303
359
  it "returns an empty list when no matching cartridges can be found" do
@@ -326,8 +382,8 @@ module RHC
326
382
  it "returns the user object associated with this client connection" do
327
383
  user = @client.user
328
384
  user.class.should == RHC::Rest::User
329
- user.instance_variable_get(:@login).should == mock_user
330
- user.instance_variable_get(:@links).should == mock_response_links(mock_user_links)
385
+ user.login.should == mock_user
386
+ user.send(:links).should == mock_response_links(mock_user_links)
331
387
  end
332
388
  end
333
389
 
@@ -366,10 +422,10 @@ module RHC
366
422
  expect { key = @client.find_key('mock_key_0') }.should_not raise_error
367
423
 
368
424
  key.class.should == RHC::Rest::Key
369
- key.instance_variable_get(:@name).should == 'mock_key_0'
370
- key.instance_variable_get(:@type).should == 'mock_key_0_type'
371
- key.instance_variable_get(:@content).should == '123456789:0'
372
- key.instance_variable_get(:@links).should ==
425
+ key.name.should == 'mock_key_0'
426
+ key.type.should == 'mock_key_0_type'
427
+ key.content.should == '123456789:0'
428
+ key.send(:links).should ==
373
429
  mock_response_links(mock_key_links('mock_key_0'))
374
430
  end
375
431
  it "raise an error when no matching keys can be found" do
@@ -380,25 +436,28 @@ module RHC
380
436
  shared_examples_for "a logout method" do
381
437
  before(:each) do
382
438
  stub_api_request(:get, '').
383
- to_return({ :body => { :data => client_links }.to_json,
439
+ to_return({ :body => { :data => client_links, :supported_api_versions => [1.0, 1.1] }.to_json,
384
440
  :status => 200
385
441
  })
386
- @client = MockClient.new(mock_href, mock_user, mock_pass)
387
442
  end
388
443
  context "debug mode is on" do
389
444
  it "writes a message to the logger" do
390
- @client.debug
391
- @client.logger # starts our mock logger
392
- eval '@client.' + logout_method.to_s
393
- @client.logged.should =~ /Logout\/Close client$/
445
+ capture do
446
+ @client = MockClient.new(mock_href, mock_user, mock_pass, true)
447
+ @client.send logout_method.to_sym
448
+ $stderr.rewind
449
+ $stderr.read.should =~ /Logout\/Close client$/
450
+ end
394
451
  end
395
452
  end
396
453
  context "debug mode is off" do
397
454
  it "does nothing" do
398
- @client = MockClient.new(mock_href, mock_user, mock_pass)
399
- @client.logger # starts our mock logger
400
- eval '@client.' + logout_method.to_s
401
- @client.logged.should == ''
455
+ capture do
456
+ @client = MockClient.new(mock_href, mock_user, mock_pass, false)
457
+ @client.send logout_method.to_sym
458
+ $stderr.rewind
459
+ $stderr.read.should == ''
460
+ end
402
461
  end
403
462
  end
404
463
  end
@@ -461,6 +520,55 @@ module RHC
461
520
  it_should_behave_like "a logout method"
462
521
  end
463
522
  end
523
+
524
+ context "when server supports API versions 1.0 and 1.1" do
525
+ before :each do
526
+ stub_api_request(:get, '').
527
+ to_return({ :body => {
528
+ :data => client_links,
529
+ :supported_api_versions => [1.0, 1.1]
530
+ }.to_json,
531
+ :status => 200
532
+ })
533
+ end
534
+
535
+ context "when client supports API version 1.1" do
536
+ before :each do
537
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.1])
538
+ end
539
+
540
+ describe "#api_version_negotiated" do
541
+ it "returns 1.1" do
542
+ @client.api_version_negotiated.to_s.should == '1.1'
543
+ end
544
+ end
545
+ end
546
+
547
+ context "when client supports only API version 1.2" do
548
+ before :each do
549
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [1.2])
550
+ end
551
+
552
+ describe "#api_version_negotiated" do
553
+ it 'returns nil' do
554
+ @client.api_version_negotiated.should be_nil
555
+ end
556
+ end
557
+ end
558
+
559
+ context "when client supports only API version 0.9" do
560
+ describe "#new" do
561
+ it "warns user that it is outdated" do
562
+ capture do
563
+ @client = RHC::Rest::Client.new(mock_href, mock_user, mock_pass, false, [0.9])
564
+ @output.rewind
565
+ @output.read.should =~ /client version may be outdated/
566
+ end
567
+ end
568
+ end
569
+ end
570
+ end
571
+
464
572
  end
465
573
  end
466
574
  end
@@ -55,7 +55,7 @@ module RHC
55
55
  :links => { :foo => 'bar' }
56
56
  }}
57
57
  it "deserializes to an application" do
58
- json_response = { :type => 'application', :data => object }.to_json
58
+ json_response = { :type => 'application', :data => object, :messages => [{'text' => 'test message'}]}.to_json
59
59
  app_obj = RHC::Rest::Application.new(object)
60
60
  subject.parse_response(json_response).should have_same_attributes_as(app_obj)
61
61
  end