lorj 1.0.9 → 1.0.10

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/example/students_1/process/students.rb +1 -1
  4. data/example/students_1/student_v1.md +2 -0
  5. data/example/students_1/students.rb +2 -1
  6. data/example/students_2/process/students.rb +1 -1
  7. data/example/students_2/students.rb +4 -2
  8. data/example/students_3/controller/yaml_students_def.rb +1 -1
  9. data/example/students_3/process/students.rb +1 -1
  10. data/example/students_3/student_v3.md +5 -3
  11. data/example/students_3/students.rb +5 -3
  12. data/example/students_4/controller/yaml_students_def.rb +1 -1
  13. data/example/students_4/process/students/definition/students.rb +1 -1
  14. data/example/students_4/students.rb +5 -3
  15. data/example/students_5/controller/yaml_students.rb +1 -1
  16. data/example/students_5/process/students.rb +1 -1
  17. data/example/students_5/student_v5.md +4 -4
  18. data/example/students_5/students.rb +8 -7
  19. data/example/yaml_students/students.rb +4 -4
  20. data/lib/core/core.rb +110 -64
  21. data/lib/core/core_internal.rb +110 -15
  22. data/lib/core/core_object_data.rb +4 -4
  23. data/lib/core/core_process_setup.rb +3 -30
  24. data/lib/core/lorj_data.rb +1 -1
  25. data/lib/core/lorj_keypath.rb +3 -1
  26. data/lib/core/process.rb +67 -0
  27. data/lib/lorj/version.rb +2 -1
  28. data/lib/lorj.rb +3 -4
  29. data/lib/lorj_account.rb +6 -5
  30. data/lib/lorj_config.rb +3 -2
  31. data/lib/providers/templates/compute.rb +1 -1
  32. data/lorj-spec/controllers/mock/mock.rb +144 -0
  33. data/lorj-spec/data.yaml +0 -0
  34. data/lorj-spec/process/mock2_process.rb +48 -0
  35. data/lorj-spec/process/mock_process.rb +48 -0
  36. data/lorj-spec/providers/mock2/mock2.rb +0 -0
  37. data/lorj.gemspec +2 -4
  38. data/spec/05_lorj_keypath_spec.rb +78 -0
  39. data/spec/20_lorj_meta_spec.rb +1 -1
  40. data/spec/21_lorj_processes_spec.rb +115 -0
  41. metadata +27 -42
  42. data/lib/core_process/cloud/process/common.rb +0 -60
  43. data/lib/core_process/cloud/process/connection.rb +0 -92
  44. data/lib/core_process/cloud/process/external_network.rb +0 -90
  45. data/lib/core_process/cloud/process/flavor.rb +0 -97
  46. data/lib/core_process/cloud/process/images.rb +0 -99
  47. data/lib/core_process/cloud/process/internet_network.rb +0 -33
  48. data/lib/core_process/cloud/process/internet_server.rb +0 -29
  49. data/lib/core_process/cloud/process/keypairs.rb +0 -332
  50. data/lib/core_process/cloud/process/network.rb +0 -107
  51. data/lib/core_process/cloud/process/public_ip.rb +0 -102
  52. data/lib/core_process/cloud/process/router.rb +0 -267
  53. data/lib/core_process/cloud/process/rules.rb +0 -120
  54. data/lib/core_process/cloud/process/security_groups.rb +0 -120
  55. data/lib/core_process/cloud/process/server.rb +0 -126
  56. data/lib/core_process/cloud/process/server_log.rb +0 -34
  57. data/lib/core_process/cloud/process/subnetwork.rb +0 -96
  58. data/lib/core_process/cloud_process.rb +0 -30
  59. data/lib/prc_base_config.rb +0 -300
  60. data/lib/prc_core_config.rb +0 -1258
  61. data/lib/prc_section_config.rb +0 -90
  62. data/lib/providers/hpcloud/compute.rb +0 -105
  63. data/lib/providers/hpcloud/hpcloud.rb +0 -462
  64. data/lib/providers/hpcloud/network.rb +0 -115
  65. data/lib/providers/hpcloud/security_groups.rb +0 -68
  66. data/lib/providers/openstack/openstack.rb +0 -410
  67. data/lib/providers/openstack/openstack_create.rb +0 -205
  68. data/lib/providers/openstack/openstack_delete.rb +0 -28
  69. data/lib/providers/openstack/openstack_get.rb +0 -39
  70. data/lib/providers/openstack/openstack_process.rb +0 -26
  71. data/lib/providers/openstack/openstack_query.rb +0 -96
  72. data/lib/providers/openstack/openstack_update.rb +0 -35
  73. data/lib/rh.rb +0 -426
  74. data/spec/01_hash_rh_spec.rb +0 -282
  75. data/spec/02_prc_base_config_spec.rb +0 -227
  76. data/spec/03_prc_section_config_spec.rb +0 -196
  77. data/spec/04_prc_core_config_spec.rb +0 -325
@@ -1,1258 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- # (c) Copyright 2014 Hewlett-Packard Development Company, L.P.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License");
6
- # you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS,
13
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- # See the License for the specific language governing permissions and
15
- # limitations under the License.
16
-
17
- require 'yaml'
18
-
19
- module PRC
20
- # Internal CoreConfig functions
21
- class CoreConfig
22
- private
23
-
24
- # Function to initialize a predefined layer
25
- # Used internally by initialize_layers.
26
- def _initialize_layer(layer)
27
- newlayer = { :config => layer[:config], :name => layer[:name] }
28
- newlayer[:set] = layer[:set].boolean? ? layer[:set] : true
29
- newlayer[:load] = layer[:load].boolean? ? layer[:load] : false
30
- newlayer[:save] = layer[:save].boolean? ? layer[:save] : false
31
- newlayer[:file_set] = layer[:file_set].boolean? ? layer[:file_set] : false
32
- newlayer[:init] = true
33
- newlayer
34
- end
35
-
36
- # Check and returns values of options required and optionnal.
37
- #
38
- # * *Args*
39
- # - +options+ : options to extract information.
40
- # - +required+ : Array of required option keys.
41
- # - +optionnal+ : Array of optionnal option keys.
42
- #
43
- # * *Returns*
44
- # - nil if at least one required keys doesn't exist
45
- # - Array of combined required and optionnql values.
46
- #
47
- def _valid_options(options, required, optionnal = [])
48
- return nil unless options.is_a?(Hash)
49
- return nil unless required.is_a?(Array)
50
- optionnal = [] unless optionnal.is_a?(Array)
51
-
52
- result = [[], []]
53
-
54
- required.each do |key|
55
- return nil unless options.key?(key)
56
- result[0] << options[key]
57
- end
58
-
59
- optionnal.each { |key| result[1] << options[key] }
60
-
61
- result
62
- end
63
-
64
- # Internal function to call _common_options_get
65
- # It ensures and cleanup caller setting
66
- # :names and :indexes as those must be single values instead of
67
- # array. ie :name and :index is the only one supported.
68
- #
69
- def _nameindex_common_options_get(options, required = [], optionnal = [])
70
- options = {} if options.nil?
71
-
72
- # ensure :names or :indexes are not set. and clean it up if exists
73
- options.delete(:names) if options.key?(:names)
74
- options.delete(:indexes) if options.key?(:indexes)
75
-
76
- _common_options_get(options, required, optionnal)
77
- end
78
-
79
- # Take care of keys, indexes, names, index and name.
80
- # If names is found, it will replace indexes.
81
- # If name is found, it will replace index.
82
- # If index is found, it will replace indexes.
83
- def _common_options_get(options, required = [], optionnal = [])
84
- return nil unless options.is_a?(Hash)
85
- required = [] unless required.is_a?(Array)
86
- optionnal = [] unless optionnal.is_a?(Array)
87
-
88
- _convert_nameindex_to_arrays(options)
89
-
90
- result = _valid_options(options, required,
91
- [:indexes, :names,
92
- :data_options].concat(optionnal))
93
- return nil if result.nil?
94
- # result Array is structured as:
95
- # required [0] => [...]
96
- # optional [1] => [indexes, names, data_options, ...]
97
-
98
- # Following eliminates the optional :names (1) element
99
- _set_indexes result
100
- # required [0] => [...]
101
- # optional [1] => [indexes, data_options, ...]
102
- return nil if _keys_data_missing(options, required, result)
103
-
104
- # Following eliminates the optional :indexes (0) element
105
- # But add it as required in the Array, at pos 0
106
- _build_layers(result)
107
- # required [0] => [layers, ...]
108
- # optional [1] => [data_options, ...]
109
-
110
- # following eliminates the optional :data_options (0) element
111
- # But data_options is added in required Array, at pos 1.
112
- _set_data_opts(result)
113
- # required [0] => [layers, data_options, ...]
114
- # optional [1] => [...]
115
-
116
- result
117
- end
118
-
119
- # This internal function identify :name and :index
120
- # To replace to respectively to :names and :indexes
121
- def _convert_nameindex_to_arrays(options)
122
- options[:names] = [options.delete(:name)] if options.key?(:name)
123
- options[:indexes] = [options.delete(:index)] if options.key?(:index)
124
- end
125
-
126
- # This internal function checks if the :keys is required, then
127
- # The keys value HAVE to be an Array with at least one element.
128
- # It returns false, if :keys is not the first required field
129
- # or if the keys data (Array not empty) is confirmed.
130
- def _keys_data_missing(options, required, result)
131
- return false unless required[0] == :keys
132
-
133
- return true unless options.key?(:keys)
134
- return true unless result[0][0].is_a?(Array)
135
- return true if result[0][0].length == 0
136
- false
137
- end
138
-
139
- # Setting indexes from names or indexes.
140
- def _set_indexes(result)
141
- names_indexes = layer_indexes(result[1][1])
142
- # replaced indexes by names indexes if exists.
143
- result[1][0] = names_indexes if names_indexes
144
- result[1].delete_at(1)
145
- end
146
-
147
- def _set_data_opts(result)
148
- data_opts = []
149
-
150
- result[0][0].each_index do |layer_index|
151
- data_options = result[1][0][layer_index] if result[1][0].is_a?(Array)
152
- data_options = {} unless data_options.is_a?(Hash)
153
- data_opts << data_options
154
- end
155
- result[0].insert(1, data_opts)
156
-
157
- # And removing the optionnal :data_options
158
- result[1].delete_at(0)
159
- end
160
-
161
- def _build_layers(result)
162
- # Setting layers at required [0]
163
- if result[1][0].nil? || result[1][0].length == 0
164
- config_layers = @config_layers
165
- else
166
- config_layers = []
167
- result[1][0].each do |index|
168
- config_layers << @config_layers[index] if index.is_a?(Fixnum)
169
- end
170
- config_layers = @config_layers if config_layers.length == 0
171
- end
172
- result[0].insert(0, config_layers)
173
-
174
- # And removing the optionnal indexes
175
- result[1].delete_at(0)
176
- result
177
- end
178
-
179
- # Internal function to provide a result for #p_get.
180
- # This function is typically used by a Child Class.
181
- #
182
- # * *Args*
183
- # - +*keys+ : Array of keys.
184
- # - +layers+ : Array of config layers to get data to merge.
185
- # - +data_opts+ : Array of data options per layers
186
- # - +data_options+ : common data options for all layers
187
- # - +merge+ : True if need to get a merge result.
188
- #
189
- # * *Returns*
190
- # - Value, Hash merged or nil.
191
- #
192
- def _get_from_layers(keys, layers, data_opts, data_options, merge)
193
- result = nil
194
-
195
- # In merge case, we need to build from bottom to top
196
- if merge.is_a?(TrueClass)
197
- layers = layers.reverse
198
- data_opts = data_opts.reverse
199
- end
200
-
201
- layers.each_index do |layer_index|
202
- layer = layers[layer_index]
203
-
204
- data_options = data_options.merge(data_opts[layer_index])
205
-
206
- layer[:config].data_options(data_options)
207
-
208
- next unless layer[:config].exist?(*keys)
209
-
210
- return layer[:config][*keys] unless merge.is_a?(TrueClass)
211
-
212
- result = _get_build_merge(result, layer[:config][*keys])
213
- end
214
- result
215
- end
216
-
217
- # Return true if at least the first key value found is of type Hash/Array,
218
- # while be_exclusive is false
219
- # return true if at least one key value is NOT Hash or Array,
220
- # while be_exclusive is true
221
- #
222
- def _check_from_layers(keys, config_layers, data_opts, data_options,
223
- be_exclusive)
224
- found = false
225
- found_class = nil
226
- config_layers.each_index do |layer_index|
227
- layer = config_layers[layer_index]
228
-
229
- data_options = data_options.merge(data_opts[layer_index])
230
-
231
- layer[:config].data_options(data_options)
232
-
233
- next unless layer[:config].exist?(*keys)
234
-
235
- found_class = layer[:config][*keys].class
236
- found = [Hash, Array].include?(found_class)
237
- if be_exclusive
238
- return false unless found
239
- unless found_class && layer[:config][*keys].is_a?(found_class)
240
- return false
241
- end
242
- else
243
- return found
244
- end
245
- end
246
- true
247
- end
248
-
249
- # Internal function to provide a merge result for #_get_from_layers
250
- #
251
- # * *Args*
252
- # - +result+ : Cumulative Hash merged
253
- # - +data+ : data to merge
254
- #
255
- # * *Returns*
256
- # - Cloned Hash merged or simple data updated if possible.
257
- #
258
- def _get_build_merge(result, data)
259
- if [Hash, Array].include?(data.class) &&
260
- [Hash, Array].include?(result.class) && result.is_a?(data.class)
261
- return _do_merge(result, data)
262
- end
263
- _choose_data(result, data)
264
- end
265
-
266
- def _choose_data(result, data)
267
- if result.nil?
268
- return data.rh_clone if [Hash, Array].include?(data.class)
269
- return data
270
- end
271
-
272
- # return result as first one impose the type between Hash/Array.
273
- return result if [Hash, Array].include?(result.class) ||
274
- [Hash, Array].include?(data.class)
275
-
276
- data
277
- end
278
-
279
- # Internal function to do the merge result for #_get_build_merge
280
- #
281
- # * *Args*
282
- # - +result+ : Cumulative Hash merged
283
- # - +data+ : data to merge
284
- #
285
- # * *Returns*
286
- # - Cloned Hash merged.
287
- #
288
- def _do_merge(result, data)
289
- # data and result are of same type. Merge is possible.
290
- return result.merge!(data.rh_clone) if result.is_a?(Hash)
291
-
292
- result.each_index do |index|
293
- result[index] = _get_build_merge(result[index], data[index])
294
- end
295
- result
296
- end
297
- end
298
-
299
- # Internal core functions
300
- class CoreConfig
301
- # *****************************************************
302
-
303
- private
304
-
305
- # Del function called by default by del
306
- # This function is typically used by a Child Class.
307
- #
308
- # * *Args*
309
- # - +options+ : Hash of how to get the data
310
- # - +:keys+ : Array of key path to found
311
- # - +:name+ : layer to get data.
312
- # - +:index+ : layer index to get data.
313
- # If neither :name or :index is set, set will use the
314
- # highest layer
315
- # - +:data_opts+ : Array or Hash. Define data options per layer.
316
- #
317
- # * *Returns*
318
- # - The value attached to the key deleted.
319
- # OR
320
- # - nil can be returned for several reasons:
321
- # - value is nil
322
- # - keys is not an array
323
- # - keys array is empty.
324
- #
325
- # ex:
326
- # value = CoreConfig.New
327
- #
328
- # value[:level1, :level2] = 'value'
329
- # # => {:level1 => {:level2 => 'value'}}
330
- #
331
- # value.del(:keys => [:level1, :level2])
332
- # # => {:level1 => {}}
333
- def p_del(options) #:doc:
334
- parameters = _nameindex_common_options_get(options, [:keys])
335
- return nil if parameters.nil?
336
-
337
- config_layers, data_opts, keys = parameters[0]
338
-
339
- # get data options for level 0
340
- data_options = options.clone.merge!(data_opts[0])
341
-
342
- return nil if keys.length == 0
343
-
344
- data_options.delete_if do |key|
345
- [:keys, :names, :indexes, :name, :index].include?(key)
346
- end
347
-
348
- return nil unless @config_layers[0][:set]
349
-
350
- config_layers[0][:config].data_options(data_options)
351
- config_layers[0][:config].del(keys)
352
- end
353
-
354
- # p_file? Core file function called by default by #file.
355
- # This function is typically used by a Child Class.
356
- #
357
- # This function can be used by child class to set one layer file name
358
- #
359
- # * *Args*
360
- # - +options+ : Hash parameters
361
- # - +:name+ : layer to get data.
362
- # - +:index+ : Array layer indexes to get data.
363
- # If neither :name or :index is set, level 0 is used.
364
- #
365
- # * *Returns*
366
- # - filename : if updated.
367
- # OR
368
- # - false : if not updated.
369
- # OR
370
- # - nil : If something went wrong.
371
- #
372
- # ex:
373
- # { :test => {:titi => 'found'}}
374
- def p_file(filename = nil, options = {}) #:doc:
375
- parameters = _nameindex_common_options_get(options)
376
-
377
- return nil if parameters.nil?
378
-
379
- config_layers = parameters[0][0]
380
-
381
- layer = config_layers[0]
382
-
383
- return layer[:config].filename unless filename.is_a?(String)
384
-
385
- return false if _filename_unsetable(layer)
386
-
387
- layer[:config].filename = filename
388
- filename
389
- end
390
-
391
- def _filename_unsetable(layer)
392
- return true if !layer[:load] && !layer[:save]
393
-
394
- !layer[:config].filename.nil? && !layer[:file_set]
395
- end
396
-
397
- # p_exist? Core exist function called by default by #exist?.
398
- # This function is typically used by a Child Class.
399
- #
400
- # * *Args*
401
- # - +options+ : Hash parameters
402
- # - +:keys+ : key tree to check existence in config layers
403
- # - +:names+ : layer to get data.
404
- # - +:indexes+ : Array layer indexes to get data.
405
- # If neither :name or :index is set, get will search data
406
- # per layers priority.
407
- # - +:data_opts+ : Array or Hash. Define data options per layer.
408
- #
409
- # * *Returns*
410
- # - boolean : true if the key path was found
411
- #
412
- # ex:
413
- # # if one layer data is { :test => {:titi => 'found'}}
414
- # p_exist?(:keys => [:test]) # => true
415
- # p_exist?(:keys => [:test, :titi]) # => true
416
- # p_exist?(:keys => [:test1]) # => false
417
- #
418
- def p_exist?(options) #:doc:
419
- parameters = _common_options_get(options, [:keys])
420
- return nil if parameters.nil?
421
-
422
- config_layers, data_opts, keys = parameters[0]
423
-
424
- return nil if keys.length == 0 || keys[0].nil? || config_layers[0].nil?
425
-
426
- config_layers.each_index do |index|
427
- config = config_layers[index][:config]
428
-
429
- data_options = options.clone
430
- data_options.delete_if do |key|
431
- [:keys, :names, :indexes, :name, :index].include?(key)
432
- end
433
- data_options.merge!(data_opts[index])
434
-
435
- config.data_options(data_options)
436
- return true if config.exist?(*keys)
437
- end
438
- false
439
- end
440
-
441
- # p_where? called by default by #where
442
- # This function is typically used by a Child Class.
443
- #
444
- # * *args*
445
- # - +options+ : Hash parameters
446
- # - +:keys+ : key tree to check existence in config layers
447
- # - +:names+ : layer to get data.
448
- # - +:indexes+ : Array layer indexes to get data.
449
- # If neither :name or :index is set, get will search data
450
- # per layers priority.
451
- # - +:data_opts+ : Array or Hash. Define data options per layer.
452
- #
453
- # * *Returns*
454
- # - array of config name : list of first layers where the key was found.
455
- # OR
456
- # - nil can be returned for several reasons:
457
- # - keys is not an array
458
- # - keys array is empty.
459
- def p_where?(options) #:doc:
460
- parameters = _common_options_get(options, [:keys])
461
- return nil if parameters.nil?
462
-
463
- config_layers, data_opts, keys = parameters[0]
464
-
465
- return nil if keys.length == 0 || keys[0].nil? || config_layers[0].nil?
466
-
467
- _do_where?(config_layers, keys, options, data_opts)
468
- end
469
-
470
- def _do_where?(config_layers, keys, options, data_opts)
471
- layer_indexes = []
472
- config_layers.each_index do |index|
473
- config = config_layers[index][:config]
474
-
475
- data_options = options.clone
476
- data_options.delete_if do |key|
477
- [:keys, :names, :indexes, :name, :index].include?(key)
478
- end
479
- data_options.merge!(data_opts[index]) if data_opts[index].is_a?(Hash)
480
-
481
- config.data_options(data_options)
482
- layer_indexes << config_layers[index][:name] if config.exist?(keys)
483
- end
484
- return layer_indexes if layer_indexes.length > 0
485
- false
486
- end
487
-
488
- # Get function called by default by #[]
489
- # This function is typically used by a Child Class.
490
- #
491
- # * *Args*
492
- # - +options+ : Hash of how to get the data
493
- # - +:keys+ : Array of key path to found
494
- # - +:names+ : layer to get data.
495
- # - +:indexes+ : Array layer indexes to get data.
496
- # If neither :name or :index is set, get will search data
497
- # per layers priority.
498
- # - +:data_opts+ : Array or Hash. Define data options per layer.
499
- # - +:merge+ : Provide a Merged result instead of first found
500
- # returned.
501
- # The merge result depends on deep layer data type found.
502
- #
503
- # Ex:
504
- #
505
- # with 2 config layers, like 'top' and 'bottom', usually a get will
506
- # search in 'top', then 'bottom'. Merge will search in 'bottom'
507
- # first. Then:
508
- # - if 'bottom' value found is of type Hash(or Array),
509
- # p_get will return a Hash(or Array), merged accross upper layers
510
- # So, if 'top' is Hash(or Array), the result is the merge Hash
511
- # (or Array). Otherwise, the 'top' will be ignored.
512
- # - if 'bottom' value found is any kind of other types
513
- # p_get won't merge, but get the highest non Array/Hash data found
514
- # . So with a 'bottom' data of String, and 'top' as 'Fixnum', the
515
- # result will be Fixnum. If there is any Hash/Array in between, it
516
- # will be ignored.
517
- #
518
- # * *Returns*
519
- # value found (or Hash merged) or nil.
520
- #
521
- # nil can be returned for several reasons:
522
- # - keys is not an array
523
- # - keys array is empty.
524
- #
525
- def p_get(options) #:doc:
526
- parameters = _common_options_get(options, [:keys], [:merge])
527
- return nil if parameters.nil?
528
-
529
- # Required options : parameters[0]
530
- config_layers, data_opts, keys = parameters[0]
531
- # Optional options : parameters[1]
532
- merge = parameters[1][0]
533
-
534
- return nil if keys.length == 0 || keys[0].nil? || config_layers[0].nil?
535
-
536
- data_options = options.clone
537
- data_options.delete_if do |key|
538
- [:keys, :names, :indexes, :name, :index, :merge].include?(key)
539
- end
540
-
541
- _get_from_layers(keys,
542
- config_layers, data_opts, data_options,
543
- merge)
544
- end
545
-
546
- # Set function called by default by #[]=
547
- # This function is typically used by a Child Class.
548
- #
549
- # * *Args*
550
- # - +options+ : Hash of how to get the data
551
- # - +:value+: Value to set
552
- # - +:keys+ : Array of key path to found
553
- # - +:name+ : layer to get data.
554
- # - +:index+: layer index to get data.
555
- # If neither :name or :index is set, set will use the highest layer.
556
- # - +:data_opts+ : Array or Hash. Define data options per layer.
557
- #
558
- # * *Returns*
559
- # - The value set.
560
- # OR
561
- # - nil can be returned for several reasons:
562
- # - layer options :set is false
563
- # - options defines a :data_readonly to true.
564
- # - value is nil
565
- # - keys is not an array
566
- # - keys array is empty.
567
- #
568
- # ex:
569
- # value = CoreConfig.New
570
- #
571
- # value[:level1, :level2] = 'value'
572
- # # => {:level1 => {:level2 => 'value'}}
573
- def p_set(options) #:doc:
574
- parameters = _nameindex_common_options_get(options, [:keys, :value])
575
- return nil if parameters.nil?
576
-
577
- config_layers, data_opts, keys, value = parameters[0]
578
-
579
- # get data options for level 0
580
- data_options = options.clone.merge!(data_opts[0])
581
-
582
- return nil if keys.length == 0 || keys[0].nil? || config_layers[0].nil?
583
-
584
- data_options.delete_if do |key|
585
- [:keys, :names, :indexes, :name, :index, :value].include?(key)
586
- end
587
-
588
- return nil unless config_layers[0][:set]
589
-
590
- config_layer = config_layers[0][:config]
591
- config_layer.data_options(data_options)
592
- config_layer[keys] = value
593
- end
594
-
595
- # Load from a file called by default by load.
596
- # This function is typically used by a Child Class.
597
- #
598
- # * *Args* :
599
- # - +options+ : Supported options for load
600
- # - +:name+ : layer name to get data.
601
- # - +:index+ : layer index to get data.
602
- # If neither :name or :index is set, set will use the highest layer.
603
- #
604
- # * *Returns* :
605
- # - true : loaded
606
- # - false: not loaded. There are several possible reasons:
607
- # - input/output issue (normally raised)
608
- # - layer option :load is false.
609
- def p_load(options = {}) #:doc:
610
- options = {} if options.nil?
611
- options[:names] = [options[:name]] if options.key?(:name)
612
- options[:indexes] = [options[:index]] if options.key?(:index)
613
-
614
- parameters = _nameindex_common_options_get(options)
615
- return nil if parameters.nil?
616
-
617
- config_layers = parameters[0][0]
618
-
619
- return nil unless config_layers[0][:load]
620
-
621
- config_layers[0][:config].load
622
- end
623
-
624
- # Save to a file called by default by save
625
- # This function is typically used by a Child Class.
626
- #
627
- # * *Args* :
628
- # - +options+ : Supported options for save
629
- # - +:name+ : layer to get data.
630
- # - +:index+: layer index to get data.
631
- # If neither :name or :index is set, set will use the highest layer
632
- #
633
- # * *Returns* :
634
- # - true : saved
635
- # - false: not saved. There are several possible reasons:
636
- # - options defines a :file_readonly to true.
637
- # - input/output issue (normally raised)
638
- # - layer option :save is false.
639
- def p_save(options = {}) #:doc:
640
- options[:names] = [options[:name]] if options.key?(:name)
641
- options[:indexes] = [options[:index]] if options.key?(:index)
642
-
643
- parameters = _nameindex_common_options_get(options)
644
- return nil if parameters.nil?
645
-
646
- config_layers = parameters[0][0]
647
-
648
- return nil unless config_layers[0][:save]
649
-
650
- config_layers[0][:config].save
651
- end
652
- end
653
-
654
- # private functions usable by child classes
655
- class CoreConfig
656
- # initialize CoreConfig
657
- #
658
- # * *Args*
659
- # - +config_layers+ : Array config layers configuration.
660
- # Each layer options have those options:
661
- # - :config : optional. See `Defining Config layer instance` for
662
- # details
663
- # - :name : required. String. Name of the config layer.
664
- # Warning! unique name on layers is no tested.
665
- # - :set : boolean. True if authorized. Default is True.
666
- # - :load : boolean. True if authorized. Default is False.
667
- # - :save : boolean. True if authorized. Default is False.
668
- # - :file_set : boolean. True if authorized to update a filename.
669
- # Default is False.
670
- #
671
- # each layers can defines some options for the layer to behave differently
672
- # CoreConfig call a layer data_options to set some options, before
673
- # exist?, get or [], set or []=, save and load functions.
674
- # See BaseConfig::data_options for predefined options.
675
- #
676
- # Core config provides some private additionnal functions for
677
- # child class functions:
678
- # - #_set_data_options(layers, options) - To set data_options on one or
679
- # more config layers
680
- # - #p_get(options) - core get function
681
- # - #p_set(options) - core set function
682
- # - #p_save(options) core save function
683
- # - #p_load(options) - core load function
684
- #
685
- # if +config_layers+ is not provided, CoreConfig will instanciate a runtime
686
- # like system:
687
- #
688
- # config = CoreConfig.New
689
- # # is equivalent to :
690
- # config_layers = [{name: 'runtime',
691
- # config: PRC::BaseConfig.new, set: true}]
692
- # config = CoreConfig.New(config_layers)
693
- #
694
- # = Defining Config layer instance:
695
- #
696
- # :config value requires it to be of type 'BaseConfig'
697
- # By default, it uses `:config => PRC::BaseConfig.new`
698
- # Instead, you can set:
699
- # * directly BaseConfig. `:config => PRC::BaseConfig.new`
700
- # * a child based on BaseConfig. `:config => MyConfig.new`
701
- # * some predefined enhanced BaseConfig:
702
- # * PRC::SectionConfig. See prc_section_config.rb.
703
- # `:config => PRC::SectionConfig.new`
704
- #
705
- def initialize(config_layers = nil)
706
- if config_layers.nil?
707
- config_layers = []
708
- config_layers << CoreConfig.define_layer
709
- end
710
- initialize_layers(config_layers)
711
- end
712
-
713
- # This function add a config layer at runtime.
714
- # The new layer added at runtime, can be removed at runtime
715
- # with layer_remove
716
- # The name MUST be different than other existing config layer names
717
- #
718
- # *Args*
719
- # - +options+ : Hash data
720
- # - :name : Required. Name of the layer to add
721
- # - :index : Config position to use. 0 is the default. 0 is the first
722
- # Config layer use by get.
723
- # - :config : A Config instance of class type PRC::BaseConfig
724
- # - :set : Boolean. True if is authorized to set a variable.
725
- # - :load : Boolean. True if is authorized to load from a file.
726
- # - :save : Boolean. True if is authorized to save to a file.
727
- # - :file_set : Boolean. True if is authorized to change the file name.
728
- #
729
- # *returns*
730
- # - true if layer is added.
731
- # OR
732
- # - nil : if layer name already exist
733
- def layer_add(options)
734
- layer = CoreConfig.define_layer(options)
735
-
736
- layer[:init] = false # Runtime layer
737
-
738
- index = 0
739
- index = options[:index] if options[:index].is_a?(Fixnum)
740
- names = []
741
- @config_layers.each { |alayer| names << alayer[:name] }
742
-
743
- return nil if names.include?(layer[:name])
744
- @config_layers.insert(index, layer)
745
- true
746
- end
747
-
748
- # Function to remove a runtime layer.
749
- # You cannot remove a predefined layer, created during CoreConfig
750
- # instanciation.
751
- # *Args*
752
- # - +options+ : Hash data
753
- # - +:name+ : Name of the layer to remove.
754
- # - +:index+: Index of the layer to remove.
755
- #
756
- # At least, :name or :index is required.
757
- # If both; :name and :index are set, :name is used.
758
- # *return*
759
- # - true if layer name is removed.
760
- # OR
761
- # - nil : if not found or invalid.
762
- def layer_remove(options)
763
- index = layer_index(options[:name])
764
- index = options[:index] if index.nil?
765
-
766
- return nil if index.nil?
767
-
768
- layer = @config_layers[index]
769
-
770
- return nil if layer.nil? || layer[:init]
771
-
772
- @config_layers.delete_at(index)
773
- true
774
- end
775
-
776
- # Function to define layer options.
777
- # By default, :set is true and :config is attached to a new PRC::BaseConfig
778
- # instance.
779
- #
780
- # Supported options:
781
- # - :config : optional. See `Defining Config layer instance` for details
782
- # - :name : required. String. Name of the config layer.
783
- # Warning! unique name on layers is no tested.
784
- # - :set : boolean. True if authorized. Default is True.
785
- # - :load : boolean. True if authorized. Default is False.
786
- # - :save : boolean. True if authorized. Default is False.
787
- # - :file_set : boolean. True if authorized to update a filename.
788
- # Default is False.
789
- def self.define_layer(options = {})
790
- attributes = [:name, :config, :set, :load, :save, :file_set]
791
-
792
- layer = {}
793
-
794
- attributes.each do |attribute|
795
- if options.key?(attribute)
796
- layer[attribute] = options[attribute]
797
- else
798
- layer[attribute] = case attribute
799
- when :name
800
- 'runtime'
801
- when :config
802
- PRC::BaseConfig.new
803
- when :set
804
- true
805
- else
806
- false
807
- end
808
- end
809
- end
810
- layer
811
- end
812
-
813
- # layer_indexes function
814
- #
815
- # * *Args*
816
- # - +:name+ : layer to identify.
817
- #
818
- # * *Returns*
819
- # first index found or nil.
820
- #
821
- def layer_indexes(names)
822
- names = [names] if names.is_a?(String)
823
- return nil unless names.is_a?(Array)
824
-
825
- layers = []
826
-
827
- names.each do |name|
828
- index = layer_index(name)
829
- layers << index unless index.nil?
830
- end
831
- return layers if layers.length > 0
832
- nil
833
- end
834
-
835
- # layer_index function
836
- #
837
- # * *Args*
838
- # - +:name+ : layer to identify.
839
- #
840
- # * *Returns*
841
- # first index found or nil.
842
- #
843
- def layer_index(name)
844
- return nil unless name.is_a?(String)
845
- return nil if @config_layers.nil?
846
-
847
- @config_layers.each_index do |index|
848
- return index if @config_layers[index][:name] == name
849
- end
850
- nil
851
- end
852
-
853
- private
854
-
855
- # Function to initialize Config layers.
856
- # This function is typically used by a Child Class.
857
- #
858
- # * *Args*
859
- # - +config_layers+ : Array of config layers.
860
- # First layer is the deepest config object.
861
- # Last layer is the first config object queried.
862
- #
863
- # Ex: If we define 2 config layers:
864
- #
865
- # class Test << PRC::CoreConfig
866
- # def initialize
867
- # local = PRC::BaseConfig.new(:test => :found_local)
868
- # runtime = PRC::BaseConfig.new(:test => :found_runtime)
869
- # layers = []
870
- # layers << PRC::CoreConfig.define_layer(name: 'local',
871
- # config: local )
872
- # layers << PRC::CoreConfig.define_layer(name: 'runtime',
873
- # config: runtime )
874
- # initialize_layers(layers)
875
- # end
876
- # end
877
- #
878
- # config = Test.new
879
- #
880
- # p config[:test] # => :found_runtime
881
- #
882
- # config[:test] = "where?"
883
- # p config.where?(:test) # => ["runtime", "local"]
884
- #
885
- # config.del(:test)
886
- # p config.where?(:test) # => ["local"]
887
- # p config[:test] # => :found_local
888
- #
889
- # config[:test] = "and now?"
890
- # p config.where?(:test) # => ["runtime", "local"]
891
- #
892
- def initialize_layers(config_layers = nil) #:doc:
893
- @config_layers = []
894
-
895
- config_layers.each do |layer|
896
- next unless layer.is_a?(Hash) && layer.key?(:config) &&
897
- layer[:config].is_a?(BaseConfig)
898
- next unless layer[:name].is_a?(String)
899
- @config_layers << _initialize_layer(layer)
900
- end
901
- @config_layers.reverse!
902
- end
903
- end
904
-
905
- # This class implement The CoreConfig system of lorj.
906
- #
907
- # * You can use it directly. See ::new.
908
- # * you can enhance it with class heritage feature.
909
- # See Class child discussion later in this class documentation.
910
- #
911
- # = Public functions implemented:
912
- #
913
- # It implements several layer of CoreConfig object type
914
- # to provide several source of data in layers priorities.
915
- # Ex: RunTime => LocalConfig => AppDefault
916
- #
917
- # It implements config features:
918
- # * #[] - To get a value for a key or tree of keys
919
- # * #[]= - To set a Config value in the highest config.
920
- # * #del - To delete key or simply nil the value in highest config.
921
- # * #exist? - To check the existence of a value in config levels.
922
- # * #where? - To get the name of the level where the value was found.
923
- # * #file - To get or set a filename to a config layer.
924
- # * #save - To save one config data level in a yaml file.
925
- # * #load - To load data from a yaml file to a config data layer.
926
- # * #merge - To merge several layers data values. Values must be Hash.
927
- #
928
- # When the instance is initialized, it defines 3 Config layers (BaseConfig).
929
- #
930
- # If you need to define layers differently, consider to create your child
931
- # class. You will be able to use SectionConfig or even any BaseConfig Child
932
- # class as well.
933
- #
934
- # For details about a Config layers, See BaseConfig or SectionConfig.
935
- #
936
- # = Child Class implementation:
937
- #
938
- # This class can be enhanced with any kind of additional functionality.
939
- #
940
- # You can redefine following functions
941
- # exist?, [], []=, file, save, load, del, merge.
942
- #
943
- # Each public functions calls pendant function, private, prefixed by _, with
944
- # default options
945
- #
946
- # public => private
947
- # * #exist? => #p_exist?
948
- # * #[] => #p_get
949
- # * #[]= => #p_set
950
- # * #file => #p_file
951
- # * #save => #p_save
952
- # * #load => #p_load
953
- # * #del => #p_del
954
- # * #merge => #p_get(:merge => true).
955
- #
956
- # == Examples:
957
- #
958
- # * Your child class can limit or re-organize config layers to query.
959
- # Use :indexes or :names options to select which layer you want to query
960
- # and call the core function.
961
- #
962
- # Ex: If you have 4 config levels and want to limit to 2 top ones
963
- #
964
- # def [](*keys)
965
- # options = { keys: keys}
966
- # options[:indexes] = [0, 1]
967
- # p_get(options)
968
- # end
969
- #
970
- # Ex: If you have 4 config levels and want to limit to 2 names.
971
- #
972
- # def [](*keys)
973
- # options = { keys: keys}
974
- # options[:names] = ['local', 'default_app']
975
- # p_get(options)
976
- # end
977
- #
978
- # * Your child class can force some levels options or define some extra
979
- # options.
980
- #
981
- # Use :data_options to define each of them
982
- #
983
- # # Ex: If your class has 4 levels. /:name is not updatable for level 1.
984
- #
985
- # def [](*keys)
986
- # options = { keys: keys }
987
- # # The following defines data_readonly for the config level 1
988
- # if keys[0] == :name
989
- # options[:data_options] = [nil, {data_readonly: true}]
990
- # end
991
- # p_get(options)
992
- # end
993
- #
994
- # # Ex: if some layer takes care of option :section, and apply to each
995
- # # layers.
996
- # def [](section, *keys)
997
- # options = { keys: keys, section: section }
998
- # p_get(options)
999
- # end
1000
- #
1001
- # # Ex: if some layer takes care of option :section, and to apply to some
1002
- # # layers, like layer 1 and 2. (Assume with 4 layers.)
1003
- #
1004
- # def [](section, *keys)
1005
- # options = { keys: keys }
1006
- # options[:data_options] = [nil, {section: section}, {section: section}]
1007
- # p_get(options)
1008
- # end
1009
- #
1010
- #
1011
- class CoreConfig
1012
- # exist?
1013
- #
1014
- # * *Args*
1015
- # - +keys+ : Array of key path to found
1016
- #
1017
- # * *Returns*
1018
- # - boolean : true if the key path was found
1019
- #
1020
- # Class child:
1021
- # A class child can redefine this function to increase default
1022
- # features.
1023
- #
1024
- def exist?(*keys)
1025
- p_exist?(:keys => keys)
1026
- end
1027
-
1028
- # where?
1029
- #
1030
- # * *Args*
1031
- # - +keys+ : Array of key path to found
1032
- #
1033
- # * *Returns*
1034
- # - boolean : true if the key path was found
1035
- #
1036
- def where?(*keys)
1037
- p_where?(:keys => keys)
1038
- end
1039
-
1040
- # Get function
1041
- #
1042
- # * *Args*
1043
- # - +keys+ : Array of key path to found
1044
- #
1045
- # * *Returns*
1046
- # value found or nil.
1047
- #
1048
- def [](*keys)
1049
- p_get(:keys => keys)
1050
- end
1051
-
1052
- # Merge function
1053
- # Compare to get, merge will extract all values from each layers
1054
- # If those values are found and are type of Hash, merge will merge
1055
- # each layers values from the bottom to the top layer.
1056
- # ie invert of CoreConfig.layers
1057
- #
1058
- # Note that if a layer contains a data, but not Hash, this layer
1059
- # will be ignored.
1060
- #
1061
- # * *Args*
1062
- # - +keys+ : Array of key path to found
1063
- #
1064
- # * *Returns*
1065
- # value found merged or nil.
1066
- #
1067
- def merge(*keys)
1068
- p_get(:keys => keys, :merge => true)
1069
- end
1070
-
1071
- # Set function
1072
- #
1073
- # * *Args*
1074
- # - +keys+ : Array of key path to found
1075
- # * *Returns*
1076
- # - The value set or nil
1077
- #
1078
- # ex:
1079
- # value = CoreConfig.New
1080
- #
1081
- # value[:level1, :level2] = 'value'
1082
- # # => {:level1 => {:level2 => 'value'}}
1083
- def []=(*keys, value)
1084
- p_set(:keys => keys, :value => value)
1085
- end
1086
-
1087
- # Del function
1088
- #
1089
- # * *Args*
1090
- # - +keys+ : Array of key path to found and delete the last element.
1091
- # * *Returns*
1092
- # - The Hash updated.
1093
- #
1094
- # ex:
1095
- # value = CoreConfig.New
1096
- #
1097
- # value[:level1, :level2] = 'value'
1098
- # # => {:level1 => {:level2 => 'value'}}
1099
- # {:level1 => {:level2 => 'value'}}.del(:level1, :level2)
1100
- # # => {:level1 => {}}
1101
- def del(*keys)
1102
- p_del(:keys => keys)
1103
- end
1104
-
1105
- # Load from a file to the highest layer or a specific layer.
1106
- #
1107
- # * *Args* :
1108
- # - +options+ : Supported options for load
1109
- # - +:name+ : layer to get data.
1110
- # - +:index+: layer index to get data.
1111
- # If neither :name or :index is set, set will use the highest
1112
- # layer
1113
- #
1114
- # * *Returns* :
1115
- # -
1116
- # * *Raises* :
1117
- # - ++ ->
1118
- def load(options = {})
1119
- p_load(options)
1120
- end
1121
-
1122
- # Save to a file
1123
- #
1124
- # * *Args* :
1125
- # - +options+ : Supported options for save
1126
- # - +:name+ : layer to get data.
1127
- # - +:index+: layer index to get data.
1128
- # If neither :name or :index is set, set will use the highest
1129
- # layer
1130
- #
1131
- # * *Returns* :
1132
- # -
1133
- def save(options = {})
1134
- p_save(options)
1135
- end
1136
-
1137
- # Get/Set the file name.
1138
- #
1139
- # * *Args*
1140
- # - +:file+ : file name for the layer identified.
1141
- # - +options+ : Supported options for save
1142
- # - +:index+: layer index to get data.
1143
- # - +:name+ : layer to get data.
1144
- # If neither :name or :index is set, nil is returned.
1145
- #
1146
- # * *Returns*
1147
- # - The file name.
1148
- def file(filename = nil, options = {})
1149
- p_file(filename, options)
1150
- end
1151
-
1152
- # Function to check if merge can be used on a key.
1153
- # merge can return data only if at least one key value accross layers
1154
- # are of type Hash or Array.
1155
- # * *Args*
1156
- # - +options+ : Hash of how to get the data
1157
- # - +:value+ : Value to set
1158
- # - +:keys+ : Array of key path to found
1159
- # - +:name+ : layer to get data.
1160
- # - +:index+ : layer index to get data.
1161
- # If neither :name or :index is set, set will use the highest layer.
1162
- # - +:data_opts+ : Array or Hash. Define data options per layer.
1163
- # - +:exclusive+ : true to ensure values found are exclusively Hash or
1164
- # Array
1165
- #
1166
- def mergeable?(options)
1167
- parameters = _common_options_get(options, [:keys], [:exclusive])
1168
- return nil if parameters.nil?
1169
-
1170
- # Required options : parameters[0]
1171
- config_layers, data_opts, keys = parameters[0]
1172
- # Optional options : parameters[1]
1173
- be_exclusive = parameters[1][0]
1174
-
1175
- # Merge is done in the reverse order. ie from deepest to top.
1176
- config_layers = config_layers.reverse
1177
-
1178
- return nil if keys.length == 0 || keys[0].nil? || config_layers[0].nil?
1179
-
1180
- data_options = options.clone
1181
- data_options.delete_if do |key|
1182
- [:keys, :names, :indexes, :name, :index, :merge].include?(key)
1183
- end
1184
-
1185
- _check_from_layers(keys, config_layers, data_opts, data_options,
1186
- be_exclusive)
1187
- end
1188
-
1189
- # Function to get the version of a config layer name.
1190
- # * *Args*
1191
- # - +:name+ : layer to get data.
1192
- #
1193
- def version(name)
1194
- return nil unless name.is_a?(String)
1195
-
1196
- index = layer_index(name)
1197
- return nil if index.nil?
1198
-
1199
- @config_layers[index][:config].version
1200
- end
1201
-
1202
- # Function to set the version of a config layer name.
1203
- # * *Args*
1204
- # - +:name+ : layer to set data version.
1205
- #
1206
- def version_set(name, version)
1207
- return nil unless name.is_a?(String) && version.is_a?(String)
1208
-
1209
- index = layer_index(name)
1210
- return nil if index.nil?
1211
-
1212
- @config_layers[index][:config].version = version
1213
- end
1214
-
1215
- # List all config layers defined in this instance.
1216
- def layers
1217
- result = []
1218
- @config_layers.each { |layer| result << layer[:name] }
1219
- result
1220
- end
1221
-
1222
- # Display in human format.
1223
- def to_s
1224
- data = "Configs list ordered:\n"
1225
- @config_layers.each do |layer|
1226
- data += format("---- Config : %s ----\noptions: ", layer[:name])
1227
-
1228
- data += 'predefined, ' if layer[:init].is_a?(TrueClass)
1229
- if layer[:set]
1230
- data += 'data RW '
1231
- else
1232
- data += 'data RO '
1233
- end
1234
- data += format(", %s\n", to_s_file_opts(layer))
1235
-
1236
- data += format("%s\n", layer[:config].to_s)
1237
- end
1238
- data
1239
- end
1240
-
1241
- private
1242
-
1243
- def to_s_file_opts(layer)
1244
- data = 'File '
1245
- if layer[:load] &&
1246
- if layer[:save]
1247
- data += 'RW'
1248
- else
1249
- data += 'RO'
1250
- end
1251
- data += ', filename updatable' if layer[:file_set]
1252
- else
1253
- data += 'None'
1254
- end
1255
- data
1256
- end
1257
- end
1258
- end