misty 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/lib/misty/auth.rb +5 -13
  3. data/lib/misty/auth/auth_v2.rb +13 -11
  4. data/lib/misty/auth/auth_v3.rb +11 -9
  5. data/lib/misty/auth/errors.rb +12 -0
  6. data/lib/misty/auth/name.rb +4 -4
  7. data/lib/misty/client.rb +105 -0
  8. data/lib/misty/client_pack.rb +16 -0
  9. data/lib/misty/http/method_builder.rb +36 -20
  10. data/lib/misty/misty.rb +14 -0
  11. data/lib/misty/openstack/aodh/aodh_v2.rb +1 -1
  12. data/lib/misty/openstack/aodh/v2.rb +5 -8
  13. data/lib/misty/openstack/ceilometer/ceilometer_v2.rb +1 -1
  14. data/lib/misty/openstack/ceilometer/v2.rb +5 -8
  15. data/lib/misty/openstack/cinder/cinder_v1.rb +1 -1
  16. data/lib/misty/openstack/cinder/cinder_v2.rb +1 -1
  17. data/lib/misty/openstack/cinder/cinder_v3.rb +1 -1
  18. data/lib/misty/openstack/cinder/v1.rb +6 -9
  19. data/lib/misty/openstack/cinder/v2.rb +6 -9
  20. data/lib/misty/openstack/cinder/v3.rb +7 -10
  21. data/lib/misty/openstack/designate/designate_v2.rb +1 -1
  22. data/lib/misty/openstack/designate/v2.rb +5 -8
  23. data/lib/misty/openstack/extension.rb +33 -0
  24. data/lib/misty/openstack/freezer/freezer_v1.rb +1 -1
  25. data/lib/misty/openstack/freezer/v1.rb +5 -8
  26. data/lib/misty/openstack/glance/glance_v1.rb +1 -1
  27. data/lib/misty/openstack/glance/glance_v2.rb +1 -1
  28. data/lib/misty/openstack/glance/v1.rb +5 -8
  29. data/lib/misty/openstack/glance/v2.rb +5 -8
  30. data/lib/misty/openstack/heat/heat_v1.rb +1 -1
  31. data/lib/misty/openstack/heat/v1.rb +6 -9
  32. data/lib/misty/openstack/ironic/ironic_v1.rb +1 -1
  33. data/lib/misty/openstack/ironic/v1.rb +6 -9
  34. data/lib/misty/openstack/karbor/karbor_v1.rb +1 -1
  35. data/lib/misty/openstack/karbor/v1.rb +5 -8
  36. data/lib/misty/openstack/keystone/keystone_v2_0.rb +1 -1
  37. data/lib/misty/openstack/keystone/keystone_v2_0_ext.rb +2 -2
  38. data/lib/misty/openstack/keystone/keystone_v3.rb +1 -1
  39. data/lib/misty/openstack/keystone/keystone_v3_ext.rb +2 -2
  40. data/lib/misty/openstack/keystone/v2_0.rb +8 -10
  41. data/lib/misty/openstack/keystone/v3.rb +8 -10
  42. data/lib/misty/openstack/magnum/magnum_v1.rb +1 -1
  43. data/lib/misty/openstack/magnum/v1.rb +6 -9
  44. data/lib/misty/openstack/manila/manila_v2.rb +1 -1
  45. data/lib/misty/openstack/manila/v2.rb +6 -9
  46. data/lib/misty/openstack/murano/murano_v1.rb +1 -1
  47. data/lib/misty/openstack/murano/v1.rb +5 -8
  48. data/lib/misty/openstack/neutron/neutron_v2_0.rb +1 -1
  49. data/lib/misty/openstack/neutron/v2_0.rb +5 -8
  50. data/lib/misty/openstack/nova/nova_v2_1.rb +1 -1
  51. data/lib/misty/openstack/nova/v2_1.rb +7 -9
  52. data/lib/misty/openstack/octavia/octavia_v2_0.rb +1 -1
  53. data/lib/misty/openstack/octavia/v2_0.rb +5 -8
  54. data/lib/misty/openstack/sahara/sahara_v1_1.rb +1 -1
  55. data/lib/misty/openstack/sahara/v1_1.rb +5 -8
  56. data/lib/misty/openstack/searchlight/searchlight_v1.rb +1 -1
  57. data/lib/misty/openstack/searchlight/v1.rb +5 -8
  58. data/lib/misty/openstack/senlin/senlin_v1.rb +1 -1
  59. data/lib/misty/openstack/senlin/v1.rb +5 -8
  60. data/lib/misty/openstack/swift/swift_v1.rb +1 -1
  61. data/lib/misty/openstack/swift/v1.rb +17 -9
  62. data/lib/misty/openstack/tacker/tacker_v1_0.rb +1 -1
  63. data/lib/misty/openstack/tacker/v1_0.rb +5 -8
  64. data/lib/misty/openstack/trove/trove_v1_0.rb +1 -1
  65. data/lib/misty/openstack/trove/v1_0.rb +5 -8
  66. data/lib/misty/openstack/zaqar/v2.rb +5 -8
  67. data/lib/misty/openstack/zaqar/zaqar_v2.rb +1 -1
  68. data/lib/misty/version.rb +1 -1
  69. data/test/unit/{http/client_test.rb → client_test.rb} +20 -8
  70. data/test/unit/cloud/requests_test.rb +77 -5
  71. data/test/unit/cloud/services_test.rb +20 -5
  72. data/test/unit/http/header_test.rb +0 -1
  73. data/test/unit/http/method_builder_test.rb +4 -4
  74. data/test/unit/http/request_test.rb +29 -20
  75. data/test/unit/microversion_test.rb +1 -1
  76. data/test/unit/misty_test.rb +18 -0
  77. data/test/unit/openstack/APIs_test.rb +18 -13
  78. data/test/unit/openstack/extension_test.rb +68 -0
  79. data/test/unit/service_helper.rb +1 -1
  80. metadata +8 -4
  81. data/lib/misty/http/client.rb +0 -108
@@ -1,5 +1,5 @@
1
1
  module Misty::Openstack::ZaqarV2
2
- def v2
2
+ def api
3
3
  {"/"=>{:GET=>[:list_major_versions]},
4
4
  "/v2/queues"=>{:GET=>[:list_queues]},
5
5
  "/v2/queues/{queue_name}"=>
@@ -1,3 +1,3 @@
1
1
  module Misty
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -1,15 +1,27 @@
1
1
  require 'test_helper'
2
2
  require 'service_helper'
3
- require 'misty/http/client'
3
+ require 'misty/client'
4
+
5
+ describe Misty::Client do
6
+ describe '#prefix_path_to_ignore' do
7
+ let(:client) do
8
+ client = Object.new
9
+ client.extend(Misty::Client)
10
+ client
11
+ end
4
12
 
5
- describe Misty::HTTP::Client do
6
- describe '#self.prefix_path_to_ignore' do
7
13
  it "returns empty String when undefined in API's module" do
8
- Misty::Openstack::Neutron::V2_0::prefix_path_to_ignore.must_be_empty
14
+ client.prefix_path_to_ignore.must_be_empty
9
15
  end
10
16
 
11
17
  it "returns String when defined in API's module" do
12
- Misty::Openstack::Cinder::V3.prefix_path_to_ignore.must_equal '/v3/{tenant_id}'
18
+ class << client
19
+ def prefix_path_to_ignore
20
+ '/v3/{tenant_id}'
21
+ end
22
+ end
23
+
24
+ client.prefix_path_to_ignore.must_equal '/v3/{tenant_id}'
13
25
  end
14
26
  end
15
27
 
@@ -30,7 +42,7 @@ describe Misty::HTTP::Client do
30
42
  describe '#setup' do
31
43
  it 'use default options' do
32
44
  options = service.send(:setup, {})
33
- options.must_be_kind_of Misty::HTTP::Client::Options
45
+ options.must_be_kind_of Misty::Client::Options
34
46
  options.base_path.must_be_nil
35
47
  options.base_url.must_be_nil
36
48
  options.headers.must_equal ({})
@@ -62,13 +74,13 @@ describe Misty::HTTP::Client do
62
74
  it 'fails with invalid interface' do
63
75
  proc do
64
76
  service.send(:setup, {:interface => 'something'})
65
- end.must_raise Misty::HTTP::Client::InvalidDataError
77
+ end.must_raise Misty::Client::InvalidDataError
66
78
  end
67
79
 
68
80
  it 'fails unless ssl_verify_mode is a boolean' do
69
81
  proc do
70
82
  service.send(:setup, {:ssl_verify_mode => 'something'})
71
- end.must_raise Misty::HTTP::Client::InvalidDataError
83
+ end.must_raise Misty::Client::InvalidDataError
72
84
  end
73
85
  end
74
86
 
@@ -81,13 +81,49 @@ describe Misty::Cloud do
81
81
  end
82
82
 
83
83
  it 'sucessful whith elements in pathwhith elements in path' do
84
- stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
85
- to_return(:status => 200, :body => JSON.dump(auth_response_v3('orchestration', 'heat')), :headers => {'x-subject-token'=>'token_data'})
84
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
85
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('orchestration', 'heat')), :headers => {'x-subject-token'=>'token_data'})
86
+
87
+ stub_request(:post, 'http://localhost/stacks/id1/id2/snapshots').
88
+ to_return(:status => 201, :body => 'snapshots', :headers => {})
89
+
90
+ cloud.orchestration.snapshot_a_stack('id1', 'id2', "{\"key\": \"value\"}").response.must_be_kind_of Net::HTTPCreated
91
+ end
92
+
93
+ it 'sucessful whith Array type data' do
94
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
95
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('network', 'neutron')), :headers => {'x-subject-token'=>'token_data'})
96
+
97
+ stub_request(:post, 'http://localhost/v2.0/networks').
98
+ with(:body => "[\"network\",{\"name\":\"network1\"}]").
99
+ with(:headers => {'Content-Type'=>'application/json'}).
100
+ to_return(:status => 201, :body => "", :headers => {})
101
+
102
+ cloud.networking.create_network(['network', {'name' => 'network1'}]).response.must_be_kind_of Net::HTTPCreated
103
+ end
104
+
105
+ it 'sucessful with Hash type data' do
106
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
107
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('network', 'neutron')), :headers => {'x-subject-token'=>'token_data'})
108
+
109
+ stub_request(:post, 'http://localhost/v2.0/networks').
110
+ with(:body => "{\"network\":{\"name\":\"network1\"}}").
111
+ with(:headers => {'Content-Type'=>'application/json'}).
112
+ to_return(:status => 201, :body => "", :headers => {})
113
+
114
+ cloud.networking.create_network({'network' => {'name' => 'network1'}}).response.must_be_kind_of Net::HTTPCreated
115
+ end
116
+
117
+ it 'sucessful with JSON String data' do
118
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
119
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('network', 'neutron')), :headers => {'x-subject-token'=>'token_data'})
86
120
 
87
- stub_request(:post, 'http://localhost/stacks/id1/id2/snapshots').
88
- to_return(:status => 201, :body => 'snapshots', :headers => {})
121
+ stub_request(:post, 'http://localhost/v2.0/networks').
122
+ with(:body => "{\"network\":{\"name\":\"network1\"}}").
123
+ with(:headers => {'Content-Type'=>'application/json'}).
124
+ to_return(:status => 201, :body => "", :headers => {})
89
125
 
90
- cloud.orchestration.snapshot_a_stack('id1', 'id2', "{\"key\": \"value\"}").response.must_be_kind_of Net::HTTPCreated
126
+ cloud.networking.create_network("{\"network\":{\"name\":\"network1\"}}").response.must_be_kind_of Net::HTTPCreated
91
127
  end
92
128
 
93
129
  it 'fails when not enough arguments' do
@@ -122,5 +158,41 @@ describe Misty::Cloud do
122
158
 
123
159
  cloud.identity.assign_role_to_group_on_domain('domain_id', 'group_id', 'roles_id').response.must_be_kind_of Net::HTTPOK
124
160
  end
161
+
162
+ it 'sucessful whith Array type data' do
163
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
164
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('network', 'neutron')), :headers => {'x-subject-token'=>'token_data'})
165
+
166
+ stub_request(:put, 'http://localhost/v2.0/networks/network_id').
167
+ with(:body => "[\"network\",{\"name\":\"network2\"}]").
168
+ with(:headers => {'Content-Type'=>'application/json'}).
169
+ to_return(:status => 200, :body => "", :headers => {})
170
+
171
+ cloud.networking.update_network('network_id', ['network', {'name' => 'network2'}]).response.must_be_kind_of Net::HTTPOK
172
+ end
173
+
174
+ it 'sucessful with Hash type data' do
175
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
176
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('network', 'neutron')), :headers => {'x-subject-token'=>'token_data'})
177
+
178
+ stub_request(:put, 'http://localhost/v2.0/networks/network_id').
179
+ with(:body => "{\"network\":{\"name\":\"network2\"}}").
180
+ with(:headers => {'Content-Type'=>'application/json'}).
181
+ to_return(:status => 200, :body => "", :headers => {})
182
+
183
+ cloud.networking.update_network('network_id', {'network' => {'name' => 'network2'}}).response.must_be_kind_of Net::HTTPOK
184
+ end
185
+
186
+ it 'sucessful with JSON String data' do
187
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
188
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('network', 'neutron')), :headers => {'x-subject-token'=>'token_data'})
189
+
190
+ stub_request(:put, 'http://localhost/v2.0/networks/network_id').
191
+ with(:body => "{\"network\":{\"name\":\"network2\"}}").
192
+ with(:headers => {'Content-Type'=>'application/json'}).
193
+ to_return(:status => 200, :body => "", :headers => {})
194
+
195
+ cloud.networking.update_network('network_id', "{\"network\":{\"name\":\"network2\"}}").response.must_be_kind_of Net::HTTPOK
196
+ end
125
197
  end
126
198
  end
@@ -160,12 +160,27 @@ describe 'Misty::Cloud' do
160
160
  cloud.nfv_orchestration.must_be_kind_of Misty::Openstack::Tacker::V1_0
161
161
  end
162
162
 
163
- it '#objectStorage' do
164
- stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
165
- with(:body => JSON.dump(auth_body), :headers => auth_headers).
166
- to_return(:status => 200, :body => JSON.dump(auth_response_v3('object-store', 'swift')), :headers => token_header)
163
+ describe '#objectStorage' do
164
+ it 'initialize with success' do
165
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
166
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
167
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('object-store', 'swift')), :headers => token_header)
168
+
169
+ cloud.object_storage.must_be_kind_of Misty::Openstack::Swift::V1
170
+ end
167
171
 
168
- cloud.object_storage.must_be_kind_of Misty::Openstack::Swift::V1
172
+ it 'execute bulk_delete' do
173
+ stub_request(:post, 'http://localhost:5000/v3/auth/tokens').
174
+ with(:body => JSON.dump(auth_body), :headers => auth_headers).
175
+ to_return(:status => 200, :body => JSON.dump(auth_response_v3('object-store', 'swift')), :headers => token_header)
176
+
177
+ stub_request(:post, "http://localhost/?bulk-delete=1").
178
+ with(:headers => {'Accept'=>'application/json; q=1.0', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'text/plain', 'User-Agent'=>'Ruby', 'X-Auth-Token'=>'token_data'}).
179
+ to_return(:status => 200, :body => "", :headers => {})
180
+
181
+ cloud.object_storage.requests.must_include :bulk_delete
182
+ cloud.object_storage.bulk_delete("container1/object1")
183
+ end
169
184
  end
170
185
 
171
186
  it '#orchestration' do
@@ -1,5 +1,4 @@
1
1
  require 'test_helper'
2
- require 'misty/http/client'
3
2
 
4
3
  describe Misty::HTTP::Header do
5
4
  describe 'create' do
@@ -38,7 +38,7 @@ describe Misty::HTTP::MethodBuilder do
38
38
 
39
39
  describe '#get_method' do
40
40
  class Service
41
- def self.api
41
+ def api
42
42
  {
43
43
  '/' => { GET: [:list_api_versions] },
44
44
  '/v2.0/' => { GET: [:show_api_v2_details] },
@@ -79,7 +79,7 @@ describe Misty::HTTP::MethodBuilder do
79
79
  describe '#prefixed_path' do
80
80
  it 'returns true and same path with empty prefix' do
81
81
  class Service
82
- def self.prefix_path_to_ignore
82
+ def prefix_path_to_ignore
83
83
  ''
84
84
  end
85
85
  end
@@ -92,7 +92,7 @@ describe Misty::HTTP::MethodBuilder do
92
92
 
93
93
  it 'returns false and same path when unmatched prefix' do
94
94
  class Service
95
- def self.prefix_path_to_ignore
95
+ def prefix_path_to_ignore
96
96
  '/v3/{project_id}'
97
97
  end
98
98
  end
@@ -105,7 +105,7 @@ describe Misty::HTTP::MethodBuilder do
105
105
 
106
106
  it 'returns true and filtered path when matched prefix' do
107
107
  class Service
108
- def self.prefix_path_to_ignore
108
+ def prefix_path_to_ignore
109
109
  '/v3/{project_id}'
110
110
  end
111
111
  end
@@ -88,32 +88,41 @@ describe Misty::HTTP::Request do
88
88
  response.must_be_kind_of Net::HTTPSuccess
89
89
  end
90
90
 
91
- it '#http_patch' do
92
- stub_request(:patch, 'http://localhost/resource').
93
- with(:headers => request_header).
94
- to_return(:status => 202, :body => "{\"key\": \"value\"}")
95
-
96
- response = service.http_patch('/resource', {}, 'data' => 'value')
97
- response.must_be_kind_of Net::HTTPAccepted
98
- response.body.wont_be_nil
91
+ describe '#http_patch' do
92
+ it 'successful with data of type String' do
93
+ stub_request(:patch, 'http://localhost/resource').
94
+ with(:body => "{\"data\":\"value\"}").
95
+ with(:headers => request_header).
96
+ to_return(:status => 202, :body => "{\"key\": \"value\"}")
97
+
98
+ response = service.http_patch('/resource', {}, "{\"data\":\"value\"}")
99
+ response.must_be_kind_of Net::HTTPAccepted
100
+ response.body.wont_be_nil
101
+ end
99
102
  end
100
103
 
101
- it '#http_post' do
102
- stub_request(:post, 'http://localhost/resource').
103
- with(:headers => request_header).
104
- to_return(:status => 201)
104
+ describe '#http_post' do
105
+ it 'successful with data of type String' do
106
+ stub_request(:post, 'http://localhost/resource').
107
+ with(:body => "{\"data\":\"value\"}").
108
+ with(:headers => request_header).
109
+ to_return(:status => 201)
105
110
 
106
- response = service.http_post('/resource', {}, 'data' => 'value')
107
- response.must_be_kind_of Net::HTTPCreated
111
+ response = service.http_post('/resource', {}, "{\"data\":\"value\"}")
112
+ response.must_be_kind_of Net::HTTPCreated
113
+ end
108
114
  end
109
115
 
110
- it '#http_put' do
111
- stub_request(:put, 'http://localhost/resource').
112
- with(:headers => request_header).
113
- to_return(:status => 200)
116
+ describe '#http_put' do
117
+ it 'successful with data of type String' do
118
+ stub_request(:put, 'http://localhost/resource').
119
+ with(:body => "{\"data\":\"value\"}").
120
+ with(:headers => request_header).
121
+ to_return(:status => 200)
114
122
 
115
- response = service.http_put('/resource', {}, 'data' => 'value')
116
- response.must_be_kind_of Net::HTTPOK
123
+ response = service.http_put('/resource', {}, "{\"data\":\"value\"}")
124
+ response.must_be_kind_of Net::HTTPOK
125
+ end
117
126
  end
118
127
 
119
128
  it '#http_to_s' do
@@ -1,6 +1,6 @@
1
1
  require 'test_helper'
2
2
  require 'auth_helper'
3
- require 'misty/http/client'
3
+ require 'misty/client'
4
4
  require 'misty/microversion'
5
5
 
6
6
  describe Misty::Microversion do
@@ -142,6 +142,24 @@ describe Misty do
142
142
  end
143
143
  end
144
144
 
145
+ describe '#json_encode?' do
146
+ it 'true with a Array type' do
147
+ Misty.json_encode?([]).must_equal true
148
+ end
149
+
150
+ it 'true with a Hash type' do
151
+ Misty.json_encode?({}).must_equal true
152
+ end
153
+
154
+ it 'true with a JSON String type' do
155
+ Misty.json_encode?('{"JSON_Key": "JSON_Value"}').must_equal true
156
+ end
157
+
158
+ it 'false with a non JSON String type' do
159
+ Misty.json_encode?("Just a string").must_equal false
160
+ end
161
+ end
162
+
145
163
  describe '#to_json' do
146
164
  it 'returns a JSON string when using a Ruby hash' do
147
165
  Misty.to_json({'key' => 'val'}).must_be_kind_of String
@@ -21,20 +21,25 @@ def api_valid?(api_entry)
21
21
  end
22
22
  end
23
23
 
24
- # For each OpenStack project version, generates an equivalent of the following example:
25
- # it 'Nova v2.1 loads a valid api structure' do
26
- # require 'misty/openstack/nova/v2_1'
27
- # api = Misty::Openstack::Nova::V2_1.api
28
- # api_valid?(api)
29
- # end
24
+ def api_validate(project, version)
25
+ it "#{project} #{version} loads a valid api structure" do
26
+ require "misty/openstack/#{project}/#{project}_#{Misty::Cloud.dot_to_underscore(version)}"
27
+ klass = Object.const_get("Misty::Openstack::#{project.capitalize}#{Misty::Cloud.dot_to_underscore(version).capitalize}")
28
+ client = Object.new
29
+ client.extend(klass)
30
+ api_valid?(client.api)
31
+ end
32
+ end
33
+
34
+ # Assert each version of OpenStack project loads a valid api structure
30
35
  describe 'Openstack API' do
31
36
  Misty.services.each do |service|
32
- #service.versions.each do |version|
33
- # it "#{service.project} #{version} loads a valid api structure" do
34
- # require "misty/openstack/#{service.project}/#{Misty::Cloud.dot_to_underscore(version)}"
35
- # api = Object.const_get("Misty::Openstack::#{service.project.capitalize}::#{Misty::Cloud.dot_to_underscore(version).capitalize}").api
36
- # api_valid?(api)
37
- # end
38
- #end
37
+ if service.versions
38
+ service.versions.each do |version|
39
+ api_validate(service.project, version)
40
+ end
41
+ elsif service.microversion && !service.microversion.empty?
42
+ api_validate(service.project, service.microversion)
43
+ end
39
44
  end
40
45
  end
@@ -0,0 +1,68 @@
1
+ require 'test_helper'
2
+ require 'misty/openstack/extension'
3
+
4
+ module DummyTestOpenstackExtension
5
+ def api
6
+ {
7
+ "/v1/resource1" => {
8
+ :POST => [:method1, :method2],
9
+ :GET => [:method3, :method4]
10
+ },
11
+ "/v2/resource2/{id}" => {
12
+ :GET =>[:method5, :method6],
13
+ :PATCH =>[:method7, :method8],
14
+ :DELETE =>[:method9, :method10]
15
+ }
16
+ }
17
+ end
18
+
19
+ def api_ext
20
+ {
21
+ "/v1/resource1" => {
22
+ :POST => [:method11, :method12],
23
+ :PUT => [:method13, :method14]
24
+ },
25
+ "/v1/resource3" => {
26
+ :POST => [:method, :method],
27
+ :GET => [:method]
28
+ }
29
+ }
30
+ end
31
+ end
32
+
33
+ describe Misty::Openstack::Extension do
34
+ let(:v1) do
35
+ v1 = Object.new
36
+ v1.extend(DummyTestOpenstackExtension)
37
+ v1.extend(Misty::Openstack::Extension)
38
+ v1
39
+ end
40
+
41
+ describe "Succesful" do
42
+ it "Adds methods to existing Verb" do
43
+ v1.api["/v1/resource1"][:POST].must_include :method11
44
+ end
45
+
46
+ it "Adds Verb" do
47
+ v1.api["/v1/resource1"].must_include :PUT
48
+ end
49
+
50
+ it "Adds Resource" do
51
+ v1.api.must_include "/v1/resource3"
52
+ end
53
+ end
54
+
55
+ describe "Fails" do
56
+ it "Raise RuntimeError when a resource already exist" do
57
+ class << v1
58
+ def api_ext
59
+ { "/v1/resource1" => { :POST => [:method1] } }
60
+ end
61
+ end
62
+
63
+ proc do
64
+ v1.api
65
+ end.must_raise RuntimeError
66
+ end
67
+ end
68
+ end