deltacloud-core 0.1.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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