deltacloud-core 0.0.2 → 0.0.3
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.
- data/COPYING +176 -502
- data/Rakefile +21 -14
- data/deltacloud.rb +3 -0
- data/lib/deltacloud/base_driver.rb +12 -11
- data/lib/deltacloud/base_driver/base_driver.rb +22 -11
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +15 -12
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +16 -11
- data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +13 -11
- data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +12 -11
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +12 -11
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +12 -11
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +12 -11
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +14 -12
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +12 -11
- data/lib/deltacloud/helpers/application_helper.rb +64 -11
- data/lib/deltacloud/helpers/conversion_helper.rb +12 -11
- data/lib/deltacloud/method_serializer.rb +12 -11
- data/lib/deltacloud/models/base_model.rb +12 -11
- data/lib/deltacloud/models/image.rb +12 -11
- data/lib/deltacloud/models/instance.rb +13 -12
- data/lib/deltacloud/models/instance_profile.rb +12 -11
- data/lib/deltacloud/models/realm.rb +12 -11
- data/lib/deltacloud/models/storage_snapshot.rb +12 -11
- data/lib/deltacloud/models/storage_volume.rb +12 -11
- data/lib/drivers.rb +12 -0
- data/lib/sinatra/rabbit.rb +1 -0
- data/lib/sinatra/respond_to.rb +3 -0
- data/server.rb +40 -80
- data/tests/api_test.rb +37 -0
- data/tests/hardware_profiles_test.rb +120 -0
- data/tests/images_test.rb +95 -78
- data/tests/instance_states_test.rb +52 -0
- data/tests/instances_test.rb +193 -110
- data/tests/realms_test.rb +66 -44
- data/views/errors/not_found.html.haml +6 -0
- data/views/errors/not_found.xml.haml +2 -0
- data/views/hardware_profiles/index.xml.haml +1 -1
- data/views/hardware_profiles/show.xml.haml +3 -2
- data/views/images/index.xml.haml +4 -3
- data/views/images/show.xml.haml +2 -2
- data/views/instances/index.xml.haml +6 -8
- data/views/instances/show.xml.haml +9 -10
- data/views/realms/index.xml.haml +1 -3
- data/views/realms/show.xml.haml +4 -5
- data/views/storage_snapshots/index.xml.haml +3 -5
- data/views/storage_snapshots/show.xml.haml +2 -4
- data/views/storage_volumes/index.xml.haml +7 -7
- data/views/storage_volumes/show.xml.haml +2 -4
- metadata +156 -81
- data/tests/deltacloud_test.rb +0 -60
- data/tests/storage_snapshots_test.rb +0 -48
- data/tests/storage_volumes_test.rb +0 -48
@@ -1,19 +1,20 @@
|
|
1
1
|
#
|
2
2
|
# Copyright (C) 2009 Red Hat, Inc.
|
3
3
|
#
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
5
|
+
# contributor license agreements. See the NOTICE file distributed with
|
6
|
+
# this work for additional information regarding copyright ownership. The
|
7
|
+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
8
|
+
# "License"); you may not use this file except in compliance with the
|
9
|
+
# License. You may obtain a copy of the License at
|
8
10
|
#
|
9
|
-
#
|
10
|
-
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
12
|
-
# Lesser General Public License for more details.
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
13
12
|
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
15
|
+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
16
|
+
# License for the specific language governing permissions and limitations
|
17
|
+
# under the License.
|
17
18
|
|
18
19
|
|
19
20
|
class StorageVolume < BaseModel
|
data/lib/drivers.rb
CHANGED
@@ -9,6 +9,18 @@ DRIVERS = {
|
|
9
9
|
:mock => { :name => "Mock" }
|
10
10
|
}
|
11
11
|
|
12
|
+
DEFAULT_COLLECTIONS = [
|
13
|
+
:hardware_profiles,
|
14
|
+
:images,
|
15
|
+
:instances,
|
16
|
+
:instance_states,
|
17
|
+
:realms,
|
18
|
+
:storage_volumes,
|
19
|
+
:storage_snapshots
|
20
|
+
]
|
21
|
+
|
22
|
+
DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
|
23
|
+
|
12
24
|
def driver_name
|
13
25
|
DRIVERS[DRIVER][:name]
|
14
26
|
end
|
data/lib/sinatra/rabbit.rb
CHANGED
@@ -203,6 +203,7 @@ module Sinatra
|
|
203
203
|
# operation on this collection.
|
204
204
|
def collection(name, &block)
|
205
205
|
raise DuplicateCollectionException if collections[name]
|
206
|
+
return unless driver.has_collection?(name.to_sym)
|
206
207
|
collections[name] = Collection.new(name, &block)
|
207
208
|
collections[name].add_feature_params(driver.features(name))
|
208
209
|
collections[name].generate
|
data/lib/sinatra/respond_to.rb
CHANGED
data/server.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
|
-
require '
|
1
|
+
require 'sinatra'
|
2
2
|
require 'deltacloud'
|
3
|
+
require 'drivers'
|
3
4
|
require 'json'
|
4
|
-
require 'sinatra'
|
5
5
|
require 'sinatra/respond_to'
|
6
|
-
require 'erb'
|
7
|
-
require 'haml'
|
8
|
-
require 'open3'
|
9
|
-
require 'builder'
|
10
|
-
require 'drivers'
|
11
6
|
require 'sinatra/static_assets'
|
12
7
|
require 'sinatra/rabbit'
|
13
8
|
require 'sinatra/lazy_auth'
|
14
|
-
require '
|
15
|
-
require '
|
9
|
+
require 'erb'
|
10
|
+
require 'haml'
|
11
|
+
require 'open3'
|
16
12
|
|
17
13
|
configure do
|
18
14
|
set :raise_errors => false
|
15
|
+
set :show_exceptions, false
|
19
16
|
end
|
20
17
|
|
21
18
|
configure :development do
|
@@ -24,59 +21,10 @@ configure :development do
|
|
24
21
|
$stderr.sync = true
|
25
22
|
end
|
26
23
|
|
27
|
-
DRIVER=ENV['API_DRIVER'] ? ENV['API_DRIVER'].to_sym : :mock
|
28
|
-
|
29
24
|
# You could use $API_HOST environment variable to change your hostname to
|
30
25
|
# whatever you want (eg. if you running API behind NAT)
|
31
26
|
HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
|
32
27
|
|
33
|
-
Rack::Mime::MIME_TYPES.merge!({ ".gv" => "text/plain" })
|
34
|
-
|
35
|
-
Sinatra::Application.register Sinatra::RespondTo
|
36
|
-
|
37
|
-
# Common actions
|
38
|
-
#
|
39
|
-
|
40
|
-
def filter_all(model)
|
41
|
-
filter = {}
|
42
|
-
filter.merge!(:id => params[:id]) if params[:id]
|
43
|
-
filter.merge!(:architecture => params[:architecture]) if params[:architecture]
|
44
|
-
filter.merge!(:owner_id => params[:owner_id]) if params[:owner_id]
|
45
|
-
filter.merge!(:state => params[:state]) if params[:state]
|
46
|
-
filter = nil if filter.keys.size.eql?(0)
|
47
|
-
singular = model.to_s.singularize.to_sym
|
48
|
-
@elements = driver.send(model.to_sym, credentials, filter)
|
49
|
-
instance_variable_set(:"@#{model}", @elements)
|
50
|
-
respond_to do |format|
|
51
|
-
format.html { haml :"#{model}/index" }
|
52
|
-
format.xml { haml :"#{model}/index" }
|
53
|
-
format.json { convert_to_json(singular, @elements) }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def show(model)
|
58
|
-
@element = driver.send(model, credentials, { :id => params[:id]} )
|
59
|
-
instance_variable_set("@#{model}", @element)
|
60
|
-
respond_to do |format|
|
61
|
-
format.html { haml :"#{model.to_s.pluralize}/show" }
|
62
|
-
format.xml { haml :"#{model.to_s.pluralize}/show" }
|
63
|
-
format.json { convert_to_json(model, @element) }
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
# Error handlers
|
70
|
-
#
|
71
|
-
def report_error(status, template)
|
72
|
-
@error = request.env['sinatra.error']
|
73
|
-
response.status = status
|
74
|
-
respond_to do |format|
|
75
|
-
format.xml { haml :"errors/#{template}", :layout => false }
|
76
|
-
format.html { haml :"errors/#{template}" }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
28
|
error Deltacloud::Validation::Failure do
|
81
29
|
report_error(400, "validation_failure")
|
82
30
|
end
|
@@ -93,7 +41,7 @@ end
|
|
93
41
|
get '/' do redirect '/api'; end
|
94
42
|
|
95
43
|
get '/api\/?' do
|
96
|
-
@version = 1
|
44
|
+
@version = 0.1
|
97
45
|
respond_to do |format|
|
98
46
|
format.xml { haml :"api/show" }
|
99
47
|
format.json do
|
@@ -111,10 +59,20 @@ end
|
|
111
59
|
# Rabbit DSL
|
112
60
|
|
113
61
|
collection :realms do
|
114
|
-
description
|
62
|
+
description <<END
|
63
|
+
Within a cloud provider a realm represents a boundary containing resources.
|
64
|
+
The exact definition of a realm is left to the cloud provider.
|
65
|
+
In some cases, a realm may represent different datacenters, different continents,
|
66
|
+
or different pools of resources within a single datacenter.
|
67
|
+
A cloud provider may insist that resources must all exist within a single realm in
|
68
|
+
order to cooperate. For instance, storage volumes may only be allowed to be mounted to
|
69
|
+
instances within the same realm.
|
70
|
+
END
|
115
71
|
|
116
72
|
operation :index do
|
117
|
-
description
|
73
|
+
description <<END
|
74
|
+
Operation will list all available realms. For specific architecture use "architecture" parameter.
|
75
|
+
END
|
118
76
|
param :id, :string
|
119
77
|
param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
|
120
78
|
control { filter_all(:realms) }
|
@@ -130,10 +88,17 @@ collection :realms do
|
|
130
88
|
end
|
131
89
|
|
132
90
|
collection :images do
|
133
|
-
description
|
91
|
+
description <<END
|
92
|
+
An image is a platonic form of a machine. Images are not directly executable,
|
93
|
+
but are a template for creating actual instances of machines."
|
94
|
+
END
|
134
95
|
|
135
96
|
operation :index do
|
136
|
-
description
|
97
|
+
description <<END
|
98
|
+
The instances collection will return a set of all images
|
99
|
+
available to the current use. You can filter images using
|
100
|
+
"owner_id" and "architecture" parameter
|
101
|
+
END
|
137
102
|
param :id, :string
|
138
103
|
param :owner_id, :string
|
139
104
|
param :architecture, :string, :optional
|
@@ -196,20 +161,11 @@ get "/api/instances/new" do
|
|
196
161
|
end
|
197
162
|
end
|
198
163
|
|
199
|
-
def instance_action(name)
|
200
|
-
@instance = driver.send(:"#{name}_instance", credentials, params["id"])
|
201
|
-
|
202
|
-
return redirect(instances_url) if name.eql?(:destroy) or @instance.class!=Instance
|
203
|
-
|
204
|
-
respond_to do |format|
|
205
|
-
format.html { haml :"instances/show" }
|
206
|
-
format.xml { haml :"instances/show" }
|
207
|
-
format.json {convert_to_json(:instance, @instance) }
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
164
|
collection :instances do
|
212
|
-
description
|
165
|
+
description <<END
|
166
|
+
An instance is a concrete machine realized from an image.
|
167
|
+
The images collection may be obtained by following the link from the primary entry-point."
|
168
|
+
END
|
213
169
|
|
214
170
|
operation :index do
|
215
171
|
description "List all instances"
|
@@ -299,10 +255,14 @@ END
|
|
299
255
|
param :id, :string, :required
|
300
256
|
control do
|
301
257
|
@profile = driver.hardware_profile(credentials, params[:id])
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
258
|
+
if @profile
|
259
|
+
respond_to do |format|
|
260
|
+
format.xml { haml :'hardware_profiles/show', :layout => false }
|
261
|
+
format.html { haml :'hardware_profiles/show' }
|
262
|
+
format.json { convert_to_json(:hardware_profile, @profile) }
|
263
|
+
end
|
264
|
+
else
|
265
|
+
report_error(404, 'not_found')
|
306
266
|
end
|
307
267
|
end
|
308
268
|
end
|
data/tests/api_test.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'tests/common'
|
2
|
+
|
3
|
+
module DeltacloudUnitTest
|
4
|
+
class ApiTest < Test::Unit::TestCase
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
def app
|
8
|
+
Sinatra::Application
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_it_returns_entry_points
|
12
|
+
do_xml_request '/api'
|
13
|
+
(last_xml_response/'/api/link').map.size.should > 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_it_has_correct_attributes_set
|
17
|
+
do_xml_request '/api'
|
18
|
+
(last_xml_response/'/api/link').each do |link|
|
19
|
+
link.attributes.keys.sort.should == [ 'href', 'rel' ]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_it_responses_to_html
|
24
|
+
do_request '/api', {}, false, { :format => :html }
|
25
|
+
last_response.status.should == 200
|
26
|
+
Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_it_responses_to_json
|
30
|
+
do_request '/api', {}, false, { :format => :json }
|
31
|
+
last_response.status.should == 200
|
32
|
+
JSON::parse(last_response.body).class.should == Hash
|
33
|
+
JSON::parse(last_response.body)['api'].class.should == Hash
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'tests/common'
|
2
|
+
|
3
|
+
module DeltacloudUnitTest
|
4
|
+
class HardwareProfilesTest < Test::Unit::TestCase
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
def app
|
8
|
+
Sinatra::Application
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_it_returns_hardware_profiles
|
12
|
+
do_xml_request '/api/hardware_profiles'
|
13
|
+
(last_xml_response/'hardware_profiles/hardware_profile').map.size.should > 0
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_it_has_correct_attributes_set
|
17
|
+
do_xml_request '/api/hardware_profiles'
|
18
|
+
(last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
|
19
|
+
profile.attributes.keys.sort.should == [ 'href', 'id' ]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_hardware_profiles_have_name
|
24
|
+
do_xml_request '/api/hardware_profiles'
|
25
|
+
(last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
|
26
|
+
(profile/'name').text.should_not == nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_hardware_profiles_have_unique_name
|
31
|
+
do_xml_request '/api/hardware_profiles'
|
32
|
+
names = []
|
33
|
+
(last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
|
34
|
+
names << (profile/'name').text
|
35
|
+
end
|
36
|
+
names.should == names.uniq
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_hardware_profiles_have_unique_id
|
40
|
+
do_xml_request '/api/hardware_profiles'
|
41
|
+
ids = []
|
42
|
+
(last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
|
43
|
+
ids << profile['id']
|
44
|
+
end
|
45
|
+
ids.should == ids.uniq
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_m1_xlarge_profile_has_correct_attributes
|
49
|
+
do_xml_request '/api/hardware_profiles'
|
50
|
+
profile = (last_xml_response/'hardware_profiles/hardware_profile[@id="m1-xlarge"]')
|
51
|
+
test_profile_properties(profile)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_it_returns_valid_hardware_profile
|
55
|
+
do_xml_request '/api/hardware_profiles/m1-xlarge'
|
56
|
+
profile = (last_xml_response/'hardware_profile')
|
57
|
+
test_profile_properties(profile)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_it_responses_to_json
|
61
|
+
do_request '/api/hardware_profiles', {}, false, { :format => :json }
|
62
|
+
JSON::parse(last_response.body).class.should == Hash
|
63
|
+
JSON::parse(last_response.body)['hardware_profiles'].class.should == Array
|
64
|
+
|
65
|
+
do_request '/api/hardware_profiles/m1-xlarge', {}, false, { :format => :json }
|
66
|
+
last_response.status.should == 200
|
67
|
+
JSON::parse(last_response.body).class.should == Hash
|
68
|
+
JSON::parse(last_response.body)['hardware_profile'].class.should == Hash
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_it_responses_to_html
|
72
|
+
do_request '/api/hardware_profiles', {}, false, { :format => :html }
|
73
|
+
last_response.status.should == 200
|
74
|
+
Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
|
75
|
+
|
76
|
+
do_request '/api/hardware_profiles/m1-xlarge', {}, false, { :format => :html }
|
77
|
+
last_response.status.should == 200
|
78
|
+
Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_it_returns_error_on_wrong_name
|
82
|
+
do_request '/api/hardware_profiles/m1-unknown-wrongname', {}, false, { :format => :html }
|
83
|
+
last_response.status.should == 404
|
84
|
+
do_xml_request '/api/hardware_profiles/m1-unknown-wrongname'
|
85
|
+
last_response.status.should == 404
|
86
|
+
do_request '/api/hardware_profiles/m1-unknown-wrongname', {}, false, { :format => :json }
|
87
|
+
last_response.status.should == 404
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def test_profile_properties(profile)
|
93
|
+
|
94
|
+
(profile/'property').each do |properties|
|
95
|
+
properties.attributes.keys.sort.should == [ 'kind', 'name', 'unit', 'value' ]
|
96
|
+
end
|
97
|
+
|
98
|
+
(profile/'property[@name="architecture"]').first['kind'].should == 'fixed'
|
99
|
+
(profile/'property[@name="architecture"]').first['unit'].should == 'label'
|
100
|
+
|
101
|
+
(profile/'property[@name="memory"]').first['kind'].should == 'range'
|
102
|
+
(profile/'property[@name="memory"]').first['unit'].should == 'MB'
|
103
|
+
(profile/'property[@name="memory"]/range').size.should == 1
|
104
|
+
(profile/'property[@name="memory"]/range').first.attributes.keys.sort.should == [ 'first', 'last' ]
|
105
|
+
|
106
|
+
(profile/'property[@name="cpu"]').first['kind'].should == 'fixed'
|
107
|
+
(profile/'property[@name="cpu"]').first['unit'].should == 'count'
|
108
|
+
|
109
|
+
(profile/'property[@name="storage"]').first['kind'].should == 'enum'
|
110
|
+
(profile/'property[@name="storage"]').first['unit'].should == 'GB'
|
111
|
+
(profile/'property[@name="storage"]/enum').size.should == 1
|
112
|
+
(profile/'property[@name="storage"]/enum/entry').map.size.should == 3
|
113
|
+
(profile/'property[@name="storage"]/enum/entry').each do |entry|
|
114
|
+
entry.attributes.keys.should == [ 'value' ]
|
115
|
+
entry['value'].should_not == nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
data/tests/images_test.rb
CHANGED
@@ -1,94 +1,111 @@
|
|
1
|
-
require 'tests/
|
1
|
+
require 'tests/common'
|
2
2
|
|
3
|
-
|
3
|
+
module DeltacloudUnitTest
|
4
|
+
class HardwareProfilesTest < Test::Unit::TestCase
|
5
|
+
include Rack::Test::Methods
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@params = {}
|
9
|
-
super(*args)
|
10
|
-
end
|
7
|
+
def app
|
8
|
+
Sinatra::Application
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
assert_not_equal 0, doc.xpath('/images/image').size
|
16
|
-
end
|
11
|
+
def test_it_require_authentication
|
12
|
+
require_authentication?('/api/images').should == true
|
13
|
+
end
|
17
14
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
get '/api/images.xml', @params, rack_headers
|
22
|
-
doc = Nokogiri::XML.parse(last_response.body)
|
23
|
-
elt = doc.xpath('/images/image[1]').first
|
24
|
-
assert_not_nil elt.xpath(option.to_s).first
|
15
|
+
def test_it_returns_images
|
16
|
+
do_xml_request '/api/images', {}, true
|
17
|
+
(last_xml_response/'images/image').map.size.should > 0
|
25
18
|
end
|
26
|
-
end
|
27
19
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
elt = doc.xpath('/image').first
|
34
|
-
assert_not_nil elt.xpath(option.to_s).first
|
20
|
+
def test_it_has_correct_attributes_set
|
21
|
+
do_xml_request '/api/images', {}, true
|
22
|
+
(last_xml_response/'images/image').each do |image|
|
23
|
+
image.attributes.keys.sort.should == [ 'href', 'id' ]
|
24
|
+
end
|
35
25
|
end
|
36
|
-
end
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
assert_equal @params[:id], doc.xpath('/images/image/id').first.text
|
44
|
-
end
|
27
|
+
def test_img1_has_correct_attributes
|
28
|
+
do_xml_request '/api/images', {}, true
|
29
|
+
image = (last_xml_response/'images/image[@id="img1"]')
|
30
|
+
test_image_attributes(image)
|
31
|
+
end
|
45
32
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
assert_equal @params[:owner_id], doc.xpath('/images/image/owner_id')[0].text
|
52
|
-
assert_equal @params[:owner_id], doc.xpath('/images/image/owner_id')[1].text
|
53
|
-
end
|
33
|
+
def test_it_returns_valid_image
|
34
|
+
do_xml_request '/api/images/img1', {}, true
|
35
|
+
image = (last_xml_response/'image')
|
36
|
+
test_image_attributes(image)
|
37
|
+
end
|
54
38
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
39
|
+
def test_it_has_unique_ids
|
40
|
+
do_xml_request '/api/images', {}, true
|
41
|
+
ids = []
|
42
|
+
(last_xml_response/'images/image').each do |image|
|
43
|
+
ids << image['id'].to_s
|
44
|
+
end
|
45
|
+
ids.sort.should == ids.sort.uniq
|
46
|
+
end
|
63
47
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
48
|
+
def test_it_has_valid_urls
|
49
|
+
do_xml_request '/api/images', {}, true
|
50
|
+
ids = []
|
51
|
+
images = (last_xml_response/'images/image')
|
52
|
+
images.each do |image|
|
53
|
+
do_xml_request image['href'].to_s, {}, true
|
54
|
+
(last_xml_response/'image').first['href'].should == image['href'].to_s
|
55
|
+
end
|
56
|
+
end
|
72
57
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
assert_equal @params[:owner_id], doc.xpath('/images/image/owner_id')[0].text
|
79
|
-
assert_equal @params[:id], doc.xpath('/images/image/id')[0].text
|
80
|
-
assert_equal @params[:architecture], doc.xpath('/images/image/architecture')[0].text
|
81
|
-
end
|
58
|
+
def test_it_can_filter_using_owner_id
|
59
|
+
do_xml_request '/api/images', { :owner_id => 'mockuser' }, true
|
60
|
+
(last_xml_response/'images/image').size.should == 1
|
61
|
+
(last_xml_response/'images/image/owner_id').first.text.should == 'mockuser'
|
62
|
+
end
|
82
63
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
64
|
+
def test_it_can_filter_using_unknown_owner_id
|
65
|
+
do_xml_request '/api/images', { :architecture => 'unknown_user' }, true
|
66
|
+
(last_xml_response/'images/image').size.should == 0
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_it_can_filter_using_architecture
|
70
|
+
do_xml_request '/api/images', { :architecture => 'x86_64' }, true
|
71
|
+
(last_xml_response/'images/image').size.should == 1
|
72
|
+
(last_xml_response/'images/image/architecture').first.text.should == 'x86_64'
|
73
|
+
end
|
91
74
|
|
92
|
-
|
75
|
+
def test_it_can_filter_using_unknown_architecture
|
76
|
+
do_xml_request '/api/images', { :architecture => 'unknown_arch' }, true
|
77
|
+
(last_xml_response/'images/image').size.should == 0
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_it_responses_to_json
|
81
|
+
do_request '/api/images', {}, true, { :format => :json }
|
82
|
+
JSON::parse(last_response.body).class.should == Hash
|
83
|
+
JSON::parse(last_response.body)['images'].class.should == Array
|
84
|
+
|
85
|
+
do_request '/api/images/img1', {}, true, { :format => :json }
|
86
|
+
last_response.status.should == 200
|
87
|
+
JSON::parse(last_response.body).class.should == Hash
|
88
|
+
JSON::parse(last_response.body)['image'].class.should == Hash
|
89
|
+
end
|
93
90
|
|
91
|
+
def test_it_responses_to_html
|
92
|
+
do_request '/api/images', {}, true, { :format => :html }
|
93
|
+
last_response.status.should == 200
|
94
|
+
Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
|
95
|
+
|
96
|
+
do_request '/api/images/img1', {}, true, { :format => :html }
|
97
|
+
last_response.status.should == 200
|
98
|
+
Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def test_image_attributes(image)
|
104
|
+
(image/'name').text.should_not nil
|
105
|
+
(image/'owner_id').text.should_not nil
|
106
|
+
(image/'description').text.should_not nil
|
107
|
+
(image/'architecture').text.should_not nil
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
94
111
|
end
|