occi-api 4.2.0.beta.2 → 4.2.0.beta.3
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.
- data/lib/occi/api/client/client_base.rb +343 -112
- data/lib/occi/api/client/client_http.rb +99 -126
- data/lib/occi/api/client/errors.rb +4 -1
- data/lib/occi/api/client/errors/ambiguous_name_error.rb +5 -0
- data/lib/occi/api/client/errors/authn_error.rb +2 -4
- data/lib/occi/api/client/errors/location_error.rb +5 -0
- data/lib/occi/api/client/errors/not_implemented_error.rb +5 -0
- data/lib/occi/api/client/errors/type_mismatch_error.rb +5 -0
- data/lib/occi/api/client/http/authn_plugins/base.rb +1 -1
- data/lib/occi/api/client/http/authn_plugins/keystone.rb +2 -2
- data/lib/occi/api/version.rb +1 -1
- metadata +6 -2
@@ -5,13 +5,8 @@ module Occi
|
|
5
5
|
class ClientBase
|
6
6
|
|
7
7
|
# a few attributes which should be visible outside the client
|
8
|
-
attr_reader :endpoint
|
9
|
-
attr_reader :
|
10
|
-
attr_reader :media_type
|
11
|
-
attr_reader :connected
|
12
|
-
attr_reader :model
|
13
|
-
attr_reader :logger
|
14
|
-
attr_reader :last_response
|
8
|
+
attr_reader :endpoint, :auth_options, :media_type
|
9
|
+
attr_reader :connected, :model, :logger, :last_response
|
15
10
|
attr_reader :options
|
16
11
|
|
17
12
|
def initialize(options = {})
|
@@ -23,17 +18,17 @@ module Occi
|
|
23
18
|
:media_type => nil
|
24
19
|
}
|
25
20
|
|
26
|
-
options = options.marshal_dump if options.is_a?
|
27
|
-
@options = defaults.merge
|
21
|
+
options = options.marshal_dump if options.is_a?(OpenStruct)
|
22
|
+
@options = defaults.merge(options)
|
28
23
|
|
29
24
|
# set Occi::Log
|
30
|
-
|
25
|
+
@logger = get_logger(@options[:log])
|
31
26
|
|
32
27
|
# check the validity and canonize the endpoint URI
|
33
|
-
|
28
|
+
@endpoint = get_endpoint_uri(@options[:endpoint])
|
34
29
|
|
35
30
|
# pass auth options
|
36
|
-
|
31
|
+
@auth_options = get_auth(@options[:auth])
|
37
32
|
|
38
33
|
# verify authN before attempting actual
|
39
34
|
# message exchange with the server; this
|
@@ -42,7 +37,7 @@ module Occi
|
|
42
37
|
preauthenticate
|
43
38
|
|
44
39
|
# set accepted media types
|
45
|
-
|
40
|
+
@media_type = get_media_type(@options[:media_type])
|
46
41
|
|
47
42
|
@connected = false
|
48
43
|
end
|
@@ -82,7 +77,9 @@ module Occi
|
|
82
77
|
#
|
83
78
|
# @param [String] resource type identifier or just type name
|
84
79
|
# @return [Array<String>] list of links
|
85
|
-
def list(resource_type_identifier=nil)
|
80
|
+
def list(resource_type_identifier=nil)
|
81
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
82
|
+
end
|
86
83
|
|
87
84
|
# Retrieves descriptions for available resources specified by a type
|
88
85
|
# identifier or resource location. If no type identifier or location
|
@@ -101,7 +98,9 @@ module Occi
|
|
101
98
|
#
|
102
99
|
# @param [String] resource type identifier, type name or resource location
|
103
100
|
# @return [Occi::Core::Resources] list of resource descriptions
|
104
|
-
def describe(resource_type_identifier=nil)
|
101
|
+
def describe(resource_type_identifier=nil)
|
102
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
103
|
+
end
|
105
104
|
|
106
105
|
# Creates a new resource on the server. Resource must be provided
|
107
106
|
# as an instance of Occi::Core::Entity, e.g. instantiated using
|
@@ -118,7 +117,9 @@ module Occi
|
|
118
117
|
#
|
119
118
|
# @param [Occi::Core::Entity] resource to be created on the server
|
120
119
|
# @return [String] URI of the new resource
|
121
|
-
def create(entity)
|
120
|
+
def create(entity)
|
121
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
122
|
+
end
|
122
123
|
|
123
124
|
# Deploys a compute resource based on an OVF/OVA descriptor available
|
124
125
|
# on a local file system.
|
@@ -128,7 +129,9 @@ module Occi
|
|
128
129
|
#
|
129
130
|
# @param [String] location of an OVF/OVA file
|
130
131
|
# @return [String] URI of the new resource
|
131
|
-
def deploy(location)
|
132
|
+
def deploy(location)
|
133
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
134
|
+
end
|
132
135
|
|
133
136
|
# Deploys a compute resource based on an OVF descriptor available
|
134
137
|
# directly as a String.
|
@@ -138,7 +141,9 @@ module Occi
|
|
138
141
|
#
|
139
142
|
# @param [String] OVF descriptor (e.g., already read from a file or generated)
|
140
143
|
# @return [String] URI of the new resource
|
141
|
-
def deploy_ovf(descriptor)
|
144
|
+
def deploy_ovf(descriptor)
|
145
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
146
|
+
end
|
142
147
|
|
143
148
|
# Deploys a compute resource based on an OVA descriptor available
|
144
149
|
# directly as a String.
|
@@ -148,7 +153,9 @@ module Occi
|
|
148
153
|
#
|
149
154
|
# @param [String] OVA descriptor (e.g., already read from a file or generated)
|
150
155
|
# @return [String] URI of the new resource
|
151
|
-
def deploy_ova(descriptor)
|
156
|
+
def deploy_ova(descriptor)
|
157
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
158
|
+
end
|
152
159
|
|
153
160
|
# Deletes a resource or all resource of a certain resource type
|
154
161
|
# from the server.
|
@@ -160,17 +167,21 @@ module Occi
|
|
160
167
|
#
|
161
168
|
# @param [String] resource type identifier, type name or location
|
162
169
|
# @return [Boolean] status
|
163
|
-
def delete(resource_type_identifier)
|
170
|
+
def delete(resource_type_identifier)
|
171
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
172
|
+
end
|
164
173
|
|
165
174
|
# Triggers given action on a specific resource.
|
166
175
|
#
|
167
176
|
# @example
|
168
177
|
# TODO: add examples
|
169
178
|
#
|
170
|
-
# @param [String] resource
|
171
|
-
# @param [
|
179
|
+
# @param [String] resource type or type identifier
|
180
|
+
# @param [Occi::Core::ActionInstance] type of action
|
172
181
|
# @return [String] resource location
|
173
|
-
def trigger(resource_type_identifier,
|
182
|
+
def trigger(resource_type_identifier, action_instance)
|
183
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
184
|
+
end
|
174
185
|
|
175
186
|
# Refreshes the Occi::Model used inside the client. Useful for
|
176
187
|
# updating the model without creating a new instance or
|
@@ -178,7 +189,9 @@ module Occi
|
|
178
189
|
#
|
179
190
|
# @example
|
180
191
|
# client.refresh
|
181
|
-
def refresh
|
192
|
+
def refresh
|
193
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
194
|
+
end
|
182
195
|
|
183
196
|
##############################################################################
|
184
197
|
######## STUBS END
|
@@ -196,36 +209,121 @@ module Occi
|
|
196
209
|
# @param [String] resource name or resource identifier
|
197
210
|
# @return [Occi::Core::Resource] new resource instance
|
198
211
|
def get_resource(resource_type)
|
199
|
-
Occi::Log.debug("Instantiating #{resource_type}
|
200
|
-
|
201
|
-
type_id = if @model.get_by_id resource_type
|
202
|
-
# we got a resource type identifier
|
203
|
-
resource_type
|
204
|
-
else
|
205
|
-
# we got a resource type name
|
206
|
-
type_ids = @model.kinds.to_a.select { |kind| kind.term == resource_type }
|
207
|
-
type_ids.first.type_identifier if type_ids.any?
|
208
|
-
end
|
212
|
+
Occi::Log.debug("Instantiating #{resource_type.inspect}")
|
209
213
|
|
214
|
+
type_id = get_resource_type_identifier(resource_type)
|
210
215
|
raise "Unknown resource type! #{resource_type.inspect}" unless type_id
|
211
216
|
|
212
|
-
Occi::Core::Resource.new
|
217
|
+
new_resource = Occi::Core::Resource.new(type_id)
|
218
|
+
new_resource.model = @model
|
219
|
+
|
220
|
+
new_resource
|
213
221
|
end
|
214
222
|
|
215
|
-
# Retrieves all
|
223
|
+
# Retrieves all available category types.
|
216
224
|
#
|
217
225
|
# @example
|
218
|
-
# client.
|
226
|
+
# client.get_category_types # => [ "entity", "resource", "link" ]
|
227
|
+
#
|
228
|
+
# @return [Array<String>] list of available category types in a human-readable format
|
229
|
+
def get_category_types
|
230
|
+
@model.categories.to_a.collect { |category| category.term }
|
231
|
+
end
|
232
|
+
|
233
|
+
# Retrieves all available category type identifiers.
|
234
|
+
#
|
235
|
+
# @example
|
236
|
+
# client.get_category_type_identifiers
|
237
|
+
# # => [ "http://schemas.ogf.org/occi/core#entity",
|
238
|
+
# # "http://schemas.ogf.org/occi/core#resource",
|
239
|
+
# # "http://schemas.ogf.org/occi/core#link" ]
|
240
|
+
#
|
241
|
+
# @return [Array<String>] list of available category type identifiers
|
242
|
+
def get_category_type_identifiers
|
243
|
+
@model.categories.to_a.collect { |category| category.type_identifier }
|
244
|
+
end
|
245
|
+
|
246
|
+
# Retrieves available category type identifier for the given category type.
|
247
|
+
#
|
248
|
+
# @example
|
249
|
+
# client.get_category_type_identifier("compute")
|
250
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
251
|
+
#
|
252
|
+
# @return [String, nil] category type identifier for the given category type
|
253
|
+
def get_category_type_identifier(type)
|
254
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
255
|
+
|
256
|
+
cats = @model.categories.to_a.select { |k| k.term == type }
|
257
|
+
tis = cats.collect { |c| c.type_identifier }
|
258
|
+
tis.uniq!
|
259
|
+
|
260
|
+
if tis.length > 1
|
261
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
262
|
+
"Category type #{type.inspect} is ambiguous, use a type identifier!"
|
263
|
+
end
|
264
|
+
|
265
|
+
tis.first
|
266
|
+
end
|
267
|
+
|
268
|
+
# Retrieves all kind type identifiers related to a given type identifier
|
269
|
+
#
|
270
|
+
# @example
|
271
|
+
# client.get_kind_type_identifiers_related_to 'http://schemas.ogf.org/occi/infrastructure#network'
|
219
272
|
# # => [ "http://schemas.ogf.org/occi/infrastructure#network",
|
220
273
|
# # "http://schemas.ogf.org/occi/infrastructure#ipnetwork" ]
|
221
274
|
#
|
222
|
-
# @param [String]
|
223
|
-
# @return [Array<String>] list of available
|
224
|
-
# given type identifier
|
225
|
-
def
|
226
|
-
Occi::Log.debug("Getting
|
227
|
-
collection = @model.get
|
228
|
-
collection.kinds.collect { |kind| kind.type_identifier }
|
275
|
+
# @param [String] type identifier
|
276
|
+
# @return [Array<String>] list of available kind type identifiers related to
|
277
|
+
# the given type identifier
|
278
|
+
def get_kind_type_identifiers_related_to(type_identifier)
|
279
|
+
Occi::Log.debug("Getting kind type identifiers related to #{type_identifier.inspect}")
|
280
|
+
collection = @model.get(type_identifier)
|
281
|
+
collection.kinds.to_a.collect { |kind| kind.type_identifier }
|
282
|
+
end
|
283
|
+
|
284
|
+
# Retrieves all available kind types.
|
285
|
+
#
|
286
|
+
# @example
|
287
|
+
# client.get_kind_types # => [ "entity", "resource", "link" ]
|
288
|
+
#
|
289
|
+
# @return [Array<String>] list of available kind types in a human-readable format
|
290
|
+
def get_kind_types
|
291
|
+
@model.kinds.to_a.collect { |kind| kind.term }
|
292
|
+
end
|
293
|
+
|
294
|
+
# Retrieves all available kind type identifiers.
|
295
|
+
#
|
296
|
+
# @example
|
297
|
+
# client.get_kind_type_identifiers
|
298
|
+
# # => [ "http://schemas.ogf.org/occi/core#entity",
|
299
|
+
# # "http://schemas.ogf.org/occi/core#resource",
|
300
|
+
# # "http://schemas.ogf.org/occi/core#link" ]
|
301
|
+
#
|
302
|
+
# @return [Array<String>] list of available kind type identifiers
|
303
|
+
def get_kind_type_identifiers
|
304
|
+
@model.kinds.to_a.collect { |kind| kind.type_identifier }
|
305
|
+
end
|
306
|
+
|
307
|
+
# Retrieves available kind type identifier for the given kind type.
|
308
|
+
#
|
309
|
+
# @example
|
310
|
+
# client.get_kind_type_identifier("compute")
|
311
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
312
|
+
#
|
313
|
+
# @return [String, nil] kind type identifier for the given kind type
|
314
|
+
def get_kind_type_identifier(type)
|
315
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
316
|
+
|
317
|
+
kinds = @model.kinds.to_a.select { |k| k.term == type }
|
318
|
+
tis = kinds.collect { |k| k.type_identifier }
|
319
|
+
tis.uniq!
|
320
|
+
|
321
|
+
if tis.length > 1
|
322
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
323
|
+
"Kind type #{type.inspect} is ambiguous, use a type identifier!"
|
324
|
+
end
|
325
|
+
|
326
|
+
tis.first
|
229
327
|
end
|
230
328
|
|
231
329
|
# Retrieves all available entity types.
|
@@ -235,21 +333,44 @@ module Occi
|
|
235
333
|
#
|
236
334
|
# @return [Array<String>] list of available entity types in a human-readable format
|
237
335
|
def get_entity_types
|
238
|
-
Occi::
|
239
|
-
|
336
|
+
collection = @model.get(Occi::Core::Entity.kind.type_identifier)
|
337
|
+
collection.kinds.to_a.collect { |kind| kind.term }
|
240
338
|
end
|
241
339
|
|
242
340
|
# Retrieves all available entity type identifiers.
|
243
341
|
#
|
244
342
|
# @example
|
245
|
-
# client.
|
343
|
+
# client.get_kind_type_identifiers
|
246
344
|
# # => [ "http://schemas.ogf.org/occi/core#entity",
|
247
345
|
# # "http://schemas.ogf.org/occi/core#resource",
|
248
346
|
# # "http://schemas.ogf.org/occi/core#link" ]
|
249
347
|
#
|
250
348
|
# @return [Array<String>] list of available entity types in a OCCI ID format
|
251
349
|
def get_entity_type_identifiers
|
252
|
-
|
350
|
+
get_kind_type_identifiers_related_to Occi::Core::Entity.kind.type_identifier
|
351
|
+
end
|
352
|
+
|
353
|
+
# Retrieves available entity type identifier for the given entity type.
|
354
|
+
#
|
355
|
+
# @example
|
356
|
+
# client.get_entity_type_identifier("compute")
|
357
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
358
|
+
#
|
359
|
+
# @return [String, nil] entity type identifier for the given entity type
|
360
|
+
def get_entity_type_identifier(type)
|
361
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
362
|
+
|
363
|
+
collection = @model.get(Occi::Core::Entity.kind.type_identifier)
|
364
|
+
e_kinds = collection.kinds.to_a.select { |e| e.term == type }
|
365
|
+
tis = e_kinds.collect { |e| e.type_identifier }
|
366
|
+
tis.uniq!
|
367
|
+
|
368
|
+
if tis.length > 1
|
369
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
370
|
+
"Entity type #{type.inspect} is ambiguous, use a type identifier!"
|
371
|
+
end
|
372
|
+
|
373
|
+
tis.first
|
253
374
|
end
|
254
375
|
|
255
376
|
# Retrieves all available resource types.
|
@@ -259,9 +380,8 @@ module Occi
|
|
259
380
|
#
|
260
381
|
# @return [Array<String>] list of available resource types in a human-readable format
|
261
382
|
def get_resource_types
|
262
|
-
Occi::
|
263
|
-
collection
|
264
|
-
collection.kinds.collect { |kind| kind.term }
|
383
|
+
collection = @model.get(Occi::Core::Resource.kind.type_identifier)
|
384
|
+
collection.kinds.to_a.collect { |kind| kind.term }
|
265
385
|
end
|
266
386
|
|
267
387
|
# Retrieves all available resource type identifiers.
|
@@ -274,7 +394,30 @@ module Occi
|
|
274
394
|
#
|
275
395
|
# @return [Array<String>] list of available resource types in a Occi ID format
|
276
396
|
def get_resource_type_identifiers
|
277
|
-
|
397
|
+
get_kind_type_identifiers_related_to Occi::Core::Resource.kind.type_identifier
|
398
|
+
end
|
399
|
+
|
400
|
+
# Retrieves available resource type identifier for the given resource type.
|
401
|
+
#
|
402
|
+
# @example
|
403
|
+
# client.get_resource_type_identifier("compute")
|
404
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#compute'
|
405
|
+
#
|
406
|
+
# @return [String, nil] resource type identifier for the given resource type
|
407
|
+
def get_resource_type_identifier(type)
|
408
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
409
|
+
|
410
|
+
collection = @model.get(Occi::Core::Resource.kind.type_identifier)
|
411
|
+
r_kinds = collection.kinds.to_a.select { |r| r.term == type }
|
412
|
+
tis = r_kinds.collect { |r| r.type_identifier }
|
413
|
+
tis.uniq!
|
414
|
+
|
415
|
+
if tis.length > 1
|
416
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
417
|
+
"Resource type #{type.inspect} is ambiguous, use a type identifier!"
|
418
|
+
end
|
419
|
+
|
420
|
+
tis.first
|
278
421
|
end
|
279
422
|
|
280
423
|
# Retrieves all available link types.
|
@@ -284,9 +427,8 @@ module Occi
|
|
284
427
|
#
|
285
428
|
# @return [Array<String>] list of available link types in a human-readable format
|
286
429
|
def get_link_types
|
287
|
-
Occi::
|
288
|
-
collection
|
289
|
-
collection.kinds.collect { |kind| kind.term }
|
430
|
+
collection = @model.get(Occi::Core::Link.kind.type_identifier)
|
431
|
+
collection.kinds.to_a.collect { |kind| kind.term }
|
290
432
|
end
|
291
433
|
|
292
434
|
# Retrieves all available link type identifiers.
|
@@ -298,7 +440,30 @@ module Occi
|
|
298
440
|
#
|
299
441
|
# @return [Array<String>] list of available link types in a OCCI ID format
|
300
442
|
def get_link_type_identifiers
|
301
|
-
|
443
|
+
get_kind_type_identifiers_related_to Occi::Core::Link.kind.type_identifier
|
444
|
+
end
|
445
|
+
|
446
|
+
# Retrieves available link type identifier for the given link type.
|
447
|
+
#
|
448
|
+
# @example
|
449
|
+
# client.get_link_type_identifier("storagelink")
|
450
|
+
# # => 'http://schemas.ogf.org/occi/infrastructure#storagelink'
|
451
|
+
#
|
452
|
+
# @return [String, nil] link type identifier for the given link type
|
453
|
+
def get_link_type_identifier(type)
|
454
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
455
|
+
|
456
|
+
collection = @model.get(Occi::Core::Link.kind.type_identifier)
|
457
|
+
l_kinds = collection.kinds.to_a.select { |r| r.term == type }
|
458
|
+
tis = l_kinds.collect { |r| r.type_identifier }
|
459
|
+
tis.uniq!
|
460
|
+
|
461
|
+
if tis.length > 1
|
462
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
463
|
+
"Link type #{type.inspect} is ambiguous, use a type identifier!"
|
464
|
+
end
|
465
|
+
|
466
|
+
tis.first
|
302
467
|
end
|
303
468
|
|
304
469
|
# Looks up a mixin using its name and, optionally, a type as well.
|
@@ -404,16 +569,16 @@ module Occi
|
|
404
569
|
# @return [Occi::Core::Mixins] collection of available mixins
|
405
570
|
def get_mixins(type = nil)
|
406
571
|
unless type.blank?
|
407
|
-
|
572
|
+
type_id = get_mixin_type_identifier(type)
|
573
|
+
unless type_id
|
408
574
|
raise ArgumentError,
|
409
575
|
"There is no such mixin type registered in the model! #{type.inspect}"
|
410
576
|
end
|
411
577
|
|
412
|
-
|
413
|
-
mixins = @model.mixins.to_a.select { |m| m.related_to?(type) }
|
578
|
+
mixins = @model.mixins.to_a.select { |m| m.related_to?(type_id) }
|
414
579
|
|
415
580
|
# drop the type mixin itself
|
416
|
-
mixins.delete_if { |m| m.type_identifier ==
|
581
|
+
mixins.delete_if { |m| m.type_identifier == type_id }
|
417
582
|
else
|
418
583
|
# we did not get a type, return all mixins
|
419
584
|
mixins = Occi::Core::Mixins.new(@model.mixins)
|
@@ -479,8 +644,18 @@ module Occi
|
|
479
644
|
#
|
480
645
|
# @return [String, nil] mixin type identifier for the given mixin type
|
481
646
|
def get_mixin_type_identifier(type)
|
482
|
-
|
483
|
-
|
647
|
+
return type if (type =~ URI::ABS_URI) || (type && type.start_with?('/'))
|
648
|
+
|
649
|
+
mixins = @model.mixins.to_a.select { |m| m.term == type }
|
650
|
+
tis = mixins.collect { |m| m.type_identifier }
|
651
|
+
tis.uniq!
|
652
|
+
|
653
|
+
if tis.length > 1
|
654
|
+
raise Occi::Api::Client::Errors::AmbiguousNameError,
|
655
|
+
"Mixin type #{type.inspect} is ambiguous, use a type identifier!"
|
656
|
+
end
|
657
|
+
|
658
|
+
tis.first
|
484
659
|
end
|
485
660
|
|
486
661
|
# Retrieves available os_tpls from the model.
|
@@ -490,7 +665,7 @@ module Occi
|
|
490
665
|
#
|
491
666
|
# @return [Occi::Core::Mixins] collection containing all registered OS templates
|
492
667
|
def get_os_templates
|
493
|
-
get_mixins
|
668
|
+
get_mixins Occi::Infrastructure::OsTpl.mixin.type_identifier
|
494
669
|
end
|
495
670
|
alias_method :get_os_tpls, :get_os_templates
|
496
671
|
|
@@ -501,53 +676,90 @@ module Occi
|
|
501
676
|
#
|
502
677
|
# @return [Occi::Core::Mixins] collection containing all registered resource templates
|
503
678
|
def get_resource_templates
|
504
|
-
get_mixins
|
679
|
+
get_mixins Occi::Infrastructure::ResourceTpl.mixin.type_identifier
|
505
680
|
end
|
506
681
|
alias_method :get_resource_tpls, :get_resource_templates
|
507
682
|
|
508
|
-
# Returns the path for a given
|
683
|
+
# Returns the path for a given kind type identifier
|
509
684
|
#
|
510
685
|
# @example
|
511
|
-
#
|
686
|
+
# path_for_kind_type_identifier "http://schemas.ogf.org/occi/infrastructure#compute"
|
512
687
|
# # => "/compute/"
|
513
|
-
#
|
688
|
+
# path_for_kind_type_identifier "http://localhost:3300/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
514
689
|
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
515
690
|
#
|
516
|
-
# @param [String]
|
691
|
+
# @param [String] kind type identifier
|
517
692
|
# @return [String]
|
518
|
-
def
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
if
|
523
|
-
#we got an
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
raise
|
693
|
+
def path_for_kind_type_identifier(kind_type_identifier)
|
694
|
+
raise ArgumentError,
|
695
|
+
"Kind type identifier is a required argument!" if kind_type_identifier.blank?
|
696
|
+
|
697
|
+
if kind_type_identifier.start_with?(@endpoint.to_s) || kind_type_identifier.start_with?('/')
|
698
|
+
#we got an instance link
|
699
|
+
return sanitize_instance_link(kind_type_identifier)
|
700
|
+
end
|
701
|
+
|
702
|
+
kind_type_id = get_kind_type_identifier(kind_type_identifier)
|
703
|
+
unless kind_type_id
|
704
|
+
raise ArgumentError,
|
705
|
+
"There is no such kind type registered in the model! #{kind_type_identifier.inspect}"
|
706
|
+
end
|
707
|
+
|
708
|
+
kinds = @model.kinds.select { |kind| kind.type_identifier == kind_type_id }
|
709
|
+
path_for_instance(kinds.first)
|
710
|
+
end
|
711
|
+
|
712
|
+
# Returns the path for a given instance, instances not providing
|
713
|
+
# path information will raise an exception.
|
714
|
+
#
|
715
|
+
# @example
|
716
|
+
# path_for_instance Occi::Infrastructure::Network.new
|
717
|
+
# # => "/network/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
718
|
+
# path_for_instance Occi::Infrastructure::Compute.new
|
719
|
+
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
720
|
+
# path_for_instance Occi::Core::Mixin.new
|
721
|
+
# # => "/mixin/my_mixin/"
|
722
|
+
# path_for_instance Occi::Infrastructure::Storagelink.new
|
723
|
+
# # => "/link/storagelink/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
724
|
+
#
|
725
|
+
# @param [Object] instance
|
726
|
+
# @return [String] path for the given instance
|
727
|
+
def path_for_instance(instance)
|
728
|
+
unless instance.respond_to?(:location)
|
729
|
+
raise Occi::Api::Client::Errors::TypeMismatchError,
|
730
|
+
"Expected an instance responding to #location, " \
|
731
|
+
"got #{instance.class.name.inspect}"
|
732
|
+
end
|
733
|
+
|
734
|
+
if instance.location.blank?
|
735
|
+
raise Occi::Api::Client::Errors::LocationError,
|
736
|
+
"Instance of #{instance.class.name.inspect} has " \
|
737
|
+
"an empty location"
|
530
738
|
end
|
739
|
+
|
740
|
+
instance.location
|
531
741
|
end
|
532
742
|
|
533
|
-
# Extracts
|
743
|
+
# Extracts path from an instance link. It will remove the leading @endpoint
|
534
744
|
# and replace it with a slash.
|
535
745
|
#
|
536
746
|
# @example
|
537
|
-
#
|
747
|
+
# sanitize_instance_link "http://localhost:3300/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
538
748
|
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
539
|
-
#
|
749
|
+
# sanitize_instance_link "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
540
750
|
# # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
|
541
751
|
#
|
542
|
-
# @param [String] string containing the full
|
752
|
+
# @param [String] string containing the full instance link
|
543
753
|
# @return [String] extracted path, with a leading slash
|
544
|
-
def
|
754
|
+
def sanitize_instance_link(instance_link)
|
545
755
|
# everything starting with '/' is considered to be a resource path
|
546
|
-
return
|
756
|
+
return instance_link if instance_link.start_with? '/'
|
547
757
|
|
548
|
-
|
758
|
+
unless instance_link.start_with?(@endpoint.to_s)
|
759
|
+
raise ArgumentError, "Resource link #{instance_link.inspect} is not valid!"
|
760
|
+
end
|
549
761
|
|
550
|
-
|
762
|
+
URI(instance_link).request_uri
|
551
763
|
end
|
552
764
|
|
553
765
|
protected
|
@@ -560,29 +772,36 @@ module Occi
|
|
560
772
|
# are: ["basic", "digest", "x509", "none"]
|
561
773
|
#
|
562
774
|
# @example
|
563
|
-
#
|
564
|
-
#
|
565
|
-
#
|
566
|
-
#
|
775
|
+
# get_auth { :type => "none" }
|
776
|
+
# get_auth { :type => "basic", :username => "123", :password => "321" }
|
777
|
+
# get_auth { :type => "digest", :username => "123", :password => "321" }
|
778
|
+
# get_auth { :type => "x509", :user_cert => "~/cert.pem",
|
567
779
|
# :user_cert_password => "321", :ca_path => nil }
|
568
780
|
#
|
569
781
|
# @param [Hash] authentication options
|
570
782
|
# @param [Boolean] allow fallback-only options
|
571
|
-
|
783
|
+
# @return [Hash] transformed hash with authN information
|
784
|
+
def get_auth(auth_options, fallback = false)
|
785
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
786
|
+
end
|
572
787
|
|
573
788
|
# Attempts to establish a preliminary connection with the server
|
574
789
|
# to verify provided credentials and perform fallback authN
|
575
|
-
# if necessary. Has to be invoked after
|
576
|
-
def preauthenticate
|
790
|
+
# if necessary. Has to be invoked after @auth_options have been set.
|
791
|
+
def preauthenticate
|
792
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
793
|
+
end
|
577
794
|
|
578
795
|
# Sets media type. Will choose either application/occi+json or text/plain
|
579
796
|
# based on the formats supported by the server.
|
580
797
|
#
|
581
798
|
# @example
|
582
|
-
#
|
799
|
+
# get_media_type # => 'application/occi+json'
|
583
800
|
#
|
584
801
|
# @return [String] chosen media type
|
585
|
-
def
|
802
|
+
def get_media_type(force_type = nil)
|
803
|
+
raise Occi::Api::Client::Errors::NotImplementedError, "#{__method__} is just a stub!"
|
804
|
+
end
|
586
805
|
|
587
806
|
##############################################################################
|
588
807
|
######## STUBS END
|
@@ -592,40 +811,52 @@ module Occi
|
|
592
811
|
# instances to the rOCCI client.
|
593
812
|
#
|
594
813
|
# @example
|
595
|
-
#
|
814
|
+
# get_logger { :out => STDERR, :level => Occi::Log::WARN, :logger => nil }
|
596
815
|
#
|
597
816
|
# @param [Hash] logger options
|
598
|
-
|
817
|
+
# @return [Occi::Log] instance of the logger
|
818
|
+
def get_logger(log_options)
|
599
819
|
unless log_options[:logger] && log_options[:logger].kind_of?(Occi::Log)
|
600
|
-
|
601
|
-
|
820
|
+
logger = Occi::Log.new(log_options[:out])
|
821
|
+
logger.level = log_options[:level]
|
822
|
+
else
|
823
|
+
logger = log_options[:logger]
|
602
824
|
end
|
825
|
+
|
826
|
+
logger
|
603
827
|
end
|
604
828
|
|
605
|
-
# Checks whether the given endpoint URI is valid and
|
606
|
-
#
|
829
|
+
# Checks whether the given endpoint URI is valid and converts it
|
830
|
+
# to a URI instance.
|
607
831
|
#
|
608
832
|
# @example
|
609
|
-
#
|
833
|
+
# get_endpoint_uri "http://localhost:3300" # => #<URI::*>
|
610
834
|
#
|
611
835
|
# @param [String] endpoint URI in a non-canonical string
|
612
|
-
# @return [
|
613
|
-
def
|
614
|
-
|
615
|
-
|
836
|
+
# @return [URI] canonical endpoint URI
|
837
|
+
def get_endpoint_uri(endpoint)
|
838
|
+
unless endpoint =~ URI::ABS_URI
|
839
|
+
raise "Endpoint not a valid absolute URI! #{endpoint.inspect}"
|
840
|
+
end
|
841
|
+
|
842
|
+
# normalize URIs, remove trailing slashes
|
843
|
+
endpoint = URI(endpoint)
|
844
|
+
endpoint.path = endpoint.path.gsub(/\/+/, '/').chomp('/')
|
845
|
+
|
846
|
+
endpoint
|
616
847
|
end
|
617
848
|
|
618
849
|
# Creates an Occi::Model from data retrieved from the server.
|
619
850
|
#
|
620
851
|
# @example
|
621
|
-
#
|
622
|
-
#
|
852
|
+
# model_collection = get('/-/')
|
853
|
+
# get_model model_collection # => #<Occi::Model>
|
623
854
|
#
|
624
855
|
# @param [Occi::Collection] parsed representation of server's model
|
625
856
|
# @return [Occi::Model] Model instance
|
626
|
-
def
|
857
|
+
def get_model(model_collection)
|
627
858
|
# build model
|
628
|
-
|
859
|
+
Occi::Model.new(model_collection)
|
629
860
|
end
|
630
861
|
|
631
862
|
# Returns mixin type identifiers for os_tpl mixins
|
@@ -88,8 +88,8 @@ module Occi
|
|
88
88
|
|
89
89
|
# get model information from the endpoint
|
90
90
|
# and create Occi::Model instance
|
91
|
-
|
92
|
-
|
91
|
+
model_collection = get('/-/')
|
92
|
+
@model = get_model(model_collection)
|
93
93
|
|
94
94
|
# auto-connect?
|
95
95
|
@connected = @options[:auto_connect]
|
@@ -98,33 +98,18 @@ module Occi
|
|
98
98
|
# @see Occi::Api::Client::ClientBase
|
99
99
|
def list(resource_type_identifier=nil)
|
100
100
|
if resource_type_identifier
|
101
|
-
|
102
|
-
|
103
|
-
|kind| kind.term == resource_type_identifier
|
104
|
-
}
|
105
|
-
if kinds.any?
|
106
|
-
resource_type_identifier = kinds.first.type_identifier
|
107
|
-
end
|
108
|
-
|
109
|
-
raise 'Unkown resource type identifier!' unless resource_type_identifier
|
110
|
-
unless @model.get_by_id resource_type_identifier
|
111
|
-
raise "Resource type identifier not allowed with this model! [#{resource_type_identifier}]"
|
112
|
-
end
|
113
|
-
|
114
|
-
# split the type identifier and get the most important part
|
115
|
-
uri_part = resource_type_identifier.split('#').last
|
116
|
-
|
117
|
-
# request uri-list from the server
|
118
|
-
path = uri_part + '/'
|
101
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
102
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
119
103
|
end
|
120
104
|
|
121
105
|
path = '/' unless path
|
106
|
+
path = "#{@endpoint.to_s}#{path}"
|
122
107
|
|
123
108
|
headers = self.class.headers.clone
|
124
109
|
headers['Accept'] = 'text/uri-list'
|
125
110
|
|
126
111
|
response = self.class.get(
|
127
|
-
|
112
|
+
path,
|
128
113
|
:headers => headers
|
129
114
|
)
|
130
115
|
|
@@ -134,20 +119,13 @@ module Occi
|
|
134
119
|
|
135
120
|
# @see Occi::Api::Client::ClientBase
|
136
121
|
def describe(resource_type_identifier=nil)
|
137
|
-
|
138
|
-
# convert type to type identifier whenever possible
|
139
122
|
if resource_type_identifier
|
140
|
-
|
141
|
-
|kind| kind.term == resource_type_identifier
|
142
|
-
}
|
143
|
-
if kinds.any?
|
144
|
-
resource_type_identifier = kinds.first.type_identifier
|
145
|
-
end
|
123
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
146
124
|
end
|
147
125
|
|
148
126
|
descriptions = Occi::Collection.new
|
149
127
|
|
150
|
-
if resource_type_identifier.
|
128
|
+
if resource_type_identifier.blank?
|
151
129
|
# no filters, describe all available resources
|
152
130
|
descriptions.merge! get('/')
|
153
131
|
elsif @model.get_by_id(resource_type_identifier)
|
@@ -157,13 +135,13 @@ module Occi
|
|
157
135
|
|
158
136
|
# make the requests
|
159
137
|
locations.each do |location|
|
160
|
-
|
138
|
+
path = sanitize_instance_link(location)
|
139
|
+
descriptions.merge! get(path)
|
161
140
|
end
|
162
|
-
elsif resource_type_identifier.start_with?(@endpoint) || resource_type_identifier.start_with?('/')
|
163
|
-
# this is a link of a specific resource (obsolute or relative)
|
164
|
-
descriptions.merge! get(sanitize_resource_link(resource_type_identifier))
|
165
141
|
else
|
166
|
-
|
142
|
+
# this is a link of a specific resource (absolute or relative)
|
143
|
+
path = sanitize_instance_link(resource_type_identifier)
|
144
|
+
descriptions.merge! get(path)
|
167
145
|
end
|
168
146
|
|
169
147
|
descriptions.resources
|
@@ -171,30 +149,27 @@ module Occi
|
|
171
149
|
|
172
150
|
# @see Occi::Api::Client::ClientBase
|
173
151
|
def create(entity)
|
152
|
+
raise "#{entity.class.name.inspect} not an entity!" unless entity.kind_of? Occi::Core::Entity
|
174
153
|
|
175
|
-
|
176
|
-
|
177
|
-
Occi::Log.debug "Entity kind: #{entity.kind}"
|
178
|
-
kind = entity.kind
|
179
|
-
raise "No kind found for #{entity}" unless kind
|
154
|
+
Occi::Log.debug "Entity kind: #{entity.kind.type_identifier.inspect}"
|
155
|
+
raise "No kind found for #{entity.inspect}" unless entity.kind
|
180
156
|
|
181
157
|
# get location for this kind of entity
|
182
|
-
|
183
|
-
location = kind.location
|
158
|
+
path = path_for_kind_type_identifier(entity.kind.type_identifier)
|
184
159
|
collection = Occi::Collection.new
|
185
160
|
|
186
161
|
# is this entity a Resource or a Link?
|
187
|
-
Occi::Log.debug "Entity class: #{entity.class.name}"
|
162
|
+
Occi::Log.debug "Entity class: #{entity.class.name.inspect}"
|
188
163
|
collection.resources << entity if entity.kind_of? Occi::Core::Resource
|
189
164
|
collection.links << entity if entity.kind_of? Occi::Core::Link
|
190
165
|
|
191
166
|
# make the request
|
192
|
-
post
|
167
|
+
post path, collection
|
193
168
|
end
|
194
169
|
|
195
170
|
# @see Occi::Api::Client::ClientBase
|
196
171
|
def deploy(location)
|
197
|
-
raise "File #{location} does not exist!" unless File.exist? location
|
172
|
+
raise "File #{location.inspect} does not exist!" unless File.exist? location
|
198
173
|
|
199
174
|
file = File.read(location)
|
200
175
|
|
@@ -209,12 +184,14 @@ module Occi
|
|
209
184
|
|
210
185
|
# @see Occi::Api::Client::ClientBase
|
211
186
|
def deploy_ovf(descriptor)
|
212
|
-
media_types = self.class.head(@endpoint).headers['accept'].to_s
|
187
|
+
media_types = self.class.head(@endpoint.to_s).headers['accept'].to_s
|
213
188
|
|
189
|
+
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
190
|
+
path = "#{@endpoint.to_s}#{path}"
|
214
191
|
if media_types.include? 'application/ovf'
|
215
192
|
headers = self.class.headers.clone
|
216
193
|
headers['Content-Type'] = 'application/ovf'
|
217
|
-
self.class.post(
|
194
|
+
self.class.post(path,
|
218
195
|
:body => descriptor,
|
219
196
|
:headers => headers)
|
220
197
|
else
|
@@ -224,12 +201,14 @@ module Occi
|
|
224
201
|
|
225
202
|
# @see Occi::Api::Client::ClientBase
|
226
203
|
def deploy_ova(descriptor)
|
227
|
-
media_types = self.class.head(@endpoint).headers['accept'].to_s
|
204
|
+
media_types = self.class.head(@endpoint.to_s).headers['accept'].to_s
|
228
205
|
|
206
|
+
path = path_for_kind_type_identifier(Occi::Infrastructure::Compute.type_identifier)
|
207
|
+
path = "#{@endpoint.to_s}#{path}"
|
229
208
|
if media_types.include? ' application/ova '
|
230
209
|
headers = self.class.headers.clone
|
231
210
|
headers['Content-Type'] = 'application/ova'
|
232
|
-
self.class.post(
|
211
|
+
self.class.post(path,
|
233
212
|
:body => descriptor,
|
234
213
|
:headers => headers)
|
235
214
|
else
|
@@ -239,47 +218,31 @@ module Occi
|
|
239
218
|
|
240
219
|
# @see Occi::Api::Client::ClientBase
|
241
220
|
def delete(resource_type_identifier)
|
242
|
-
raise 'Resource not provided!'
|
243
|
-
path =
|
221
|
+
raise 'Resource not provided!' if resource_type_identifier.blank?
|
222
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
244
223
|
|
245
|
-
Occi::Log.debug("Deleting #{path}
|
224
|
+
Occi::Log.debug("Deleting #{path.inspect} for #{resource_type_identifier.inspect}")
|
246
225
|
del path
|
247
226
|
end
|
248
227
|
|
249
228
|
# @see Occi::Api::Client::ClientBase
|
250
|
-
def trigger(resource_type_identifier,
|
229
|
+
def trigger(resource_type_identifier, action_instance)
|
251
230
|
# TODO: not tested
|
252
|
-
raise 'Resource not provided!'
|
253
|
-
type_identifiers = @model.kinds.select {
|
254
|
-
|kind| kind.term == resource_type_identifier
|
255
|
-
}
|
256
|
-
|
257
|
-
if type_identifiers.any?
|
258
|
-
type_identifier = @model.kinds.select {
|
259
|
-
|kind| kind.term == resource_type_identifier
|
260
|
-
}.first.type_identifier
|
261
|
-
|
262
|
-
location = @model.get_by_id(type_identifier).location
|
263
|
-
resource_type_identifier = @endpoint + location
|
264
|
-
end
|
265
|
-
|
266
|
-
raise "Unknown resource identifier! #{resource_type_identifier}" unless resource_type_identifier.start_with? @endpoint
|
231
|
+
raise 'Resource not provided!' if resource_type_identifier.blank?
|
267
232
|
|
268
|
-
#
|
269
|
-
|
270
|
-
|
271
|
-
collection.actions << Occi::Core::Action.new(scheme + '#', term)
|
233
|
+
#
|
234
|
+
resource_type_identifier = get_resource_type_identifier(resource_type_identifier)
|
235
|
+
path = path_for_kind_type_identifier(resource_type_identifier)
|
272
236
|
|
273
237
|
# make the request
|
274
|
-
path
|
275
|
-
post path, collection
|
238
|
+
post path, action_instance
|
276
239
|
end
|
277
240
|
|
278
241
|
# @see Occi::Api::Client::ClientBase
|
279
242
|
def refresh
|
280
243
|
# re-download the model from the server
|
281
|
-
|
282
|
-
|
244
|
+
model_collection = get('/-/')
|
245
|
+
@model = get_model(model_collection)
|
283
246
|
end
|
284
247
|
|
285
248
|
private
|
@@ -294,10 +257,10 @@ module Occi
|
|
294
257
|
# @param [String] path for the GET request
|
295
258
|
# @param [Occi::Collection] collection of filters
|
296
259
|
# @return [Occi::Collection] parsed result of the request
|
297
|
-
def get(path='', filter=nil)
|
298
|
-
|
299
|
-
path = path
|
300
|
-
|
260
|
+
def get(path='/', filter=nil)
|
261
|
+
relative_path = path
|
262
|
+
path = "#{@endpoint.to_s}#{path}"
|
263
|
+
# apply filters if present
|
301
264
|
response = if filter
|
302
265
|
categories = filter.categories.collect { |category| category.to_text }.join(',')
|
303
266
|
attributes = filter.entities.collect { |entity| entity.attributes.combine.collect { |k, v| k + '=' + v } }.join(',')
|
@@ -307,28 +270,28 @@ module Occi
|
|
307
270
|
headers['Category'] = categories unless categories.empty?
|
308
271
|
headers['X-OCCI-Attributes'] = attributes unless attributes.empty?
|
309
272
|
|
310
|
-
self.class.get(
|
273
|
+
self.class.get(path, :headers => headers)
|
311
274
|
else
|
312
|
-
self.class.get(
|
275
|
+
self.class.get(path)
|
313
276
|
end
|
314
277
|
|
315
278
|
response_msg = response_message response
|
316
279
|
raise "HTTP GET failed! #{response_msg}" unless response.code.between? 200, 300
|
317
280
|
|
318
|
-
Occi::Log.debug "Response location: #{
|
319
|
-
kind = @model.get_by_location(
|
281
|
+
Occi::Log.debug "Response location: #{relative_path.inspect}"
|
282
|
+
kind = @model.get_by_location(relative_path) if @model
|
320
283
|
|
321
|
-
Occi::Log.debug "Response kind: #{kind}"
|
284
|
+
Occi::Log.debug "Response kind: #{kind.inspect}"
|
322
285
|
|
323
|
-
|
324
|
-
|
325
|
-
entity_type = Occi::Core::Link
|
286
|
+
entity_type = nil
|
287
|
+
if kind && kind.related_to?(Occi::Core::Link)
|
288
|
+
entity_type = Occi::Core::Link
|
326
289
|
end
|
327
290
|
|
328
291
|
entity_type = Occi::Core::Resource unless entity_type
|
329
292
|
|
330
|
-
Occi::Log.debug "Parser call: #{response.content_type} #{path.include?('
|
331
|
-
collection = Occi::Parser.parse(response.content_type, response.body, path.include?('
|
293
|
+
Occi::Log.debug "Parser call: #{response.content_type} #{path.include?('/-/')} #{entity_type} #{response.headers.inspect}"
|
294
|
+
collection = Occi::Parser.parse(response.content_type, response.body, path.include?('/-/'), entity_type, response.headers)
|
332
295
|
|
333
296
|
Occi::Log.debug "Parsed collection: empty? #{collection.empty?}"
|
334
297
|
collection
|
@@ -350,27 +313,28 @@ module Occi
|
|
350
313
|
# @param [Occi::Collection] resource data to be POSTed
|
351
314
|
# @return [String] URI location
|
352
315
|
def post(path, collection)
|
353
|
-
|
354
|
-
path = path.gsub(/\A\//, '')
|
316
|
+
raise ArgumentError, "Path is a required argument!" if path.blank?
|
355
317
|
|
356
318
|
headers = self.class.headers.clone
|
357
319
|
headers['Content-Type'] = @media_type
|
358
320
|
|
321
|
+
path = "#{@endpoint.to_s}#{path}"
|
322
|
+
|
359
323
|
response = case @media_type
|
360
324
|
when 'application/occi+json'
|
361
|
-
self.class.post(
|
325
|
+
self.class.post(path,
|
362
326
|
:body => collection.to_json,
|
363
327
|
:headers => headers)
|
364
328
|
when 'text/occi'
|
365
|
-
self.class.post(
|
329
|
+
self.class.post(path,
|
366
330
|
:headers => collection.to_header.merge(headers))
|
367
331
|
else
|
368
|
-
self.class.post(
|
332
|
+
self.class.post(path,
|
369
333
|
:body => collection.to_text,
|
370
334
|
:headers => headers)
|
371
335
|
end
|
372
336
|
|
373
|
-
response_msg = response_message
|
337
|
+
response_msg = response_message(response)
|
374
338
|
|
375
339
|
case response.code
|
376
340
|
when 200
|
@@ -403,27 +367,28 @@ module Occi
|
|
403
367
|
# @param [Occi::Collection] resource data to send
|
404
368
|
# @return [Occi::Collection] parsed result of the request
|
405
369
|
def put(path, collection)
|
406
|
-
|
407
|
-
path = path.gsub(/\A\//, '')
|
370
|
+
raise ArgumentError, "Path is a required argument!" if path.blank?
|
408
371
|
|
409
372
|
headers = self.class.headers.clone
|
410
373
|
headers['Content-Type'] = @media_type
|
411
374
|
|
375
|
+
path = "#{@endpoint.to_s}#{path}"
|
376
|
+
|
412
377
|
response = case @media_type
|
413
378
|
when 'application/occi+json'
|
414
|
-
self.class.post(
|
379
|
+
self.class.post(path,
|
415
380
|
:body => collection.to_json,
|
416
381
|
:headers => headers)
|
417
382
|
when 'text/occi'
|
418
|
-
self.class.post(
|
383
|
+
self.class.post(path,
|
419
384
|
:headers => collection.to_header.merge(headers))
|
420
385
|
else
|
421
|
-
self.class.post(
|
386
|
+
self.class.post(path,
|
422
387
|
:body => collection.to_text,
|
423
388
|
:headers => headers)
|
424
389
|
end
|
425
390
|
|
426
|
-
response_msg = response_message
|
391
|
+
response_msg = response_message(response)
|
427
392
|
|
428
393
|
case response.code
|
429
394
|
when 200, 201
|
@@ -442,38 +407,37 @@ module Occi
|
|
442
407
|
# @param [Occi::Collection] collection of filters (currently NOT used)
|
443
408
|
# @return [Boolean] status
|
444
409
|
def del(path, filter=nil)
|
445
|
-
|
446
|
-
path = path.gsub(/\A\//, '')
|
410
|
+
raise ArgumentError, "Path is a required argument!" if path.blank?
|
447
411
|
|
448
|
-
response = self.class.delete(@endpoint
|
412
|
+
response = self.class.delete("#{@endpoint.to_s}#{path}")
|
449
413
|
|
450
|
-
response_msg = response_message
|
414
|
+
response_msg = response_message(response)
|
451
415
|
raise "HTTP DELETE failed! #{response_msg}" unless response.code.between? 200, 300
|
452
416
|
|
453
417
|
true
|
454
418
|
end
|
455
419
|
|
456
420
|
# @see Occi::Api::Client::ClientBase
|
457
|
-
def
|
458
|
-
super
|
421
|
+
def get_logger(log_options)
|
422
|
+
logger = super(log_options)
|
423
|
+
self.class.debug_output $stderr if logger.level == Occi::Log::DEBUG
|
459
424
|
|
460
|
-
|
425
|
+
logger
|
461
426
|
end
|
462
427
|
|
463
428
|
# @see Occi::Api::Client::ClientBase
|
464
|
-
def
|
465
|
-
|
466
|
-
|
467
|
-
case @auth_options[:type]
|
429
|
+
def get_auth(auth_options, fallback = false)
|
430
|
+
# select appropriate authN type
|
431
|
+
case auth_options[:type]
|
468
432
|
when "basic"
|
469
|
-
@authn_plugin = Http::AuthnPlugins::Basic.new self,
|
433
|
+
@authn_plugin = Http::AuthnPlugins::Basic.new self, auth_options
|
470
434
|
when "digest"
|
471
|
-
@authn_plugin = Http::AuthnPlugins::Digest.new self,
|
435
|
+
@authn_plugin = Http::AuthnPlugins::Digest.new self, auth_options
|
472
436
|
when "x509"
|
473
|
-
@authn_plugin = Http::AuthnPlugins::X509.new self,
|
437
|
+
@authn_plugin = Http::AuthnPlugins::X509.new self, auth_options
|
474
438
|
when "keystone"
|
475
439
|
raise ::Occi::Api::Client::Errors::AuthnError, "This authN method is for fallback only!" unless fallback
|
476
|
-
@authn_plugin = Http::AuthnPlugins::Keystone.new self,
|
440
|
+
@authn_plugin = Http::AuthnPlugins::Keystone.new self, auth_options
|
477
441
|
when "none", nil
|
478
442
|
@authn_plugin = Http::AuthnPlugins::Dummy.new self
|
479
443
|
else
|
@@ -481,6 +445,8 @@ module Occi
|
|
481
445
|
end
|
482
446
|
|
483
447
|
@authn_plugin.setup
|
448
|
+
|
449
|
+
auth_options
|
484
450
|
end
|
485
451
|
|
486
452
|
# @see Occi::Api::Client::ClientBase
|
@@ -495,7 +461,7 @@ module Occi
|
|
495
461
|
@auth_options[:original_type] = @auth_options[:type]
|
496
462
|
@auth_options[:type] = @authn_plugin.fallbacks.first
|
497
463
|
|
498
|
-
|
464
|
+
@auth_options = get_auth(@auth_options, true)
|
499
465
|
@authn_plugin.authenticate
|
500
466
|
else
|
501
467
|
raise e
|
@@ -504,34 +470,41 @@ module Occi
|
|
504
470
|
end
|
505
471
|
|
506
472
|
# @see Occi::Api::Client::ClientBase
|
507
|
-
def
|
473
|
+
def get_media_type(force_type = nil)
|
508
474
|
# force media_type if provided
|
509
|
-
|
475
|
+
unless force_type.blank?
|
510
476
|
self.class.headers 'Accept' => force_type
|
511
|
-
|
477
|
+
media_type = force_type
|
512
478
|
else
|
513
|
-
media_types = self.class.head(@endpoint).headers['accept']
|
514
|
-
|
515
|
-
|
479
|
+
media_types = self.class.head(@endpoint.to_s).headers['accept']
|
480
|
+
|
481
|
+
Occi::Log.debug("Available media types: #{media_types.inspect}")
|
482
|
+
media_type = case media_types
|
516
483
|
when /application\/occi\+json/
|
517
484
|
'application/occi+json'
|
485
|
+
when /application\/occi\+xml/
|
486
|
+
'application/occi+xml'
|
487
|
+
when /text\/occi/
|
488
|
+
'text/occi'
|
518
489
|
else
|
519
490
|
'text/plain'
|
520
491
|
end
|
521
492
|
end
|
493
|
+
|
494
|
+
media_type
|
522
495
|
end
|
523
496
|
|
524
497
|
# Generates a human-readable response message based on the HTTP response code.
|
525
498
|
#
|
526
499
|
# @example
|
527
|
-
# response_message self.class.delete(@endpoint + path)
|
500
|
+
# response_message self.class.delete(@endpoint.to_s + path)
|
528
501
|
# # => 'HTTP Response status: [200] OK'
|
529
502
|
#
|
530
503
|
# @param [HTTParty::Response] HTTParty response object
|
531
504
|
# @return [String] message
|
532
505
|
def response_message(response)
|
533
506
|
@last_response = response
|
534
|
-
|
507
|
+
"HTTP Response status: [#{response.code.to_s}] #{reason_phrase(response.code)}"
|
535
508
|
end
|
536
509
|
|
537
510
|
# Converts HTTP response codes to human-readable phrases.
|
@@ -16,7 +16,7 @@ module Occi::Api::Client
|
|
16
16
|
def setup(options = {}); end
|
17
17
|
|
18
18
|
def authenticate(options = {})
|
19
|
-
response = @env_ref.class.head
|
19
|
+
response = @env_ref.class.head("#{@env_ref.endpoint.to_s}/-/")
|
20
20
|
raise ::Occi::Api::Client::Errors::AuthnError, "Authentication failed with code #{response.code.to_s}!" unless response.success?
|
21
21
|
end
|
22
22
|
|
@@ -18,7 +18,7 @@ module Occi::Api::Client
|
|
18
18
|
|
19
19
|
def authenticate(options = {})
|
20
20
|
# OCCI-OS doesn't support HEAD method!
|
21
|
-
response = @env_ref.class.get "#{@env_ref.endpoint}
|
21
|
+
response = @env_ref.class.get "#{@env_ref.endpoint.to_s}/-/"
|
22
22
|
raise ::Occi::Api::Client::Errors::AuthnError,
|
23
23
|
"Authentication failed with code #{response.code.to_s}!" unless response.success?
|
24
24
|
end
|
@@ -26,7 +26,7 @@ module Occi::Api::Client
|
|
26
26
|
private
|
27
27
|
|
28
28
|
def set_keystone_base_url
|
29
|
-
response = @env_ref.class.head "#{@env_ref.endpoint}
|
29
|
+
response = @env_ref.class.head "#{@env_ref.endpoint.to_s}/-/"
|
30
30
|
Occi::Log.debug response.inspect
|
31
31
|
|
32
32
|
return if response.success?
|
data/lib/occi/api/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occi-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.2.0.beta.
|
4
|
+
version: 4.2.0.beta.3
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2013-12-
|
14
|
+
date: 2013-12-06 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: occi-core
|
@@ -87,7 +87,11 @@ files:
|
|
87
87
|
- lib/occi/api/client/client_base.rb
|
88
88
|
- lib/occi/api/client/client_http.rb
|
89
89
|
- lib/occi/api/client/errors.rb
|
90
|
+
- lib/occi/api/client/errors/ambiguous_name_error.rb
|
90
91
|
- lib/occi/api/client/errors/authn_error.rb
|
92
|
+
- lib/occi/api/client/errors/location_error.rb
|
93
|
+
- lib/occi/api/client/errors/not_implemented_error.rb
|
94
|
+
- lib/occi/api/client/errors/type_mismatch_error.rb
|
91
95
|
- lib/occi/api/client/http/authn_plugins.rb
|
92
96
|
- lib/occi/api/client/http/authn_plugins/base.rb
|
93
97
|
- lib/occi/api/client/http/authn_plugins/basic.rb
|