deltacloud-core 0.1.2 → 0.3.0

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.
Files changed (158) hide show
  1. data/DISCLAIMER +8 -0
  2. data/{COPYING → LICENSE} +0 -0
  3. data/NOTICE +13 -0
  4. data/Rakefile +50 -51
  5. data/bin/deltacloudd +8 -1
  6. data/config.ru +0 -2
  7. data/config/drivers.yaml +48 -0
  8. data/deltacloud-core.gemspec +75 -0
  9. data/deltacloud.rb +3 -2
  10. data/lib/deltacloud/backend_capability.rb +15 -3
  11. data/lib/deltacloud/base_driver.rb +0 -2
  12. data/lib/deltacloud/base_driver/base_driver.rb +85 -89
  13. data/lib/deltacloud/base_driver/features.rb +61 -7
  14. data/lib/deltacloud/base_driver/mock_driver.rb +42 -43
  15. data/lib/deltacloud/core_ext.rb +18 -0
  16. data/lib/deltacloud/core_ext/integer.rb +31 -0
  17. data/lib/deltacloud/core_ext/string.rb +50 -0
  18. data/lib/deltacloud/drivers/azure/azure_driver.rb +71 -22
  19. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +641 -584
  20. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +0 -2
  21. data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +167 -0
  22. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +39 -1
  23. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +41 -25
  24. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob1.yml +6 -3
  25. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob2.yml +6 -3
  26. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob3.yml +4 -2
  27. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob4.yml +5 -2
  28. data/lib/deltacloud/drivers/mock/data/buckets/blobs/blob5.yml +4 -2
  29. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +1 -0
  30. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +1 -0
  31. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +1 -0
  32. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +1 -0
  33. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +1 -0
  34. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +1 -0
  35. data/lib/deltacloud/drivers/mock/mock_driver.rb +138 -30
  36. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +13 -15
  37. data/lib/deltacloud/drivers/opennebula/occi_client.rb +13 -15
  38. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +13 -15
  39. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +224 -113
  40. data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +332 -0
  41. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +221 -170
  42. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +0 -1
  43. data/lib/deltacloud/drivers/sbc/sbc_client.rb +247 -0
  44. data/lib/deltacloud/drivers/sbc/sbc_driver.rb +297 -0
  45. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +0 -2
  46. data/lib/deltacloud/hardware_profile.rb +1 -3
  47. data/lib/deltacloud/helpers.rb +0 -2
  48. data/lib/deltacloud/helpers/application_helper.rb +86 -12
  49. data/lib/deltacloud/helpers/blob_stream.rb +19 -2
  50. data/lib/deltacloud/helpers/conversion_helper.rb +0 -2
  51. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +0 -2
  52. data/lib/deltacloud/method_serializer.rb +0 -2
  53. data/lib/deltacloud/models/base_model.rb +0 -2
  54. data/lib/deltacloud/models/blob.rb +1 -2
  55. data/lib/deltacloud/models/bucket.rb +0 -2
  56. data/lib/deltacloud/models/image.rb +0 -2
  57. data/lib/deltacloud/models/instance.rb +19 -2
  58. data/lib/deltacloud/models/instance_profile.rb +4 -2
  59. data/lib/deltacloud/models/key.rb +0 -2
  60. data/lib/deltacloud/models/load_balancer.rb +0 -2
  61. data/lib/deltacloud/models/realm.rb +0 -2
  62. data/lib/deltacloud/models/storage_snapshot.rb +0 -2
  63. data/lib/deltacloud/models/storage_volume.rb +4 -2
  64. data/lib/deltacloud/runner.rb +132 -0
  65. data/lib/deltacloud/state_machine.rb +0 -2
  66. data/lib/deltacloud/validation.rb +9 -7
  67. data/lib/drivers.rb +36 -48
  68. data/lib/sinatra/accept_media_types.rb +26 -0
  69. data/lib/sinatra/lazy_auth.rb +16 -0
  70. data/lib/sinatra/rabbit.rb +112 -54
  71. data/lib/sinatra/rack_driver_select.rb +50 -16
  72. data/lib/sinatra/rack_etag.rb +79 -0
  73. data/lib/sinatra/rack_matrix_params.rb +84 -0
  74. data/lib/sinatra/rack_runtime.rb +47 -0
  75. data/lib/sinatra/static_assets.rb +16 -0
  76. data/lib/sinatra/url_for.rb +31 -4
  77. data/public/favicon.ico +0 -0
  78. data/public/images/bread-bg.png +0 -0
  79. data/public/images/error.png +0 -0
  80. data/public/images/pending.png +0 -0
  81. data/public/images/running.png +0 -0
  82. data/public/images/stopped.png +0 -0
  83. data/public/javascripts/application.js +35 -0
  84. data/public/stylesheets/compiled/application.css +59 -5
  85. data/public/stylesheets/compiled/screen.css +1 -1
  86. data/server.rb +293 -29
  87. data/support/fedora/deltacloud-core +78 -0
  88. data/support/fedora/deltacloud-core.spec +143 -0
  89. data/support/fedora/deltacloudd +78 -18
  90. data/support/fedora/rubygem-deltacloud-core.spec +76 -40
  91. data/tests/common.rb +172 -0
  92. data/tests/drivers/mock/api_test.rb +133 -0
  93. data/tests/drivers/mock/hardware_profiles_test.rb +134 -0
  94. data/tests/drivers/mock/images_test.rb +126 -0
  95. data/tests/drivers/mock/instance_states_test.rb +71 -0
  96. data/tests/drivers/mock/instances_test.rb +236 -0
  97. data/tests/drivers/mock/realms_test.rb +93 -0
  98. data/tests/drivers/mock/setup.rb +3 -0
  99. data/tests/drivers/mock/url_for_test.rb +67 -0
  100. data/tests/drivers/rackspace/api_test.rb +41 -0
  101. data/tests/drivers/rackspace/hardware_profiles_test.rb +53 -0
  102. data/tests/drivers/rackspace/images_test.rb +40 -0
  103. data/tests/drivers/rackspace/instances_test.rb +161 -0
  104. data/tests/drivers/rackspace/realms_test.rb +36 -0
  105. data/tests/drivers/rackspace/setup.rb +14 -0
  106. data/tests/drivers/rhevm/api_test.rb +39 -0
  107. data/tests/drivers/rhevm/hardware_profiles_test.rb +53 -0
  108. data/tests/drivers/rhevm/images_test.rb +42 -0
  109. data/tests/drivers/rhevm/instances_test.rb +179 -0
  110. data/tests/drivers/rhevm/realms_test.rb +35 -0
  111. data/tests/drivers/rhevm/setup.rb +14 -0
  112. data/tests/rabbit_test.rb +52 -0
  113. data/views/api/show.html.haml +2 -5
  114. data/views/blobs/new.html.haml +17 -1
  115. data/views/blobs/show.html.haml +6 -0
  116. data/views/blobs/show.xml.haml +5 -1
  117. data/views/buckets/index.html.haml +1 -12
  118. data/views/buckets/index.xml.haml +3 -5
  119. data/views/docs/operation.html.haml +23 -11
  120. data/views/drivers/index.html.haml +15 -0
  121. data/views/drivers/index.xml.haml +7 -0
  122. data/views/drivers/show.html.haml +20 -0
  123. data/views/drivers/show.xml.haml +7 -0
  124. data/views/error.html.haml +31 -0
  125. data/views/errors/auth_exception.xml.haml +2 -1
  126. data/views/errors/backend_capability_failure.xml.haml +2 -1
  127. data/views/errors/backend_error.html.haml +3 -0
  128. data/views/errors/backend_error.xml.haml +2 -2
  129. data/views/errors/validation_failure.xml.haml +3 -2
  130. data/views/images/index.html.haml +1 -6
  131. data/views/images/index.xml.haml +2 -0
  132. data/views/images/new.html.haml +14 -0
  133. data/views/images/show.xml.haml +2 -0
  134. data/views/instances/index.html.haml +8 -6
  135. data/views/instances/index.xml.haml +4 -0
  136. data/views/instances/new.html.haml +40 -11
  137. data/views/instances/run.html.haml +9 -0
  138. data/views/instances/run.xml.haml +7 -0
  139. data/views/instances/run_command.html.haml +16 -0
  140. data/views/instances/show.html.haml +14 -0
  141. data/views/instances/show.xml.haml +12 -4
  142. data/views/layout.html.haml +7 -2
  143. data/views/load_balancers/index.html.haml +1 -1
  144. data/views/load_balancers/new.html.haml +2 -2
  145. data/views/load_balancers/show.html.haml +1 -1
  146. data/views/storage_snapshots/index.html.haml +3 -0
  147. data/views/storage_snapshots/new.html.haml +9 -0
  148. data/views/storage_volumes/attach.html.haml +20 -0
  149. data/views/storage_volumes/index.html.haml +16 -1
  150. data/views/storage_volumes/index.xml.haml +1 -10
  151. data/views/storage_volumes/new.html.haml +17 -0
  152. data/views/storage_volumes/show.html.haml +8 -0
  153. data/views/storage_volumes/show.xml.haml +25 -3
  154. metadata +197 -127
  155. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +0 -130
  156. data/parse.rb +0 -7
  157. data/test.rb +0 -3
  158. data/views/api/drivers.xml.haml +0 -6
@@ -0,0 +1,172 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+ $:.unshift File.join(File.dirname(__FILE__), '..')
18
+
19
+ require 'rubygems'
20
+ require 'yaml'
21
+ require 'test/unit'
22
+ require 'spec'
23
+ require 'nokogiri'
24
+ require 'json'
25
+ require 'digest/sha1'
26
+ require 'base64'
27
+ require 'rack/test'
28
+ require 'server'
29
+
30
+ driver
31
+
32
+ # Set proper environment variables for running test
33
+
34
+ ENV['RACK_ENV'] = 'test'
35
+ ENV['API_HOST'] = 'localhost'
36
+ ENV['API_PORT'] = '4040'
37
+
38
+ configure :test do
39
+ set :environment, :test
40
+ set :raise_errors, false
41
+ set :show_exceptions, false
42
+ end
43
+
44
+ Spec::Runner.configure do |conf|
45
+ conf.include Rack::Test::Methods
46
+ end
47
+
48
+ module DeltacloudTestCommon
49
+
50
+ def recording?
51
+ @use_recording
52
+ end
53
+
54
+ def record!
55
+ @use_recording = true
56
+ end
57
+
58
+
59
+ # Authentication helper for Basic HTTP authentication
60
+ # To change default user credentials stored in ENV['API_USER|PASSWORD'] you
61
+ # need to set opts[:credentials] = { :user => '...', :password => '...'}
62
+ #
63
+ def authenticate(opts={})
64
+ credentials = opts[:credentials] || { :user => ENV['API_USER'], :password => ENV['API_PASSWORD']}
65
+ return {
66
+ 'HTTP_AUTHORIZATION' => "Basic " + Base64.encode64("#{credentials[:user]}:#{credentials[:password]}")
67
+ }
68
+ end
69
+
70
+ # HTTP Accept header helper.
71
+ # Will set appropriate value for this header.
72
+ # Available options for format are: :json, :html or :xml
73
+ # By default :xml is used
74
+ #
75
+ def accept(format=:xml)
76
+ case format
77
+ when :json then 'application/json;q=0.9'
78
+ when :html then 'text/html;q=0.9'
79
+ when :xml then 'application/xml;q=0.9'
80
+ else 'application/xml;q=0.9'
81
+ end
82
+ end
83
+
84
+ # This helper will execute GET operation on given URI.
85
+ # You can set additional parameters using params Hash, which will be passed to
86
+ # request.
87
+ # You can change format used for communication using opts[:format] = :xml | :html :json
88
+ # You can turn on recording (you need to configure it first in setup.rb) using
89
+ # opts[:record] (true/false)
90
+ # You can force authentication using opts[:auth] parameter or use
91
+ # 'get_auth_url' which will do it for you ;-)
92
+ #
93
+ def get_url(uri, params={}, opts={})
94
+ header 'Accept', accept(opts[:format] || :xml)
95
+ if DeltacloudTestCommon::recording?
96
+ VCR.use_cassette("get-" + Digest::SHA1.hexdigest("#{uri}-#{params}}")) do
97
+ get(uri, params || {}, opts[:auth] ? authenticate(opts) : {})
98
+ end
99
+ else
100
+ get(uri, params || {}, opts[:auth] ? authenticate(opts) : {})
101
+ end
102
+ last_response.status.should_not == 401
103
+ end
104
+
105
+ def get_auth_url(uri, params={}, opts={})
106
+ opts.merge!(:auth => true)
107
+ get_url(uri, params, opts)
108
+ end
109
+
110
+ def post_url(uri, params={}, opts={})
111
+ header 'Accept', accept(opts[:format] || :xml)
112
+ if DeltacloudTestCommon::recording?
113
+ VCR.use_cassette("post-" + Digest::SHA1.hexdigest("#{uri}-#{params}")) do
114
+ post(uri, params || {}, authenticate(opts))
115
+ end
116
+ else
117
+ post(uri, params || {}, authenticate(opts))
118
+ end
119
+ end
120
+
121
+ def delete_url(uri, params={}, opts={})
122
+ header 'Accept', accept(opts[:format] || :xml)
123
+ if DeltacloudTestCommon::recording?
124
+ VCR.use_cassette("delete-"+Digest::SHA1.hexdigest("#{uri}-#{params}")) do
125
+ delete(uri, params || {}, authenticate(opts))
126
+ end
127
+ else
128
+ delete(uri, params || {}, authenticate(opts))
129
+ end
130
+ end
131
+
132
+ def put_url(uri, params={}, opts={})
133
+ header 'Accept', accept(opts[:format] || :xml)
134
+ if DeltacloudTestCommon::recording?
135
+ VCR.use_cassette("put-"+Digest::SHA1.hexdigest("#{uri}-#{params}-#{authenticate(opts)}")) do
136
+ put(uri, params || {}, authenticate(opts))
137
+ end
138
+ else
139
+ put(uri, params || {}, authenticate(opts))
140
+ end
141
+ end
142
+
143
+ # This helper will automatically convert output from method above to Nokogiri
144
+ # XML object
145
+ def last_xml_response
146
+ Nokogiri::XML(last_response.body) #if last_response.status.to_s =~ /2(\d+)/
147
+ end
148
+
149
+ # Check if given URI require authentication
150
+ def require_authentication?(uri)
151
+ get uri, {}
152
+ true if last_response.status == 401
153
+ end
154
+
155
+ def with_provider(new_provider, &block)
156
+ old_provider = ENV["API_PROVIDER"]
157
+ begin
158
+ ENV["API_PROVIDER"] = new_provider
159
+ yield
160
+ ensure
161
+ ENV["API_PROVIDER"] = old_provider
162
+ end
163
+ end
164
+
165
+ def add_created_instance(id)
166
+ $created_instances ||= []
167
+ $created_instances << id
168
+ end
169
+
170
+ end
171
+
172
+ include DeltacloudTestCommon
@@ -0,0 +1,133 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..')
18
+ require 'tests/common'
19
+
20
+ module DeltacloudUnitTest
21
+ class ApiTest < Test::Unit::TestCase
22
+ include Rack::Test::Methods
23
+
24
+ def app
25
+ Sinatra::Application
26
+ end
27
+
28
+ def test_it_returns_entry_points
29
+ get_auth_url '/api'
30
+ (last_xml_response/'/api/link').length.should > 0
31
+ end
32
+
33
+ def test_it_has_correct_attributes_set
34
+ get_auth_url '/api'
35
+ (last_xml_response/'/api/link').each do |link|
36
+ link.attributes.keys.sort.should == [ 'href', 'rel' ]
37
+ end
38
+ end
39
+
40
+ def test_it_responses_to_html
41
+ get_url '/api', {}, { :format => :html }
42
+ last_response.status.should == 200
43
+ Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
44
+ end
45
+
46
+ def test_it_responses_to_json
47
+ get_url '/api', {}, { :format => :json }
48
+ last_response.status.should == 200
49
+ JSON::parse(last_response.body).class.should == Hash
50
+ JSON::parse(last_response.body)['api'].class.should == Hash
51
+ end
52
+
53
+ def test_it_switches_drivers
54
+ with_provider("") do
55
+ get_auth_url '/api'
56
+ (last_xml_response/"api/link[rel = 'instances']").first.should_not == nil
57
+ end
58
+
59
+ # Switch to storage-only mock driver
60
+ with_provider("storage") do
61
+ get_auth_url '/api'
62
+ (last_xml_response/"api/link[rel = 'instances']").first.should == nil
63
+ end
64
+ end
65
+
66
+ def test_it_handles_unsupported_collections
67
+ get_auth_url '/api/no_such_collection'
68
+ last_response.status.should == 404
69
+
70
+ with_provider("storage") do
71
+ get_auth_url '/api/instances'
72
+ last_response.status.should == 404
73
+ end
74
+ end
75
+
76
+ def test_it_allows_accessing_docs
77
+ get_url '/api/docs/instances'
78
+ last_response.status.should == 200
79
+
80
+ with_provider("storage") do
81
+ get_url '/api/docs/instances'
82
+ last_response.status.should == 404
83
+ end
84
+ end
85
+
86
+ def test_it_respond_to_head
87
+ head '/api/instances'
88
+ last_response.headers['Allow'].should_not == nil
89
+ last_response.headers['Allow'].split(',').include?('HEAD').should == true
90
+ end
91
+
92
+ def test_it_expose_available_drivers
93
+ get_auth_url '/api/drivers'
94
+ last_response.status.should == 200
95
+ (last_xml_response/"drivers").length.should > 0
96
+ (last_xml_response/'drivers/driver').length.should > 0
97
+ (last_xml_response/"drivers/driver[@id = 'mock']").length.should == 1
98
+ end
99
+
100
+ def test_it_expose_ec2_driver_entrypoints
101
+ get_auth_url '/api/drivers'
102
+ last_response.status.should == 200
103
+ ec2 = (last_xml_response/'drivers/driver[@id=ec2]').first
104
+ (ec2/"provider").length.should > 0
105
+ (ec2/"provider[@id = 'eu-west-1']").length.should == 1
106
+ get_auth_url ec2[:href]
107
+ eu_west = (last_xml_response/"provider[@id = 'eu-west-1']").first
108
+ (eu_west/"entrypoint").length.should > 0
109
+ (eu_west/"entrypoint[@kind = 'ec2']").length.should == 1
110
+ end
111
+
112
+ def test_it_supports_matrix_params
113
+ get_auth_url "/api;driver=ec2"
114
+ last_response.status.should == 200
115
+ (last_xml_response/'api').first[:driver].should == 'ec2'
116
+ get_auth_url "/api;driver=mock"
117
+ (last_xml_response/'api').first[:driver].should == 'mock'
118
+ get_auth_url "/api;driver=ec2/hardware_profiles"
119
+ (last_xml_response/'hardware_profiles/hardware_profile/@id').map {|n| n.to_s}.include?('m1.small').should == true
120
+ last_response.status.should == 200
121
+ end
122
+
123
+ def test_it_change_features_after_driver_change
124
+ get_auth_url "/api;driver=ec2"
125
+ (last_xml_response/'api/link[@rel="instances"]/feature[@name="user_name"]').first.should == nil
126
+ (last_xml_response/'api/link[@rel="instances"]/feature[@name="user_data"]').first.should_not == nil
127
+ get_auth_url "/api;driver=mock"
128
+ (last_xml_response/'api/link[@rel="instances"]/feature[@name="user_name"]').first.should_not == nil
129
+ (last_xml_response/'api/link[@rel="instances"]/feature[@name="user_data"]').first.should == nil
130
+ end
131
+
132
+ end
133
+ end
@@ -0,0 +1,134 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..')
18
+ require 'tests/common'
19
+
20
+ module DeltacloudUnitTest
21
+ class HardwareProfilesTest < Test::Unit::TestCase
22
+ include Rack::Test::Methods
23
+
24
+ def app
25
+ Sinatra::Application
26
+ end
27
+
28
+ def test_it_returns_hardware_profiles
29
+ get_url '/api/hardware_profiles'
30
+ (last_xml_response/'hardware_profiles/hardware_profile').length.should > 0
31
+ end
32
+
33
+ def test_it_has_correct_attributes_set
34
+ get_auth_url '/api/hardware_profiles'
35
+ (last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
36
+ profile.attributes.keys.sort.should == [ 'href', 'id' ]
37
+ end
38
+ end
39
+
40
+ def test_hardware_profiles_have_name
41
+ get_auth_url '/api/hardware_profiles'
42
+ (last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
43
+ (profile/'name').text.should_not == nil
44
+ end
45
+ end
46
+
47
+ def test_hardware_profiles_have_unique_name
48
+ get_auth_url '/api/hardware_profiles'
49
+ names = []
50
+ (last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
51
+ names << (profile/'name').text
52
+ end
53
+ names.should == names.uniq
54
+ end
55
+
56
+ def test_hardware_profiles_have_unique_id
57
+ get_auth_url '/api/hardware_profiles'
58
+ ids = []
59
+ (last_xml_response/'hardware_profiles/hardware_profile').each do |profile|
60
+ ids << profile['id']
61
+ end
62
+ ids.should == ids.uniq
63
+ end
64
+
65
+ def test_m1_xlarge_profile_has_correct_attributes
66
+ get_auth_url '/api/hardware_profiles'
67
+ profile = (last_xml_response/'hardware_profiles/hardware_profile[@id="m1-xlarge"]')
68
+ test_profile_properties(profile)
69
+ end
70
+
71
+ def test_it_returns_valid_hardware_profile
72
+ get_auth_url '/api/hardware_profiles/m1-xlarge'
73
+ profile = (last_xml_response/'hardware_profile')
74
+ test_profile_properties(profile)
75
+ end
76
+
77
+ def test_it_responses_to_json
78
+ get_url '/api/hardware_profiles', {}, { :format => :json }
79
+ JSON::parse(last_response.body).class.should == Hash
80
+ JSON::parse(last_response.body)['hardware_profiles'].class.should == Array
81
+ get_url '/api/hardware_profiles/m1-xlarge', {}, { :format => :json }
82
+ last_response.status.should == 200
83
+ JSON::parse(last_response.body).class.should == Hash
84
+ JSON::parse(last_response.body)['hardware_profile'].class.should == Hash
85
+ end
86
+
87
+ def test_it_responses_to_html
88
+ get_url '/api/hardware_profiles', {}, { :format => :html }
89
+ last_response.status.should == 200
90
+ Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
91
+ get_url '/api/hardware_profiles/m1-xlarge', {}, { :format => :html }
92
+ last_response.status.should == 200
93
+ Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
94
+ end
95
+
96
+ def test_it_returns_error_on_wrong_name
97
+ get_url '/api/hardware_profiles/m1-unknown-wrongname', {}, { :format => :html }
98
+ last_response.status.should == 404
99
+ get_auth_url '/api/hardware_profiles/m1-unknown-wrongname'
100
+ last_response.status.should == 404
101
+ get_url '/api/hardware_profiles/m1-unknown-wrongname', {}, { :format => :json }
102
+ last_response.status.should == 404
103
+ end
104
+
105
+ private
106
+
107
+ def test_profile_properties(profile)
108
+ (profile/'property').each do |properties|
109
+ properties.attributes.keys.sort.should == [ 'kind', 'name', 'unit', 'value' ]
110
+ end
111
+
112
+ (profile/'property[@name="architecture"]').first['kind'].should == 'fixed'
113
+ (profile/'property[@name="architecture"]').first['unit'].should == 'label'
114
+
115
+ (profile/'property[@name="memory"]').first['kind'].should == 'range'
116
+ (profile/'property[@name="memory"]').first['unit'].should == 'MB'
117
+ (profile/'property[@name="memory"]/range').length.should == 1
118
+ (profile/'property[@name="memory"]/range').first.attributes.keys.sort.should == [ 'first', 'last' ]
119
+
120
+ (profile/'property[@name="cpu"]').first['kind'].should == 'fixed'
121
+ (profile/'property[@name="cpu"]').first['unit'].should == 'count'
122
+
123
+ (profile/'property[@name="storage"]').first['kind'].should == 'enum'
124
+ (profile/'property[@name="storage"]').first['unit'].should == 'GB'
125
+ (profile/'property[@name="storage"]/enum').length.should == 1
126
+ (profile/'property[@name="storage"]/enum/entry').length.should == 3
127
+ (profile/'property[@name="storage"]/enum/entry').each do |entry|
128
+ entry.attributes.keys.should == [ 'value' ]
129
+ entry['value'].should_not == nil
130
+ end
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,126 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one or more
2
+ # contributor license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright ownership. The
4
+ # ASF licenses this file to you under the Apache License, Version 2.0 (the
5
+ # "License"); you may not use this file except in compliance with the
6
+ # License. You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
+ # License for the specific language governing permissions and limitations
14
+ # under the License.
15
+ #
16
+
17
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', '..')
18
+ require 'tests/common'
19
+
20
+ module DeltacloudUnitTest
21
+ class HardwareProfilesTest < Test::Unit::TestCase
22
+ include Rack::Test::Methods
23
+
24
+ def app
25
+ Sinatra::Application
26
+ end
27
+
28
+ def test_it_require_authentication
29
+ require_authentication?('/api/images').should == true
30
+ end
31
+
32
+ def test_it_returns_images
33
+ get_auth_url '/api/images', {}
34
+ (last_xml_response/'images/image').length.should > 0
35
+ end
36
+
37
+ def test_it_has_correct_attributes_set
38
+ get_auth_url '/api/images', {}
39
+ (last_xml_response/'images/image').each do |image|
40
+ image.attributes.keys.sort.should == [ 'href', 'id' ]
41
+ end
42
+ end
43
+
44
+ def test_img1_has_correct_attributes
45
+ get_auth_url '/api/images', {}
46
+ image = (last_xml_response/'images/image[@id="img1"]')
47
+ test_image_attributes(image)
48
+ end
49
+
50
+ def test_it_returns_valid_image
51
+ get_auth_url '/api/images/img1', {}
52
+ image = (last_xml_response/'image')
53
+ test_image_attributes(image)
54
+ end
55
+
56
+ def test_it_has_unique_ids
57
+ get_auth_url '/api/images', {}
58
+ ids = []
59
+ (last_xml_response/'images/image').each do |image|
60
+ ids << image['id'].to_s
61
+ end
62
+ ids.sort.should == ids.sort.uniq
63
+ end
64
+
65
+ def test_it_has_valid_urls
66
+ get_auth_url '/api/images', {}
67
+ ids = []
68
+ images = (last_xml_response/'images/image')
69
+ images.each do |image|
70
+ get_auth_url image['href'].to_s, {}
71
+ (last_xml_response/'image').first['href'].should == image['href'].to_s
72
+ end
73
+ end
74
+
75
+ def test_it_can_filter_using_owner_id
76
+ get_auth_url '/api/images', { :owner_id => 'mockuser' }
77
+ (last_xml_response/'images/image').length.should == 1
78
+ (last_xml_response/'images/image/owner_id').first.text.should == 'mockuser'
79
+ end
80
+
81
+ def test_it_can_filter_using_unknown_owner_id
82
+ get_auth_url '/api/images', { :architecture => 'unknown_user' }
83
+ (last_xml_response/'images/image').length.should == 0
84
+ end
85
+
86
+ def test_it_can_filter_using_architecture
87
+ get_auth_url '/api/images', { :architecture => 'x86_64' }
88
+ (last_xml_response/'images/image').length.should == 1
89
+ (last_xml_response/'images/image/architecture').first.text.should == 'x86_64'
90
+ end
91
+
92
+ def test_it_can_filter_using_unknown_architecture
93
+ get_auth_url '/api/images', { :architecture => 'unknown_arch' }
94
+ (last_xml_response/'images/image').length.should == 0
95
+ end
96
+
97
+ def test_it_responses_to_json
98
+ get_auth_url '/api/images', {}, { :format => :json }
99
+ JSON::parse(last_response.body).class.should == Hash
100
+ JSON::parse(last_response.body)['images'].class.should == Array
101
+ get_auth_url '/api/images/img1', {}, { :format => :json }
102
+ last_response.status.should == 200
103
+ JSON::parse(last_response.body).class.should == Hash
104
+ JSON::parse(last_response.body)['image'].class.should == Hash
105
+ end
106
+
107
+ def test_it_responses_to_html
108
+ get_auth_url '/api/images', {}, { :format => :html }
109
+ last_response.status.should == 200
110
+ Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
111
+ get_auth_url '/api/images/img1', {}, { :format => :html }
112
+ last_response.status.should == 200
113
+ Nokogiri::HTML(last_response.body).search('html').first.name.should == 'html'
114
+ end
115
+
116
+ private
117
+
118
+ def test_image_attributes(image)
119
+ (image/'name').text.should_not nil
120
+ (image/'owner_id').text.should_not nil
121
+ (image/'description').text.should_not nil
122
+ (image/'architecture').text.should_not nil
123
+ end
124
+
125
+ end
126
+ end