deltacloud-core 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/COPYING +176 -502
  2. data/Rakefile +21 -14
  3. data/deltacloud.rb +3 -0
  4. data/lib/deltacloud/base_driver.rb +12 -11
  5. data/lib/deltacloud/base_driver/base_driver.rb +22 -11
  6. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +15 -12
  7. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +16 -11
  8. data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
  9. data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
  10. data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
  11. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
  12. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
  13. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
  14. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
  15. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
  16. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
  17. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
  18. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
  19. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
  20. data/lib/deltacloud/drivers/mock/mock_driver.rb +13 -11
  21. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +12 -11
  22. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +12 -11
  23. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +12 -11
  24. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +12 -11
  25. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +14 -12
  26. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +12 -11
  27. data/lib/deltacloud/helpers/application_helper.rb +64 -11
  28. data/lib/deltacloud/helpers/conversion_helper.rb +12 -11
  29. data/lib/deltacloud/method_serializer.rb +12 -11
  30. data/lib/deltacloud/models/base_model.rb +12 -11
  31. data/lib/deltacloud/models/image.rb +12 -11
  32. data/lib/deltacloud/models/instance.rb +13 -12
  33. data/lib/deltacloud/models/instance_profile.rb +12 -11
  34. data/lib/deltacloud/models/realm.rb +12 -11
  35. data/lib/deltacloud/models/storage_snapshot.rb +12 -11
  36. data/lib/deltacloud/models/storage_volume.rb +12 -11
  37. data/lib/drivers.rb +12 -0
  38. data/lib/sinatra/rabbit.rb +1 -0
  39. data/lib/sinatra/respond_to.rb +3 -0
  40. data/server.rb +40 -80
  41. data/tests/api_test.rb +37 -0
  42. data/tests/hardware_profiles_test.rb +120 -0
  43. data/tests/images_test.rb +95 -78
  44. data/tests/instance_states_test.rb +52 -0
  45. data/tests/instances_test.rb +193 -110
  46. data/tests/realms_test.rb +66 -44
  47. data/views/errors/not_found.html.haml +6 -0
  48. data/views/errors/not_found.xml.haml +2 -0
  49. data/views/hardware_profiles/index.xml.haml +1 -1
  50. data/views/hardware_profiles/show.xml.haml +3 -2
  51. data/views/images/index.xml.haml +4 -3
  52. data/views/images/show.xml.haml +2 -2
  53. data/views/instances/index.xml.haml +6 -8
  54. data/views/instances/show.xml.haml +9 -10
  55. data/views/realms/index.xml.haml +1 -3
  56. data/views/realms/show.xml.haml +4 -5
  57. data/views/storage_snapshots/index.xml.haml +3 -5
  58. data/views/storage_snapshots/show.xml.haml +2 -4
  59. data/views/storage_volumes/index.xml.haml +7 -7
  60. data/views/storage_volumes/show.xml.haml +2 -4
  61. metadata +156 -81
  62. data/tests/deltacloud_test.rb +0 -60
  63. data/tests/storage_snapshots_test.rb +0 -48
  64. 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
- # This library is free software; you can redistribute it and/or
5
- # modify it under the terms of the GNU Lesser General Public
6
- # License as published by the Free Software Foundation; either
7
- # version 2.1 of the License, or (at your option) any later version.
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
- # This library is distributed in the hope that it will be useful,
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
- # You should have received a copy of the GNU Lesser General Public
15
- # License along with this library; if not, write to the Free Software
16
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
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
@@ -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
@@ -267,3 +267,6 @@ module Sinatra
267
267
  end
268
268
  end
269
269
  end
270
+
271
+ Rack::Mime::MIME_TYPES.merge!({ ".gv" => "text/plain" })
272
+ Sinatra::Application.register Sinatra::RespondTo
data/server.rb CHANGED
@@ -1,21 +1,18 @@
1
- require 'rubygems'
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 'deltacloud/validation'
15
- require 'deltacloud/helpers'
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.0
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 "Within a cloud provider a realm represents a boundary containing resources. The exact definition of a realm is left to the cloud provider. In some cases, a realm may represent different datacenters, different continents, or different pools of resources within a single datacenter. A cloud provider may insist that resources must all exist within a single realm in order to cooperate. For instance, storage volumes may only be allowed to be mounted to instances within the same realm."
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 'Operation will list all available realms. For specific architecture use "architecture" parameter.'
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 "An image is a platonic form of a machine. Images are not directly executable, but are a template for creating actual instances of machines."
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 'The instances collection will return a set of all images available to the current use. You can filter images using "owner_id" and "architecture" parameter'
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 "An instance is a concrete machine realized from an image. The images collection may be obtained by following the link from the primary entry-point."
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
- respond_to do |format|
303
- format.xml { haml :'hardware_profiles/show', :layout => false }
304
- format.html { haml :'hardware_profiles/show' }
305
- format.json { convert_to_json(:hardware_profile, @profile) }
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/deltacloud_test'
1
+ require 'tests/common'
2
2
 
3
- class ImagesTest < Test::Unit::TestCase
3
+ module DeltacloudUnitTest
4
+ class HardwareProfilesTest < Test::Unit::TestCase
5
+ include Rack::Test::Methods
4
6
 
5
- def initialize(*args)
6
- @collection = 'images'
7
- @operations = [:index, :show]
8
- @params = {}
9
- super(*args)
10
- end
7
+ def app
8
+ Sinatra::Application
9
+ end
11
10
 
12
- def test_if_images_are_not_empty
13
- get '/api/images.xml', @params, rack_headers
14
- doc = Nokogiri::XML.parse(last_response.body)
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
- [:id, :owner_id, :name, :description, :architecture].each do |option|
19
- method_name = :"test_if_images_index_contain_#{option}"
20
- send :define_method, method_name do
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
- [:id, :owner_id, :name, :description, :architecture].each do |option|
29
- method_name = :"test_if_image_show_contain_#{option}"
30
- send :define_method, method_name do
31
- get '/api/images/img1.xml', @params, rack_headers
32
- doc = Nokogiri::XML.parse(last_response.body)
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
- def test_images_filtering_by_id
39
- @params={ :id => 'img1' }
40
- get '/api/images.xml', @params, rack_headers
41
- doc = Nokogiri::XML.parse(last_response.body)
42
- assert_equal 1, doc.xpath('/images/image').size
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
- def test_images_filtering_by_owner_id
47
- @params={ :owner_id => 'fedoraproject' }
48
- get '/api/images.xml', @params, rack_headers
49
- doc = Nokogiri::XML.parse(last_response.body)
50
- assert_equal 2, doc.xpath('/images/image').size
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
- def test_images_filtering_by_architecture
56
- @params={ :architecture => 'i386' }
57
- get '/api/images.xml', @params, rack_headers
58
- doc = Nokogiri::XML.parse(last_response.body)
59
- assert_equal 2, doc.xpath('/images/image').size
60
- assert_equal @params[:architecture], doc.xpath('/images/image/architecture')[0].text
61
- assert_equal @params[:architecture], doc.xpath('/images/image/architecture')[1].text
62
- end
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
- def test_images_filtering_by_id_and_owner_id
65
- @params={ :id => 'img1', :owner_id => 'fedoraproject' }
66
- get '/api/images.xml', @params, rack_headers
67
- doc = Nokogiri::XML.parse(last_response.body)
68
- assert_equal 1, doc.xpath('/images/image').size
69
- assert_equal @params[:owner_id], doc.xpath('/images/image/owner_id')[0].text
70
- assert_equal @params[:id], doc.xpath('/images/image/id')[0].text
71
- end
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
- def test_images_filtering_by_id_and_owner_id_and_architecture
74
- @params={ :id => 'img1', :owner_id => 'fedoraproject', :architecture => 'x86_64' }
75
- get '/api/images.xml', @params, rack_headers
76
- doc = Nokogiri::XML.parse(last_response.body)
77
- assert_equal 1, doc.xpath('/images/image').size
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
- def test_images_filtering_by_id_and_architecture
84
- @params={ :id => 'img1', :architecture => 'x86_64' }
85
- get '/api/images.xml', @params, rack_headers
86
- doc = Nokogiri::XML.parse(last_response.body)
87
- assert_equal 1, doc.xpath('/images/image').size
88
- assert_equal @params[:id], doc.xpath('/images/image/id')[0].text
89
- assert_equal @params[:architecture], doc.xpath('/images/image/architecture')[0].text
90
- end
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
- include DeltacloudTest
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