misty 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/misty/auth.rb +5 -13
- data/lib/misty/auth/auth_v2.rb +13 -11
- data/lib/misty/auth/auth_v3.rb +11 -9
- data/lib/misty/auth/errors.rb +12 -0
- data/lib/misty/auth/name.rb +4 -4
- data/lib/misty/client.rb +105 -0
- data/lib/misty/client_pack.rb +16 -0
- data/lib/misty/http/method_builder.rb +36 -20
- data/lib/misty/misty.rb +14 -0
- data/lib/misty/openstack/aodh/aodh_v2.rb +1 -1
- data/lib/misty/openstack/aodh/v2.rb +5 -8
- data/lib/misty/openstack/ceilometer/ceilometer_v2.rb +1 -1
- data/lib/misty/openstack/ceilometer/v2.rb +5 -8
- data/lib/misty/openstack/cinder/cinder_v1.rb +1 -1
- data/lib/misty/openstack/cinder/cinder_v2.rb +1 -1
- data/lib/misty/openstack/cinder/cinder_v3.rb +1 -1
- data/lib/misty/openstack/cinder/v1.rb +6 -9
- data/lib/misty/openstack/cinder/v2.rb +6 -9
- data/lib/misty/openstack/cinder/v3.rb +7 -10
- data/lib/misty/openstack/designate/designate_v2.rb +1 -1
- data/lib/misty/openstack/designate/v2.rb +5 -8
- data/lib/misty/openstack/extension.rb +33 -0
- data/lib/misty/openstack/freezer/freezer_v1.rb +1 -1
- data/lib/misty/openstack/freezer/v1.rb +5 -8
- data/lib/misty/openstack/glance/glance_v1.rb +1 -1
- data/lib/misty/openstack/glance/glance_v2.rb +1 -1
- data/lib/misty/openstack/glance/v1.rb +5 -8
- data/lib/misty/openstack/glance/v2.rb +5 -8
- data/lib/misty/openstack/heat/heat_v1.rb +1 -1
- data/lib/misty/openstack/heat/v1.rb +6 -9
- data/lib/misty/openstack/ironic/ironic_v1.rb +1 -1
- data/lib/misty/openstack/ironic/v1.rb +6 -9
- data/lib/misty/openstack/karbor/karbor_v1.rb +1 -1
- data/lib/misty/openstack/karbor/v1.rb +5 -8
- data/lib/misty/openstack/keystone/keystone_v2_0.rb +1 -1
- data/lib/misty/openstack/keystone/keystone_v2_0_ext.rb +2 -2
- data/lib/misty/openstack/keystone/keystone_v3.rb +1 -1
- data/lib/misty/openstack/keystone/keystone_v3_ext.rb +2 -2
- data/lib/misty/openstack/keystone/v2_0.rb +8 -10
- data/lib/misty/openstack/keystone/v3.rb +8 -10
- data/lib/misty/openstack/magnum/magnum_v1.rb +1 -1
- data/lib/misty/openstack/magnum/v1.rb +6 -9
- data/lib/misty/openstack/manila/manila_v2.rb +1 -1
- data/lib/misty/openstack/manila/v2.rb +6 -9
- data/lib/misty/openstack/murano/murano_v1.rb +1 -1
- data/lib/misty/openstack/murano/v1.rb +5 -8
- data/lib/misty/openstack/neutron/neutron_v2_0.rb +1 -1
- data/lib/misty/openstack/neutron/v2_0.rb +5 -8
- data/lib/misty/openstack/nova/nova_v2_1.rb +1 -1
- data/lib/misty/openstack/nova/v2_1.rb +7 -9
- data/lib/misty/openstack/octavia/octavia_v2_0.rb +1 -1
- data/lib/misty/openstack/octavia/v2_0.rb +5 -8
- data/lib/misty/openstack/sahara/sahara_v1_1.rb +1 -1
- data/lib/misty/openstack/sahara/v1_1.rb +5 -8
- data/lib/misty/openstack/searchlight/searchlight_v1.rb +1 -1
- data/lib/misty/openstack/searchlight/v1.rb +5 -8
- data/lib/misty/openstack/senlin/senlin_v1.rb +1 -1
- data/lib/misty/openstack/senlin/v1.rb +5 -8
- data/lib/misty/openstack/swift/swift_v1.rb +1 -1
- data/lib/misty/openstack/swift/v1.rb +17 -9
- data/lib/misty/openstack/tacker/tacker_v1_0.rb +1 -1
- data/lib/misty/openstack/tacker/v1_0.rb +5 -8
- data/lib/misty/openstack/trove/trove_v1_0.rb +1 -1
- data/lib/misty/openstack/trove/v1_0.rb +5 -8
- data/lib/misty/openstack/zaqar/v2.rb +5 -8
- data/lib/misty/openstack/zaqar/zaqar_v2.rb +1 -1
- data/lib/misty/version.rb +1 -1
- data/test/unit/{http/client_test.rb → client_test.rb} +20 -8
- data/test/unit/cloud/requests_test.rb +77 -5
- data/test/unit/cloud/services_test.rb +20 -5
- data/test/unit/http/header_test.rb +0 -1
- data/test/unit/http/method_builder_test.rb +4 -4
- data/test/unit/http/request_test.rb +29 -20
- data/test/unit/microversion_test.rb +1 -1
- data/test/unit/misty_test.rb +18 -0
- data/test/unit/openstack/APIs_test.rb +18 -13
- data/test/unit/openstack/extension_test.rb +68 -0
- data/test/unit/service_helper.rb +1 -1
- metadata +8 -4
- data/lib/misty/http/client.rb +0 -108
data/lib/misty/version.rb
CHANGED
@@ -1,15 +1,27 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'service_helper'
|
3
|
-
require 'misty/
|
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
|
-
|
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
|
-
|
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::
|
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::
|
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::
|
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
|
-
|
85
|
-
|
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
|
-
|
88
|
-
|
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
|
-
|
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
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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
|
-
|
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
|
@@ -38,7 +38,7 @@ describe Misty::HTTP::MethodBuilder do
|
|
38
38
|
|
39
39
|
describe '#get_method' do
|
40
40
|
class Service
|
41
|
-
def
|
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
|
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
|
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
|
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
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
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
|
-
|
107
|
-
|
111
|
+
response = service.http_post('/resource', {}, "{\"data\":\"value\"}")
|
112
|
+
response.must_be_kind_of Net::HTTPCreated
|
113
|
+
end
|
108
114
|
end
|
109
115
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
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
|
-
|
116
|
-
|
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
|
data/test/unit/misty_test.rb
CHANGED
@@ -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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|