rhc 0.98.16 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
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