bbrowning-deltacloud-core 0.0.4-java

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