bbrowning-deltacloud-core 0.0.4-java

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 (134) hide show
  1. data/COPYING +176 -0
  2. data/Rakefile +99 -0
  3. data/bin/deltacloudd +120 -0
  4. data/config.ru +5 -0
  5. data/deltacloud.rb +18 -0
  6. data/lib/deltacloud/base_driver/base_driver.rb +229 -0
  7. data/lib/deltacloud/base_driver/features.rb +166 -0
  8. data/lib/deltacloud/base_driver/mock_driver.rb +40 -0
  9. data/lib/deltacloud/base_driver.rb +20 -0
  10. data/lib/deltacloud/drivers/ec2/ec2_driver.rb +410 -0
  11. data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +170 -0
  12. data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +50 -0
  13. data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +332 -0
  14. data/lib/deltacloud/drivers/gogrid/test.rb +13 -0
  15. data/lib/deltacloud/drivers/mock/data/images/img1.yml +3 -0
  16. data/lib/deltacloud/drivers/mock/data/images/img2.yml +3 -0
  17. data/lib/deltacloud/drivers/mock/data/images/img3.yml +3 -0
  18. data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +16 -0
  19. data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +9 -0
  20. data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +9 -0
  21. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +4 -0
  22. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +4 -0
  23. data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +4 -0
  24. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +6 -0
  25. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +6 -0
  26. data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +6 -0
  27. data/lib/deltacloud/drivers/mock/mock_driver.rb +277 -0
  28. data/lib/deltacloud/drivers/opennebula/cloud_client.rb +116 -0
  29. data/lib/deltacloud/drivers/opennebula/occi_client.rb +204 -0
  30. data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +241 -0
  31. data/lib/deltacloud/drivers/rackspace/rackspace_client.rb +130 -0
  32. data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +182 -0
  33. data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +255 -0
  34. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +85 -0
  35. data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +166 -0
  36. data/lib/deltacloud/drivers/terremark/terremark_driver.rb +286 -0
  37. data/lib/deltacloud/hardware_profile.rb +153 -0
  38. data/lib/deltacloud/helpers/application_helper.rb +115 -0
  39. data/lib/deltacloud/helpers/conversion_helper.rb +39 -0
  40. data/lib/deltacloud/helpers/hardware_profiles_helper.rb +35 -0
  41. data/lib/deltacloud/helpers.rb +5 -0
  42. data/lib/deltacloud/method_serializer.rb +85 -0
  43. data/lib/deltacloud/models/base_model.rb +59 -0
  44. data/lib/deltacloud/models/image.rb +27 -0
  45. data/lib/deltacloud/models/instance.rb +38 -0
  46. data/lib/deltacloud/models/instance_profile.rb +48 -0
  47. data/lib/deltacloud/models/key.rb +35 -0
  48. data/lib/deltacloud/models/realm.rb +26 -0
  49. data/lib/deltacloud/models/storage_snapshot.rb +27 -0
  50. data/lib/deltacloud/models/storage_volume.rb +28 -0
  51. data/lib/deltacloud/state_machine.rb +84 -0
  52. data/lib/deltacloud/validation.rb +70 -0
  53. data/lib/drivers.rb +50 -0
  54. data/lib/sinatra/accept_media_types.rb +128 -0
  55. data/lib/sinatra/lazy_auth.rb +56 -0
  56. data/lib/sinatra/rabbit.rb +273 -0
  57. data/lib/sinatra/respond_to.rb +272 -0
  58. data/lib/sinatra/static_assets.rb +83 -0
  59. data/lib/sinatra/url_for.rb +53 -0
  60. data/public/favicon.ico +0 -0
  61. data/public/images/grid.png +0 -0
  62. data/public/images/logo-wide.png +0 -0
  63. data/public/images/rails.png +0 -0
  64. data/public/images/topbar-bg.png +0 -0
  65. data/public/javascripts/application.js +32 -0
  66. data/public/javascripts/jquery-1.4.2.min.js +154 -0
  67. data/public/stylesheets/compiled/application.css +613 -0
  68. data/public/stylesheets/compiled/ie.css +31 -0
  69. data/public/stylesheets/compiled/print.css +27 -0
  70. data/public/stylesheets/compiled/screen.css +456 -0
  71. data/server.rb +354 -0
  72. data/support/fedora/deltacloudd +68 -0
  73. data/support/fedora/rubygem-deltacloud-core.spec +91 -0
  74. data/tests/api_test.rb +37 -0
  75. data/tests/hardware_profiles_test.rb +120 -0
  76. data/tests/images_test.rb +111 -0
  77. data/tests/instance_states_test.rb +52 -0
  78. data/tests/instances_test.rb +219 -0
  79. data/tests/realms_test.rb +78 -0
  80. data/tests/url_for_test.rb +50 -0
  81. data/views/accounts/index.html.haml +11 -0
  82. data/views/accounts/show.html.haml +30 -0
  83. data/views/api/show.html.haml +15 -0
  84. data/views/api/show.xml.haml +5 -0
  85. data/views/docs/collection.html.haml +37 -0
  86. data/views/docs/collection.xml.haml +14 -0
  87. data/views/docs/index.html.haml +15 -0
  88. data/views/docs/index.xml.haml +5 -0
  89. data/views/docs/operation.html.haml +31 -0
  90. data/views/docs/operation.xml.haml +10 -0
  91. data/views/errors/auth_exception.html.haml +8 -0
  92. data/views/errors/auth_exception.xml.haml +2 -0
  93. data/views/errors/backend_error.html.haml +19 -0
  94. data/views/errors/backend_error.xml.haml +8 -0
  95. data/views/errors/not_found.html.haml +6 -0
  96. data/views/errors/not_found.xml.haml +2 -0
  97. data/views/errors/validation_failure.html.haml +11 -0
  98. data/views/errors/validation_failure.xml.haml +7 -0
  99. data/views/hardware_profiles/index.html.haml +25 -0
  100. data/views/hardware_profiles/index.xml.haml +4 -0
  101. data/views/hardware_profiles/show.html.haml +19 -0
  102. data/views/hardware_profiles/show.xml.haml +18 -0
  103. data/views/images/index.html.haml +30 -0
  104. data/views/images/index.xml.haml +8 -0
  105. data/views/images/show.html.haml +21 -0
  106. data/views/images/show.xml.haml +5 -0
  107. data/views/instance_states/show.gv.erb +45 -0
  108. data/views/instance_states/show.html.haml +31 -0
  109. data/views/instance_states/show.xml.haml +8 -0
  110. data/views/instances/index.html.haml +30 -0
  111. data/views/instances/index.xml.haml +21 -0
  112. data/views/instances/new.html.haml +55 -0
  113. data/views/instances/show.html.haml +43 -0
  114. data/views/instances/show.xml.haml +49 -0
  115. data/views/keys/index.html.haml +26 -0
  116. data/views/keys/index.xml.haml +4 -0
  117. data/views/keys/new.html.haml +8 -0
  118. data/views/keys/show.html.haml +22 -0
  119. data/views/keys/show.xml.haml +20 -0
  120. data/views/layout.html.haml +26 -0
  121. data/views/realms/index.html.haml +29 -0
  122. data/views/realms/index.xml.haml +10 -0
  123. data/views/realms/show.html.haml +15 -0
  124. data/views/realms/show.xml.haml +9 -0
  125. data/views/root/index.html.haml +4 -0
  126. data/views/storage_snapshots/index.html.haml +20 -0
  127. data/views/storage_snapshots/index.xml.haml +9 -0
  128. data/views/storage_snapshots/show.html.haml +14 -0
  129. data/views/storage_snapshots/show.xml.haml +7 -0
  130. data/views/storage_volumes/index.html.haml +21 -0
  131. data/views/storage_volumes/index.xml.haml +13 -0
  132. data/views/storage_volumes/show.html.haml +20 -0
  133. data/views/storage_volumes/show.xml.haml +11 -0
  134. metadata +334 -0
data/server.rb ADDED
@@ -0,0 +1,354 @@
1
+ require 'sinatra'
2
+ require 'deltacloud'
3
+ require 'drivers'
4
+ require 'json'
5
+ require 'sinatra/respond_to'
6
+ require 'sinatra/static_assets'
7
+ require 'sinatra/rabbit'
8
+ require 'sinatra/lazy_auth'
9
+ require 'erb'
10
+ require 'haml'
11
+ require 'open3'
12
+
13
+ configure do
14
+ set :raise_errors => false
15
+ set :show_exceptions, false
16
+ end
17
+
18
+ configure :development do
19
+ # So we can just use puts for logging
20
+ $stdout.sync = true
21
+ $stderr.sync = true
22
+ end
23
+
24
+ # You could use $API_HOST environment variable to change your hostname to
25
+ # whatever you want (eg. if you running API behind NAT)
26
+ HOSTNAME=ENV['API_HOST'] ? ENV['API_HOST'] : nil
27
+
28
+ error Deltacloud::Validation::Failure do
29
+ report_error(400, "validation_failure")
30
+ end
31
+
32
+ error Deltacloud::AuthException do
33
+ report_error(403, "auth_exception")
34
+ end
35
+
36
+ error Deltacloud::BackendError do
37
+ report_error(500, "backend_error")
38
+ end
39
+
40
+ # Redirect to /api
41
+ get '/' do redirect url_for('/api'); end
42
+
43
+ get '/api\/?' do
44
+ @version = 0.1
45
+ respond_to do |format|
46
+ format.xml { haml :"api/show" }
47
+ format.json do
48
+ { :api => {
49
+ :version => @version,
50
+ :driver => DRIVER,
51
+ :links => entry_points.collect { |l| { :rel => l[0], :href => l[1]} }
52
+ }
53
+ }.to_json
54
+ end
55
+ format.html { haml :"api/show" }
56
+ end
57
+ end
58
+
59
+ # Rabbit DSL
60
+
61
+ collection :realms do
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
71
+
72
+ operation :index do
73
+ description <<END
74
+ Operation will list all available realms. For specific architecture use "architecture" parameter.
75
+ END
76
+ param :id, :string
77
+ param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
78
+ control { filter_all(:realms) }
79
+ end
80
+
81
+ #FIXME: It always shows whole list
82
+ operation :show do
83
+ description 'Show an realm identified by "id" parameter.'
84
+ param :id, :string, :required
85
+ control { show(:realm) }
86
+ end
87
+
88
+ end
89
+
90
+ collection :images do
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
95
+
96
+ operation :index do
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
102
+ param :id, :string
103
+ param :architecture, :string, :optional
104
+ control { filter_all(:images) }
105
+ end
106
+
107
+ operation :show do
108
+ description 'Show an image identified by "id" parameter.'
109
+ param :id, :string, :required
110
+ control { show(:image) }
111
+ end
112
+
113
+ end
114
+
115
+ collection :instance_states do
116
+ description "The possible states of an instance, and how to traverse between them "
117
+
118
+ operation :index do
119
+ control do
120
+ @machine = driver.instance_state_machine
121
+ respond_to do |format|
122
+ format.xml { haml :'instance_states/show', :layout => false }
123
+ format.json do
124
+ out = []
125
+ @machine.states.each do |state|
126
+ transitions = state.transitions.collect do |t|
127
+ t.automatically? ? {:to => t.destination, :auto => 'true'} : {:to => t.destination, :action => t.action}
128
+ end
129
+ out << { :name => state, :transitions => transitions }
130
+ end
131
+ out.to_json
132
+ end
133
+ format.html { haml :'instance_states/show'}
134
+ format.gv { erb :"instance_states/show" }
135
+ format.png do
136
+ # Trick respond_to into looking up the right template for the
137
+ # graphviz file
138
+ format(:gv); gv = erb :"instance_states/show"; format(:png)
139
+ png = ''
140
+ cmd = 'dot -Kdot -Gpad="0.2,0.2" -Gsize="5.0,8.0" -Gdpi="180" -Tpng'
141
+ Open3.popen3( cmd ) do |stdin, stdout, stderr|
142
+ stdin.write( gv )
143
+ stdin.close()
144
+ png = stdout.read
145
+ end
146
+ png
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ get "/api/instances/new" do
154
+ @instance = Instance.new( { :id=>params[:id], :image_id=>params[:image_id] } )
155
+ @image = driver.image( credentials, :id => params[:image_id] )
156
+ @hardware_profiles = driver.hardware_profiles(credentials, :architecture => @image.architecture )
157
+ @realms = driver.realms(credentials)
158
+ respond_to do |format|
159
+ format.html { haml :"instances/new" }
160
+ end
161
+ end
162
+
163
+ collection :instances do
164
+ description <<END
165
+ An instance is a concrete machine realized from an image.
166
+ The images collection may be obtained by following the link from the primary entry-point."
167
+ END
168
+
169
+ operation :index do
170
+ description "List all instances"
171
+ param :id, :string, :optional
172
+ param :state, :string, :optional
173
+ control { filter_all(:instances) }
174
+ end
175
+
176
+ operation :show do
177
+ description 'Show an instance identified by "id" parameter.'
178
+ param :id, :string, :required
179
+ control { show(:instance) }
180
+ end
181
+
182
+ operation :create do
183
+ description "Create a new instance"
184
+ param :image_id, :string, :required
185
+ param :realm_id, :string, :optional
186
+ param :hwp_id, :string, :optional
187
+ control do
188
+ @image = driver.image(credentials, :id => params[:image_id])
189
+ instance = driver.create_instance(credentials, @image.id, params)
190
+ respond_to do |format|
191
+ format.xml do
192
+ response.status = 201 # Created
193
+ response['Location'] = instance_url(instance.id)
194
+ @instance = instance
195
+ haml :"instances/show"
196
+ end
197
+ format.html do
198
+ redirect instance_url(instance.id) if instance and instance.id
199
+ redirect instances_url
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ operation :reboot, :method => :post, :member => true do
206
+ description "Reboot running instance"
207
+ param :id, :string, :required
208
+ control { instance_action(:reboot) }
209
+ end
210
+
211
+ operation :start, :method => :post, :member => true do
212
+ description "Start an instance"
213
+ param :id, :string, :required
214
+ control { instance_action(:start) }
215
+ end
216
+
217
+ operation :stop, :method => :post, :member => true do
218
+ description "Stop running instance"
219
+ param :id, :string, :required
220
+ control { instance_action(:stop) }
221
+ end
222
+
223
+ operation :destroy do
224
+ description "Destroy instance"
225
+ param :id, :string, :required
226
+ control { instance_action(:destroy) }
227
+ end
228
+ end
229
+
230
+ collection :hardware_profiles do
231
+ description <<END
232
+ A hardware profile represents a configuration of resources upon which a
233
+ machine may be deployed. It defines aspects such as local disk storage,
234
+ available RAM, and architecture. Each provider is free to define as many
235
+ (or as few) hardware profiles as desired.
236
+ END
237
+
238
+ operation :index do
239
+ description "List of available hardware profiles"
240
+ param :id, :string
241
+ param :architecture, :string, :optional, [ 'i386', 'x86_64' ]
242
+ control do
243
+ @profiles = driver.hardware_profiles(credentials, params)
244
+ respond_to do |format|
245
+ format.xml { haml :'hardware_profiles/index' }
246
+ format.html { haml :'hardware_profiles/index' }
247
+ format.json { convert_to_json(:hardware_profile, @profiles) }
248
+ end
249
+ end
250
+ end
251
+
252
+ operation :show do
253
+ description "Show specific hardware profile"
254
+ param :id, :string, :required
255
+ control do
256
+ @profile = driver.hardware_profile(credentials, params[:id])
257
+ if @profile
258
+ respond_to do |format|
259
+ format.xml { haml :'hardware_profiles/show', :layout => false }
260
+ format.html { haml :'hardware_profiles/show' }
261
+ format.json { convert_to_json(:hardware_profile, @profile) }
262
+ end
263
+ else
264
+ report_error(404, 'not_found')
265
+ end
266
+ end
267
+ end
268
+
269
+ end
270
+
271
+ collection :storage_snapshots do
272
+ description "Storage snapshots description here"
273
+
274
+ operation :index do
275
+ description "Listing of storage snapshots"
276
+ param :id, :string
277
+ control { filter_all(:storage_snapshots) }
278
+ end
279
+
280
+ operation :show do
281
+ description "Show storage snapshot"
282
+ param :id, :string, :required
283
+ control { show(:storage_snapshot) }
284
+ end
285
+ end
286
+
287
+ collection :storage_volumes do
288
+ description "Storage volumes description here"
289
+
290
+ operation :index do
291
+ description "Listing of storage volumes"
292
+ param :id, :string
293
+ control { filter_all(:storage_volumes) }
294
+ end
295
+
296
+ operation :show do
297
+ description "Show storage volume"
298
+ param :id, :string, :required
299
+ control { show(:storage_volume) }
300
+ end
301
+ end
302
+
303
+ get '/api/keys/new' do
304
+ respond_to do |format|
305
+ format.html { haml :"keys/new" }
306
+ end
307
+ end
308
+
309
+ collection :keys do
310
+ description "Instance authentication credentials"
311
+
312
+ operation :index do
313
+ description "List all available credentials which could be used for instance authentication"
314
+ control do
315
+ filter_all :keys
316
+ end
317
+ end
318
+
319
+ operation :show do
320
+ description "Show details about given instance credential"
321
+ param :id, :string, :required
322
+ control { show :key }
323
+ end
324
+
325
+ operation :create do
326
+ description "Create a new instance credential if backend supports this"
327
+ param :name, :string, :required
328
+ control do
329
+ unless driver.respond_to?(:create_key)
330
+ raise Deltacloud::BackendFeatureUnsupported.new('501',
331
+ 'Creating instance credentials is not supported in backend')
332
+ end
333
+ @key = driver.create_key(credentials, { :key_name => params[:name] })
334
+ respond_to do |format|
335
+ format.html { haml :"keys/show" }
336
+ format.xml { haml :"keys/show" }
337
+ end
338
+ end
339
+ end
340
+
341
+ operation :destroy do
342
+ description "Destroy given instance credential if backend supports this"
343
+ param :id, :string, :required
344
+ control do
345
+ unless driver.respond_to?(:destroy_key)
346
+ raise Deltacloud::BackendFeatureUnsupported.new('501',
347
+ 'Creating instance credentials is not supported in backend')
348
+ end
349
+ driver.destroy_key(credentials, { :key_name => params[:id]})
350
+ redirect(keys_url)
351
+ end
352
+ end
353
+
354
+ end
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'optparse'
5
+ require 'thin'
6
+
7
+ options = {
8
+ :env => 'production'
9
+ }
10
+ optparse = OptionParser.new do |opts|
11
+
12
+ opts.banner = <<BANNER
13
+ Usage:
14
+ deltacloudd -i <driver> [options]
15
+
16
+ Options:
17
+ BANNER
18
+ opts.on( '-i', '--driver DRIVER', 'Driver to use') do |driver|
19
+ ENV["API_DRIVER"] = driver
20
+ end
21
+ opts.on( '-r', '--hostname HOSTNAME',
22
+ 'Bind to HOST address (default: localhost)') do |host|
23
+ ENV["API_HOST"] = host
24
+ end
25
+ opts.on( '-p', '--port PORT', 'Use PORT (default: 3001)') do |port|
26
+ ENV["API_PORT"] = port
27
+ end
28
+ opts.on( '-e', '--env ENV', 'Environment (default: "development")') { |env| options[:env] = env }
29
+ opts.on( '-h', '--help', '') { options[:help] = true }
30
+ end
31
+
32
+ optparse.parse!
33
+
34
+ if options[:help]
35
+ puts optparse
36
+ exit(0)
37
+ end
38
+
39
+ unless ENV["API_DRIVER"]
40
+ puts "You need to specify a driver to use (-i <driver>)"
41
+ exit(1)
42
+ end
43
+
44
+ ENV["API_HOST"] = "localhost" unless ENV["API_HOST"]
45
+ ENV["API_PORT"] = "3001" unless ENV["API_PORT"]
46
+
47
+ dirname="#{File.dirname(__FILE__)}/.."
48
+
49
+ argv_opts = ARGV.clone
50
+ argv_opts << ['start'] unless Thin::Runner.commands.include?(options[0])
51
+ argv_opts << ['--address', ENV["API_HOST"] ]
52
+ argv_opts << ['--port', ENV["API_PORT"] ]
53
+ argv_opts << ['--rackup', 'config.ru' ]
54
+ argv_opts << ['--chdir', dirname ]
55
+ argv_opts << ['-e', options[:env] ]
56
+ argv_opts << ['--threaded', '-D', '--stats', '/stats']
57
+
58
+ argv_opts.flatten!
59
+
60
+ puts "Starting Deltacloud API :: #{ENV["API_DRIVER"]} :: http://#{ENV["API_HOST"]}:#{ENV["API_PORT"]}/api"
61
+ puts
62
+
63
+ thin = Thin::Runner.new(argv_opts)
64
+ begin
65
+ thin.run!
66
+ rescue Exception => e
67
+ puts "ERROR: #{e.message}"
68
+ end
@@ -0,0 +1,91 @@
1
+ %global ruby_sitelib %(ruby -rrbconfig -e "puts Config::CONFIG['sitelibdir']")
2
+ %global gemdir %(ruby -rubygems -e 'puts Gem::dir' 2>/dev/null)
3
+ %global gemname deltacloud-core
4
+ %global geminstdir %{gemdir}/gems/%{gemname}-%{version}
5
+
6
+ Summary: Deltacloud REST API
7
+ Name: rubygem-%{gemname}
8
+ Version: 0.0.1
9
+ Release: 2%{?dist}
10
+ Group: Development/Languages
11
+ License: ASL 2.0 and MIT
12
+ URL: http://www.deltacloud.org
13
+ Source0: http://gems.rubyforge.org/gems/%{gemname}-%{version}.gem
14
+ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
15
+ Requires: rubygems
16
+ Requires: ruby(abi) = 1.8
17
+ Requires: rubygem(eventmachine) >= 0.12.10
18
+ Requires: rubygem(haml) >= 2.2.17
19
+ Requires: rubygem(sinatra) >= 0.9.4
20
+ Requires: rubygem(rack) >= 1.0.0
21
+ Requires: rubygem(thin) >= 1.2.5
22
+ Requires: rubygem(builder) >= 2.1.2
23
+ Requires: rubygem(json) >= 1.2.3
24
+ BuildRequires: ruby-json >= 1.1.9
25
+ BuildRequires: rubygem(rake) >= 0.8.7
26
+ BuildRequires: rubygem(rack-test) >= 0.4.0
27
+ BuildRequires: rubygem(cucumber) >= 0.4.0
28
+ BuildRequires: rubygem(rcov) >= 0.9.6
29
+ BuildRequires: rubygems
30
+ BuildRequires: ruby(abi) = 1.8
31
+ BuildArch: noarch
32
+ Provides: rubygem(%{gemname}) = %{version}
33
+
34
+ %description
35
+ The Deltacloud API is built as a service-based REST API.
36
+ You do not directly link a Deltacloud library into your program to use it.
37
+ Instead, a client speaks the Deltacloud API over HTTP to a server
38
+ which implements the REST interface.
39
+
40
+ %prep
41
+
42
+ %build
43
+
44
+ %install
45
+ rm -rf %{buildroot}
46
+ mkdir -p %{buildroot}%{gemdir}
47
+ gem install --local --install-dir %{buildroot}%{gemdir} \
48
+ --force --rdoc %{SOURCE0}
49
+ mkdir -p %{buildroot}/%{_bindir}
50
+ mv %{buildroot}%{geminstdir}/support/fedora/deltacloudd %{buildroot}/%{geminstdir}/bin
51
+ mv %{buildroot}%{gemdir}/bin/* %{buildroot}/%{_bindir}
52
+ rmdir %{buildroot}%{gemdir}/bin
53
+ find %{buildroot}%{geminstdir}/bin -type f | xargs chmod a+x
54
+
55
+ # Needs json_pure gem / not available in Fedora yet
56
+ #%check
57
+ #pushd %{buildroot}%{geminstdir}
58
+ #cucumber features/*.feature
59
+ #popd
60
+
61
+ %clean
62
+ rm -rf %{buildroot}
63
+
64
+ %files
65
+ %defattr(-, root, root, -)
66
+ %{_bindir}/deltacloudd
67
+ %{gemdir}/gems/%{gemname}-%{version}/bin
68
+ %{gemdir}/gems/%{gemname}-%{version}/lib
69
+ %{gemdir}/gems/%{gemname}-%{version}/public/favicon.ico
70
+ %{gemdir}/gems/%{gemname}-%{version}/public/images
71
+ %{gemdir}/gems/%{gemname}-%{version}/public/stylesheets
72
+ %{gemdir}/gems/%{gemname}-%{version}/tests
73
+ %{gemdir}/gems/%{gemname}-%{version}/views
74
+ %{gemdir}/gems/%{gemname}-%{version}/Rakefile
75
+ %{gemdir}/gems/%{gemname}-%{version}/*.rb
76
+ %{gemdir}/gems/%{gemname}-%{version}/config.ru
77
+ %doc %{gemdir}/gems/%{gemname}-%{version}/support/fedora
78
+ %doc %{gemdir}/gems/%{gemname}-%{version}/COPYING
79
+ %doc %{gemdir}/doc/%{gemname}-%{version}
80
+ %{gemdir}/cache/%{gemname}-%{version}.gem
81
+ %{gemdir}/specifications/%{gemname}-%{version}.gemspec
82
+ # MIT
83
+ %{gemdir}/gems/%{gemname}-%{version}/public/javascripts
84
+
85
+ %changelog
86
+ * Mon Apr 26 2010 Michal Fojtik <mfojtik@packager> - 0.0.1-1
87
+ - Initial package
88
+
89
+ * Mon Apr 26 2010 Michal Fojtik <mfojtik@packager> - 0.0.1-2
90
+ - Fixed broken dependencies
91
+ - Added new launcher for Fedora
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