occi-api 4.0.0.alpha.1

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 (105) hide show
  1. data/.gitignore +15 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +43 -0
  4. data/.yardopts +1 -0
  5. data/AUTHORS +9 -0
  6. data/Gemfile +16 -0
  7. data/LICENSE +13 -0
  8. data/README.md +344 -0
  9. data/Rakefile +37 -0
  10. data/examples/dsl_example.rb +167 -0
  11. data/examples/x509auth_example.rb +161 -0
  12. data/ext/mkrf_conf.rb +34 -0
  13. data/features/cassettes/Create_an_OCCI_Resource/_http_http___141_5_99_69__text_plain_201_.yml +288 -0
  14. data/features/cassettes/Delete_an_OCCI_Resource/_http_http___141_5_99_69__text_plain_201_.yml +288 -0
  15. data/features/cassettes/Discovery_Interface/Retrieving_all_OCCI_Categories_supported_by_the_OCCI_Server/_http_http___141_5_99_69__application_json_200_.yml +333 -0
  16. data/features/cassettes/Discovery_Interface/Retrieving_all_OCCI_Categories_supported_by_the_OCCI_Server/_http_http___141_5_99_69__text_plain_200_.yml +529 -0
  17. data/features/cassettes/Discovery_Interface/Retrieving_all_OCCI_Categories_supported_by_the_OCCI_Server/_http_http___141_5_99_69__text_plain_200_action_.yml +288 -0
  18. data/features/cassettes/Miscellaneous_operation_on_an_OCCI_Resource/_http_http___141_5_99_69__text_plain_201_.yml +288 -0
  19. data/features/cassettes/Read_an_OCCI_Resource/_http_http___141_5_99_69__text_plain_201_.yml +288 -0
  20. data/features/cassettes/Update_an_OCCI_Resource/_http_http___141_5_99_69__text_plain_201_.yml +288 -0
  21. data/features/common/step_definitions/common_steps.rb +32 -0
  22. data/features/occi/core/create/create.feature +18 -0
  23. data/features/occi/core/create/step_definitions/create_steps.rb +0 -0
  24. data/features/occi/core/delete/delete.feature +18 -0
  25. data/features/occi/core/delete/step_definitions/delete_steps.rb +0 -0
  26. data/features/occi/core/discovery_interface/discovery_interface.feature +37 -0
  27. data/features/occi/core/discovery_interface/step_definitions/discovery_interface_steps.rb +19 -0
  28. data/features/occi/core/miscellaneous/miscellaneous.feature +18 -0
  29. data/features/occi/core/miscellaneous/step_definitions/miscellaneous_steps.rb +0 -0
  30. data/features/occi/core/read/read.feature +18 -0
  31. data/features/occi/core/read/step_definitions/read_steps.rb +0 -0
  32. data/features/occi/core/update/step_definitions/update_steps.rb +0 -0
  33. data/features/occi/core/update/update.feature +18 -0
  34. data/features/occi/infrastructure/create/create.feature +18 -0
  35. data/features/occi/infrastructure/create/step_definitions/create_steps.rb +0 -0
  36. data/features/support/env.rb +16 -0
  37. data/lib/occi/api/client/client_amqp.rb +766 -0
  38. data/lib/occi/api/client/client_base.rb +689 -0
  39. data/lib/occi/api/client/client_http.rb +541 -0
  40. data/lib/occi/api/client/errors/authn_error.rb +7 -0
  41. data/lib/occi/api/client/errors.rb +1 -0
  42. data/lib/occi/api/client/http/authn_plugins/base.rb +27 -0
  43. data/lib/occi/api/client/http/authn_plugins/basic.rb +22 -0
  44. data/lib/occi/api/client/http/authn_plugins/digest.rb +22 -0
  45. data/lib/occi/api/client/http/authn_plugins/dummy.rb +13 -0
  46. data/lib/occi/api/client/http/authn_plugins/keystone.rb +61 -0
  47. data/lib/occi/api/client/http/authn_plugins/x509.rb +46 -0
  48. data/lib/occi/api/client/http/authn_plugins.rb +6 -0
  49. data/lib/occi/api/client/http/authn_utils.rb +87 -0
  50. data/lib/occi/api/client/http/httparty_fix.rb +53 -0
  51. data/lib/occi/api/client/http/net_http_fix.rb +21 -0
  52. data/lib/occi/api/dsl.rb +146 -0
  53. data/lib/occi/api/version.rb +5 -0
  54. data/lib/occi-api.rb +14 -0
  55. data/occi-api.gemspec +38 -0
  56. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/creates_a_new_compute_resource.yml +266 -0
  57. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/creates_a_new_network_resource.yml +266 -0
  58. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/creates_a_new_storage_resource.yml +266 -0
  59. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/deletes_a_compute_resource.yml +266 -0
  60. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/deletes_a_network_resource.yml +266 -0
  61. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/deletes_a_storage_resource.yml +266 -0
  62. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/deploys_an_instance_based_on_OVF_OVA_file.yml +266 -0
  63. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/describes_compute_resources.yml +368 -0
  64. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/describes_network_resources.yml +370 -0
  65. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/describes_storage_resources.yml +430 -0
  66. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/establishes_connection.yml +266 -0
  67. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/finds_and_describes_scoped_os_tpl_mixin.yml +266 -0
  68. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/finds_and_describes_scoped_resource_tpl_mixin.yml +266 -0
  69. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/finds_and_describes_unscoped_mixin.yml +266 -0
  70. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/instantiates_a_compute_resource_using_type_identifier.yml +266 -0
  71. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/instantiates_a_compute_resource_using_type_name.yml +266 -0
  72. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/instantiates_a_network_resource_using_type_identifier.yml +266 -0
  73. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/instantiates_a_network_resource_using_type_name.yml +266 -0
  74. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/instantiates_a_storage_resource_using_type_identifier.yml +266 -0
  75. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/instantiates_a_storage_resource_using_type_name.yml +266 -0
  76. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_entity_type_identifiers.yml +266 -0
  77. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_entity_types.yml +266 -0
  78. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_link_type_identifiers.yml +266 -0
  79. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_link_types.yml +266 -0
  80. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_mixin_type_identifiers.yml +266 -0
  81. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_mixin_types.yml +266 -0
  82. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_mixins.yml +266 -0
  83. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_resource_type_identifiers.yml +266 -0
  84. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_all_available_resource_types.yml +266 -0
  85. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_compute_resources.yml +308 -0
  86. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_network_resources.yml +308 -0
  87. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_os_tpl_mixins.yml +266 -0
  88. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_resource_tpl_mixins.yml +266 -0
  89. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/lists_storage_resources.yml +310 -0
  90. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/refreshes_its_model.yml +485 -0
  91. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/triggers_an_action_on_a_compute_resource.yml +266 -0
  92. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/triggers_an_action_on_a_network_resource.yml +266 -0
  93. data/spec/cassettes/Occi_Api_Client_ClientHttp/using_media_type_text_plain/triggers_an_action_on_a_storage_resource.yml +266 -0
  94. data/spec/occi/api/client/client_amqp_spec.rb +158 -0
  95. data/spec/occi/api/client/client_http_spec.rb +292 -0
  96. data/spec/occi/api/client/http/authn_utils_spec.rb +55 -0
  97. data/spec/occi/api/client/http/httparty_fix_spec.rb +0 -0
  98. data/spec/occi/api/client/http/net_http_fix_spec.rb +0 -0
  99. data/spec/occi/api/client/http/rocci-cred-cert.pem +3 -0
  100. data/spec/occi/api/client/http/rocci-cred-key-jruby.pem +3 -0
  101. data/spec/occi/api/client/http/rocci-cred-key.pem +3 -0
  102. data/spec/occi/api/client/http/rocci-cred.p12 +0 -0
  103. data/spec/occi/api/dsl_spec.rb +21 -0
  104. data/spec/spec_helper.rb +38 -0
  105. metadata +379 -0
@@ -0,0 +1,689 @@
1
+ module Occi
2
+ module Api
3
+ module Client
4
+
5
+ class ClientBase
6
+
7
+ # a few attributes which should be visible outside the client
8
+ attr_reader :endpoint
9
+ attr_reader :auth_options
10
+ attr_reader :media_type
11
+ attr_reader :connected
12
+ attr_reader :model
13
+ attr_reader :logger
14
+ attr_reader :last_response
15
+ attr_reader :options
16
+
17
+ def initialize(options = {})
18
+ defaults = {
19
+ :endpoint => "http://localhost:3300/",
20
+ :auth => {:type => "none"},
21
+ :log => {:out => STDERR, :level => Occi::Log::WARN, :logger => nil},
22
+ :auto_connect => true,
23
+ :media_type => nil
24
+ }
25
+
26
+ options = options.marshal_dump if options.is_a? OpenStruct
27
+ @options = defaults.merge options
28
+
29
+ # set Occi::Log
30
+ set_logger @options[:log]
31
+
32
+ # check the validity and canonize the endpoint URI
33
+ set_endpoint @options[:endpoint]
34
+
35
+ # pass auth options
36
+ set_auth @options[:auth]
37
+
38
+ # verify authN before attempting actual
39
+ # message exchange with the server; this
40
+ # is necessary because of OCCI-OS and its
41
+ # redirect to OS Keystone
42
+ preauthenticate
43
+
44
+ # set accepted media types
45
+ set_media_type @options[:media_type]
46
+
47
+ @connected = false
48
+ end
49
+
50
+ # Issues necessary connecting operations on connection-oriented
51
+ # clients. Stateless clients (such as ClientHttp) should use
52
+ # the auto_connect option during instantiation.
53
+ #
54
+ # @example
55
+ # client.connect # => true
56
+ #
57
+ # @param [Boolean] force re-connect on already connected client
58
+ # @return [Boolean] true on successful connect
59
+ def connect(force = false)
60
+ raise "Client already connected!" if @connected && !force
61
+ @connected = true
62
+ end
63
+
64
+ ##############################################################################
65
+ ######## STUBS START
66
+ ##############################################################################
67
+
68
+ # Retrieves available resources represented by resource locations (URIs).
69
+ # If no type identifier is specified, all available resource are listed.
70
+ # Type identifier can be specified in its shortened format (e.g. "compute",
71
+ # "storage", "network").
72
+ #
73
+ # @example
74
+ # client.list
75
+ # # => [ "http://localhost:3300/compute/jh425jhj3h413-7dj29d7djd9e3-djh2jh4j4j",
76
+ # # "http://localhost:3300/network/kh425jhj3h413-7dj29d7djd9e3-djh2jh4j4j",
77
+ # # "http://localhost:3300/storage/lh425jhj3h413-7dj29d7djd9e3-djh2jh4j4j" ]
78
+ # client.list "compute"
79
+ # # => [ "http://localhost:3300/compute/jh425jhj3h413-7dj29d7djd9e3-djh2jh4j4j" ]
80
+ # client.list "http://schemas.ogf.org/occi/infrastructure#compute"
81
+ # # => [ "http://localhost:3300/compute/jh425jhj3h413-7dj29d7djd9e3-djh2jh4j4j" ]
82
+ #
83
+ # @param [String] resource type identifier or just type name
84
+ # @return [Array<String>] list of links
85
+ def list(resource_type_identifier=nil); end
86
+
87
+ # Retrieves descriptions for available resources specified by a type
88
+ # identifier or resource location. If no type identifier or location
89
+ # is specified, all available resources in all available resource types
90
+ # will be described.
91
+ #
92
+ # @example
93
+ # client.describe
94
+ # # => [#<Occi::Collection>, #<Occi::Collection>, #<Occi::Collection>]
95
+ # client.describe "compute"
96
+ # # => [#<Occi::Collection>, #<Occi::Collection>, #<Occi::Collection>]
97
+ # client.describe "http://schemas.ogf.org/occi/infrastructure#compute"
98
+ # # => [#<Occi::Collection>, #<Occi::Collection>, #<Occi::Collection>]
99
+ # client.describe "http://localhost:3300/compute/j5hk1234jk2524-2j3j2k34jjh234-adfaf1234"
100
+ # # => [#<Occi::Collection>]
101
+ #
102
+ # @param [String] resource type identifier, type name or resource location
103
+ # @return [Array<Occi::Collection>] list of resource descriptions
104
+ def describe(resource_type_identifier=nil); end
105
+
106
+ # Creates a new resource on the server. Resource must be provided
107
+ # as an instance of Occi::Core::Entity, e.g. instantiated using
108
+ # the get_resource method.
109
+ #
110
+ # @example
111
+ # res = client.get_resource "compute"
112
+ #
113
+ # res.title = "MyComputeResource1"
114
+ # res.mixins << client.find_mixin('small', "resource_tpl")
115
+ # res.mixins << client.find_mixin('debian6', "os_tpl")
116
+ #
117
+ # client.create res # => "http://localhost:3300/compute/df7698...f987fa"
118
+ #
119
+ # @param [Occi::Core::Entity] resource to be created on the server
120
+ # @return [String] URI of the new resource
121
+ def create(entity); end
122
+
123
+ # Deploys a compute resource based on an OVF/OVA descriptor available
124
+ # on a local file system.
125
+ #
126
+ # @example
127
+ # client.deploy "~/MyVMs/rOcciVM.ovf" # => "http://localhost:3300/compute/343423...42njhdafa"
128
+ #
129
+ # @param [String] location of an OVF/OVA file
130
+ # @return [String] URI of the new resource
131
+ def deploy(location); end
132
+
133
+ # Deploys a compute resource based on an OVF descriptor available
134
+ # directly as a String.
135
+ #
136
+ # @example
137
+ # client.deploy_ovf "OVF DESCRIPTOR HERE" # => "http://localhost:3300/compute/343423...42njhdafa"
138
+ #
139
+ # @param [String] OVF descriptor (e.g., already read from a file or generated)
140
+ # @return [String] URI of the new resource
141
+ def deploy_ovf(descriptor); end
142
+
143
+ # Deploys a compute resource based on an OVA descriptor available
144
+ # directly as a String.
145
+ #
146
+ # @example
147
+ # client.deploy_ova "OVA DESCRIPTOR HERE" # => "http://localhost:3300/compute/343423...42njhdafa"
148
+ #
149
+ # @param [String] OVA descriptor (e.g., already read from a file or generated)
150
+ # @return [String] URI of the new resource
151
+ def deploy_ova(descriptor); end
152
+
153
+ # Deletes a resource or all resource of a certain resource type
154
+ # from the server.
155
+ #
156
+ # @example
157
+ # client.delete "compute" # => true
158
+ # client.delete "http://schemas.ogf.org/occi/infrastructure#compute" # => true
159
+ # client.delete "http://localhost:3300/compute/245j42594...98s9df8s9f" # => true
160
+ #
161
+ # @param [String] resource type identifier, type name or location
162
+ # @return [Boolean] status
163
+ def delete(resource_type_identifier); end
164
+
165
+ # Triggers given action on a specific resource.
166
+ #
167
+ # @example
168
+ # TODO: add examples
169
+ #
170
+ # @param [String] resource location
171
+ # @param [String] type of action
172
+ # @return [String] resource location
173
+ def trigger(resource_type_identifier, action); end
174
+
175
+ # Refreshes the Occi::Model used inside the client. Useful for
176
+ # updating the model without creating a new instance or
177
+ # reconnecting. Saves a lot of time in an interactive mode.
178
+ #
179
+ # @example
180
+ # client.refresh
181
+ def refresh; end
182
+
183
+ ##############################################################################
184
+ ######## STUBS END
185
+ ##############################################################################
186
+
187
+ # Creates a new resource instance, resource should be specified
188
+ # by its name or identifier.
189
+ #
190
+ # @example
191
+ # client.get_resource "compute" # => Occi::Core::Resource
192
+ # client.get_resource "storage" # => Occi::Core::Resource
193
+ # client.get_resource "http://schemas.ogf.org/occi/infrastructure#network"
194
+ # # => Occi::Core::Resource
195
+ #
196
+ # @param [String] resource name or resource identifier
197
+ # @return [Occi::Core::Resource] new resource instance
198
+ def get_resource(resource_type)
199
+
200
+ Occi::Log.debug("Instantiating #{resource_type} ...")
201
+
202
+ type_id = nil
203
+ if @model.get_by_id resource_type
204
+ # we got a resource type identifier
205
+ type_id = resource_type
206
+ else
207
+ # we got a resource type name
208
+ type_ids = @model.kinds.select { |kind| kind.term == resource_type }
209
+ type_id = type_ids.first.type_identifier if type_ids.any?
210
+ end
211
+
212
+ raise "Unknown resource type! [#{resource_type}]" unless type_id
213
+
214
+ Occi::Core::Resource.new type_id
215
+ end
216
+
217
+ # Retrieves all entity type identifiers related to a given type identifier
218
+ #
219
+ # @example
220
+ # client.get_entity_type_identifiers_related_to 'network'
221
+ # # => [ "http://schemas.ogf.org/occi/infrastructure#network",
222
+ # # "http://schemas.ogf.org/occi/infrastructure#ipnetwork" ]
223
+ #
224
+ # @param [String] type_identifier
225
+ # @return [Array<String>] list of available entity type identifiers related to
226
+ # given type identifier in a human-readable format
227
+ def get_entity_types_related_to(type_identifier)
228
+ Occi::Log.debug("Getting entity type identifiers related to #{type_identifier}")
229
+ collection = @model.get type_identifier
230
+ collection.kinds.collect { |kind| kind.type_identifier }
231
+ end
232
+
233
+ # Retrieves all available entity types.
234
+ #
235
+ # @example
236
+ # client.get_entity_types # => [ "entity", "resource", "link" ]
237
+ #
238
+ # @return [Array<String>] list of available entity types in a human-readable format
239
+ def get_entity_types
240
+ Occi::Log.debug("Getting entity types ...")
241
+ @model.kinds.collect { |kind| kind.term }
242
+ end
243
+
244
+ # Retrieves all available entity type identifiers.
245
+ #
246
+ # @example
247
+ # client.get_entity_type_identifiers
248
+ # # => [ "http://schemas.ogf.org/occi/core#entity",
249
+ # # "http://schemas.ogf.org/occi/core#resource",
250
+ # # "http://schemas.ogf.org/occi/core#link" ]
251
+ #
252
+ # @return [Array<String>] list of available entity types in a OCCI ID format
253
+ def get_entity_type_identifiers
254
+ get_entity_types_related_to Occi::Core::Entity.kind.type_identifier
255
+ end
256
+
257
+ # Retrieves all available resource types.
258
+ #
259
+ # @example
260
+ # client.get_resource_types # => [ "compute", "storage", "network" ]
261
+ #
262
+ # @return [Array<String>] list of available resource types in a human-readable format
263
+ def get_resource_types
264
+ Occi::Log.debug("Getting resource types ...")
265
+ collection = @model.get Occi::Core::Resource.kind
266
+ collection.kinds.collect { |kind| kind.term }
267
+ end
268
+
269
+ # Retrieves all available resource type identifiers.
270
+ #
271
+ # @example
272
+ # client.get_resource_type_identifiers
273
+ # # => [ "http://schemas.ogf.org/occi/infrastructure#compute",
274
+ # # "http://schemas.ogf.org/occi/infrastructure#storage",
275
+ # # "http://schemas.ogf.org/occi/infrastructure#network" ]
276
+ #
277
+ # @return [Array<String>] list of available resource types in a Occi ID format
278
+ def get_resource_type_identifiers
279
+ get_entity_types_related_to Occi::Core::Resource.kind.type_identifier
280
+ end
281
+
282
+ # Retrieves all available link types.
283
+ #
284
+ # @example
285
+ # client.get_link_types # => [ "storagelink", "networkinterface" ]
286
+ #
287
+ # @return [Array<String>] list of available link types in a human-readable format
288
+ def get_link_types
289
+ Occi::Log.debug("Getting link types ...")
290
+ collection = @model.get Occi::Core::Link.kind
291
+ collection.kinds.collect { |kind| kind.term }
292
+ end
293
+
294
+ # Retrieves all available link type identifiers.
295
+ #
296
+ # @example
297
+ # client.get_link_type_identifiers
298
+ # # => [ "http://schemas.ogf.org/occi/infrastructure#storagelink",
299
+ # # "http://schemas.ogf.org/occi/infrastructure#networkinterface" ]
300
+ #
301
+ # @return [Array<String>] list of available link types in a OCCI ID format
302
+ def get_link_type_identifiers
303
+ get_entity_types_related_to Occi::Core::Link.kind.type_identifier
304
+ end
305
+
306
+ # Looks up a mixin using its name and, optionally, a type as well.
307
+ # Will return mixin's full location (a link) or a description.
308
+ #
309
+ # @example
310
+ # client.find_mixin "debian6"
311
+ # # => "http://my.occi.service/occi/infrastructure/os_tpl#debian6"
312
+ # client.find_mixin "debian6", "os_tpl", true
313
+ # # => #<Occi::Collection>
314
+ # client.find_mixin "large", "resource_tpl"
315
+ # # => "http://my.occi.service/occi/infrastructure/resource_tpl#large"
316
+ # client.find_mixin "debian6", "resource_tpl" # => nil
317
+ #
318
+ # @param [String] name of the mixin
319
+ # @param [String] type of the mixin
320
+ # @param [Boolean] should we describe the mixin or return its link?
321
+ # @return [String, Occi::Collection, nil] link, mixin description or nothing found
322
+ def find_mixin(name, type = nil, describe = false)
323
+
324
+ Occi::Log.debug("Looking for mixin #{name} + #{type} + #{describe}")
325
+
326
+ # is type valid?
327
+ raise "Unknown mixin type! [#{type}]" if type && !@mixins.has_key?(type.to_sym)
328
+
329
+ # TODO: extend this code to support multiple matches and regex filters
330
+ # should we look for links or descriptions?
331
+ if describe
332
+ # we are looking for descriptions
333
+ find_mixin_describe name, type
334
+ else
335
+ # we are looking for links
336
+ find_mixin_list name, type
337
+ end
338
+ end
339
+
340
+ # Looks up a mixin using its name and, optionally, a type as well.
341
+ # Will return mixin's full description.
342
+ #
343
+ # @example
344
+ # client.find_mixin "debian6"
345
+ # # => #<Occi::Collection>
346
+ # client.find_mixin "debian6", "os_tpl"
347
+ # # => #<Occi::Collection>
348
+ # client.find_mixin "large", "resource_tpl"
349
+ # # => #<Occi::Collection>
350
+ # client.find_mixin "debian6", "resource_tpl" # => nil
351
+ #
352
+ # @param [String] name of the mixin
353
+ # @param [String] type of the mixin
354
+ # @return [Occi::Collection, nil] mixin description or nothing found
355
+ def find_mixin_describe(name, type = nil)
356
+ found_ary = []
357
+
358
+ if type
359
+ # get the first match from either os_tpls or resource_tpls
360
+ case type
361
+ when "os_tpl"
362
+ found_ary = get_os_templates.select { |mixin| mixin.term == name }
363
+ when "resource_tpl"
364
+ found_ary = get_resource_templates.select { |template| template.term == name }
365
+ else
366
+ # TODO: should raise an Error?
367
+ end
368
+ else
369
+ # try in os_tpls first
370
+ found_ary = get_os_templates.select { |os| os.term == name }
371
+
372
+ # then try in resource_tpls
373
+
374
+ found_ary = get_resource_templates.select {
375
+ |template| template.term == name
376
+ } unless found_ary.any?
377
+ end
378
+
379
+ found_ary.any? ? found_ary.first : nil
380
+ end
381
+
382
+ # Looks up a mixin using its name and, optionally, a type as well.
383
+ # Will return mixin's full location.
384
+ #
385
+ # @example
386
+ # client.find_mixin "debian6"
387
+ # # => "http://my.occi.service/occi/infrastructure/os_tpl#debian6"
388
+ # client.find_mixin "debian6", "os_tpl"
389
+ # # => "http://my.occi.service/occi/infrastructure/os_tpl#debian6"
390
+ # client.find_mixin "large", "resource_tpl"
391
+ # # => "http://my.occi.service/occi/infrastructure/resource_tpl#large"
392
+ # client.find_mixin "debian6", "resource_tpl" # => nil
393
+ #
394
+ # @param [String] name of the mixin
395
+ # @param [String] type of the mixin
396
+ # @return [String, nil] link or nothing found
397
+ def find_mixin_list(name, type = nil)
398
+ # prefix mixin name with '#' to simplify the search
399
+ mxns = []
400
+ name_rev = "##{name}".reverse
401
+
402
+ if type
403
+ # return the first match with the selected type
404
+ mxns = @mixins[type.to_sym].select {
405
+ |mixin| mixin.to_s.reverse.start_with? name_rev
406
+ }
407
+ else
408
+ # there is no type preference, return first global match
409
+ mxns = @mixins.flatten(2).select {
410
+ |mixin| mixin.to_s.reverse.start_with? name_rev
411
+ }
412
+ end
413
+
414
+ mxns.any? ? mxns.first : nil
415
+ end
416
+
417
+ # Retrieves available mixins of a specified type or all available
418
+ # mixins if the type wasn't specified. Mixins are returned in the
419
+ # form of mixin identifiers.
420
+ #
421
+ # @example
422
+ # client.get_mixins
423
+ # # => ["http://my.occi.service/occi/infrastructure/os_tpl#debian6",
424
+ # # "http://my.occi.service/occi/infrastructure/resource_tpl#small"]
425
+ # client.get_mixins "os_tpl"
426
+ # # => ["http://my.occi.service/occi/infrastructure/os_tpl#debian6"]
427
+ # client.get_mixins "resource_tpl"
428
+ # # => ["http://my.occi.service/occi/infrastructure/resource_tpl#small"]
429
+ #
430
+ # @param [String] type of mixins
431
+ # @return [Array<String>] list of available mixins
432
+ def get_mixins(type = nil)
433
+ if type
434
+ # is type valid?
435
+ raise "Unknown mixin type! #{type}" unless @mixins.has_key? type.to_sym
436
+
437
+ # return mixin of the selected type
438
+ @mixins[type.to_sym]
439
+ else
440
+ # we did not get a type, return all mixins
441
+ mixins = []
442
+
443
+ # flatten the hash and remove its keys
444
+ get_mixin_types.each do |ltype|
445
+ mixins.concat @mixins[ltype.to_sym]
446
+ end
447
+
448
+ mixins
449
+ end
450
+ end
451
+
452
+ # Retrieves available mixin types. Mixin types are presented
453
+ # in a shortened format (i.e. not as type identifiers).
454
+ #
455
+ # @example
456
+ # client.get_mixin_types # => [ "os_tpl", "resource_tpl" ]
457
+ #
458
+ # @return [Array<String>] list of available mixin types
459
+ def get_mixin_types
460
+ @mixins.keys.map { |k| k.to_s }
461
+ end
462
+
463
+ # Retrieves available mixin type identifiers.
464
+ #
465
+ # @example
466
+ # client.get_mixin_type_identifiers
467
+ # # => ['http://schemas.ogf.org/occi/infrastructure#os_tpl',
468
+ # # 'http://schemas.ogf.org/occi/infrastructure#resource_tpl']
469
+ #
470
+ # @return [Array<String>] list of available mixin type identifiers
471
+ def get_mixin_type_identifiers
472
+ identifiers = []
473
+
474
+ get_mixin_types.each do |mixin_type|
475
+ identifiers << 'http://schemas.ogf.org/occi/infrastructure#' + mixin_type
476
+ end
477
+
478
+ identifiers
479
+ end
480
+
481
+ # Retrieves available os_tpls from the model.
482
+ #
483
+ # @example
484
+ # get_os_templates # => #<Occi::Collection>
485
+ #
486
+ # @return [Occi::Collection] collection containing all registered OS templates
487
+ def get_os_templates
488
+ @model.get.mixins.select { |mixin| mixin.related.select { |rel| rel.end_with? 'os_tpl' }.any? }
489
+ end
490
+
491
+ # Retrieves available resource_tpls from the model.
492
+ #
493
+ # @example
494
+ # get_resource_templates # => #<Occi::Collection>
495
+ #
496
+ # @return [Occi::Collection] collection containing all registered resource templates
497
+ def get_resource_templates
498
+ @model.get.mixins.select { |mixin| mixin.related.select { |rel| rel.end_with? 'resource_tpl' }.any? }
499
+ end
500
+
501
+ # Creates a link of a specified kind and binds it to the given resource.
502
+ #
503
+ # @example
504
+ # link_kind = 'http://schemas.ogf.org/occi/infrastructure#storagelink'
505
+ # compute = client.get_resource "compute"
506
+ # storage_location = "http://localhost:3300/storage/321df21adfad-f3adfa5f4adf-a3d54ffadffe"
507
+ # linked_resource_kind = 'http://schemas.ogf.org/occi/infrastructure#storage'
508
+ #
509
+ # link link_kind, compute, storage_location, linked_resource_kind
510
+ #
511
+ # @param [String] link type identifier (link kind)
512
+ # @param [Occi::Core::Resource] resource to link to
513
+ # @param [URI, String] resource to be linked
514
+ # @param [String] type identifier of the linked resource
515
+ # @param [Occi::Core::Attributes] link attributes
516
+ # @param [Array<String>] link mixins
517
+ # @return [Occi::Core::Link] link instance
518
+ def link(kind, source, target_location, target_kind, attributes=Occi::Core::Attributes.new, mixins=[])
519
+ link = Occi::Core::Link.new(kind)
520
+ link.mixins = mixins
521
+ link.attributes = attributes
522
+ link.target = (target_location.kind_of? URI::Generic) ? target_location.path : target_location.to_s
523
+ link.rel = target_kind
524
+
525
+ link.check @model
526
+ source.links << link
527
+
528
+ link
529
+ end
530
+
531
+ # Returns the path for a given resource type identifier
532
+ #
533
+ # @example
534
+ # path_for_resource_type "http://schemas.ogf.org/occi/infrastructure#compute"
535
+ # # => "/compute/"
536
+ # path_for_resource_type "http://localhost:3300/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
537
+ # # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
538
+ #
539
+ # @param [String] resource type identifier
540
+ # @return [String]
541
+ def path_for_resource_type(resource_type_identifier)
542
+ return "/" if resource_type_identifier.nil? || resource_type_identifier == "/"
543
+
544
+ kinds = @model.kinds.select { |kind| kind.term == resource_type_identifier }
545
+ if kinds.any?
546
+ #we got an type identifier
547
+ path = "/" + kinds.first.type_identifier.split('#').last + "/"
548
+ elsif resource_type_identifier.start_with?(@endpoint) || resource_type_identifier.start_with?('/')
549
+ #we got an resource link
550
+ path = sanitize_resource_link(resource_type_identifier)
551
+ else
552
+ raise "Unknown resource identifier! #{resource_type_identifier}"
553
+ end
554
+ end
555
+
556
+ # Extracts the resource path from a resource link. It will remove the leading @endpoint
557
+ # and replace it with a slash.
558
+ #
559
+ # @example
560
+ # sanitize_resource_link "http://localhost:3300/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
561
+ # # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
562
+ # sanitize_resource_link "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
563
+ # # => "/compute/35ad4f45gsf-gsfg524s6gsfg-sfgsf4gsfg"
564
+ #
565
+ # @param [String] string containing the full resource link
566
+ # @return [String] extracted path, with a leading slash
567
+ def sanitize_resource_link(resource_link)
568
+ # everything starting with '/' is considered to be a resource path
569
+ return resource_link if resource_link.start_with? '/'
570
+
571
+ raise "Resource link #{resource_link} is not valid!" unless resource_link.start_with? @endpoint
572
+
573
+ resource_link.gsub @endpoint, '/'
574
+ end
575
+
576
+ protected
577
+
578
+ # Sets auth method and appropriate httparty attributes. Supported auth methods
579
+ # are: ["basic", "digest", "x509", "none"]
580
+ #
581
+ # @example
582
+ # set_auth { :type => "none" }
583
+ # set_auth { :type => "basic", :username => "123", :password => "321" }
584
+ # set_auth { :type => "digest", :username => "123", :password => "321" }
585
+ # set_auth { :type => "x509", :user_cert => "~/cert.pem",
586
+ # :user_cert_password => "321", :ca_path => nil }
587
+ #
588
+ # @param [Hash] authentication options
589
+ # @param [Boolean] allow fallback-only options
590
+ def set_auth(auth_options, fallback = false); end
591
+
592
+ # Attempts to establish a preliminary connection with the server
593
+ # to verify provided credentials and perform fallback authN
594
+ # if necessary. Has to be invoked after set_auth
595
+ def preauthenticate; end
596
+
597
+ # Sets media type. Will choose either application/occi+json or text/plain
598
+ # based on the formats supported by the server.
599
+ #
600
+ # @example
601
+ # set_media_type # => 'application/occi+json'
602
+ #
603
+ # @return [String] chosen media type
604
+ def set_media_type(force_type = nil); end
605
+
606
+ # Sets the logger and log levels. This allows users to pass existing logger
607
+ # instances to the rOCCI client.
608
+ #
609
+ # @example
610
+ # set_logger { :out => STDERR, :level => Occi::Log::WARN, :logger => nil }
611
+ #
612
+ # @param [Hash] logger options
613
+ def set_logger(log_options)
614
+ if log_options[:logger].nil? || (not log_options[:logger].kind_of? Occi::Log)
615
+ @logger = Occi::Log.new(log_options[:out])
616
+ @logger.level = log_options[:level]
617
+ end
618
+ end
619
+
620
+ # Checks whether the given endpoint URI is valid and adds a trailing
621
+ # slash if necessary.
622
+ #
623
+ # @example
624
+ # set_endpoint "http://localhost:3300" # => "http://localhost:3300/"
625
+ #
626
+ # @param [String] endpoint URI in a non-canonical string
627
+ # @return [String] canonical endpoint URI in a string, with a trailing slash
628
+ def set_endpoint(endpoint)
629
+ raise 'Endpoint not a valid URI' if (endpoint =~ URI::ABS_URI).nil?
630
+ @endpoint = endpoint.chomp('/') + '/'
631
+ end
632
+
633
+ # Creates an Occi::Model from data retrieved from the server.
634
+ #
635
+ # @example
636
+ # model = get('/-/')
637
+ # set_model model # => #<Occi::Model>
638
+ #
639
+ # @param [Occi::Collection] parsed representation of server's model
640
+ # @return [Occi::Model] Model instance
641
+ def set_model(model)
642
+ # build model
643
+ @model = Occi::Model.new(model)
644
+
645
+ @mixins = {
646
+ :os_tpl => get_os_tpl_mixins_ary,
647
+ :resource_tpl => get_res_tpl_mixins_ary
648
+ }
649
+
650
+ @model
651
+ end
652
+
653
+ #
654
+ #
655
+ #
656
+ def get_os_tpl_mixins_ary
657
+ os_tpls = []
658
+
659
+ get_os_templates.each do |os_tpl|
660
+ unless os_tpl.nil? || os_tpl.type_identifier.nil?
661
+ tid = os_tpl.type_identifier.strip
662
+ os_tpls << tid unless tid.empty?
663
+ end
664
+ end
665
+
666
+ os_tpls
667
+ end
668
+
669
+ #
670
+ #
671
+ #
672
+ def get_res_tpl_mixins_ary
673
+ res_tpls = []
674
+
675
+ get_resource_templates.each do |res_tpl|
676
+ unless res_tpl.nil? || res_tpl.type_identifier.nil?
677
+ tid = res_tpl.type_identifier.strip
678
+ res_tpls << tid unless tid.empty?
679
+ end
680
+ end
681
+
682
+ res_tpls
683
+ end
684
+
685
+ end
686
+
687
+ end
688
+ end
689
+ end