lorj 1.0.3 → 1.0.4

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/example/students_1/students.rb +5 -6
  3. data/example/students_2/students.rb +4 -5
  4. data/example/students_3/students.rb +4 -5
  5. data/example/students_4/students.rb +4 -5
  6. data/example/students_5/students.rb +5 -5
  7. data/lib/core/core.rb +6 -1
  8. data/lib/core/core_controller.rb +1 -9
  9. data/lib/core/core_internal.rb +2 -1
  10. data/lib/core/core_model.rb +2 -10
  11. data/lib/core/core_object_data.rb +18 -0
  12. data/lib/core/core_object_params.rb +43 -4
  13. data/lib/core/core_process.rb +1 -9
  14. data/lib/core/core_process_setup.rb +32 -6
  15. data/lib/core/core_setup_ask.rb +41 -33
  16. data/lib/core/core_setup_encrypt.rb +29 -6
  17. data/lib/core/core_setup_init.rb +2 -2
  18. data/lib/core/definition.rb +33 -10
  19. data/lib/core/definition_internal.rb +10 -14
  20. data/lib/core/lorj_basedefinition.rb +16 -24
  21. data/lib/core/lorj_baseprocess.rb +113 -44
  22. data/lib/core/lorj_data.rb +2 -9
  23. data/lib/core/lorj_keypath.rb +5 -2
  24. data/lib/core_process/cloud/process/common.rb +4 -7
  25. data/lib/core_process/cloud/process/connection.rb +44 -45
  26. data/lib/core_process/cloud/process/external_network.rb +24 -28
  27. data/lib/core_process/cloud/process/flavor.rb +31 -34
  28. data/lib/core_process/cloud/process/images.rb +12 -15
  29. data/lib/core_process/cloud/process/internet_network.rb +13 -14
  30. data/lib/core_process/cloud/process/internet_server.rb +9 -10
  31. data/lib/core_process/cloud/process/keypairs.rb +34 -27
  32. data/lib/core_process/cloud/process/network.rb +21 -23
  33. data/lib/core_process/cloud/process/public_ip.rb +17 -18
  34. data/lib/core_process/cloud/process/router.rb +86 -92
  35. data/lib/core_process/cloud/process/rules.rb +30 -31
  36. data/lib/core_process/cloud/process/security_groups.rb +21 -22
  37. data/lib/core_process/cloud/process/server.rb +30 -31
  38. data/lib/core_process/cloud/process/server_log.rb +13 -14
  39. data/lib/core_process/cloud/process/subnetwork.rb +25 -40
  40. data/lib/logging.rb +4 -17
  41. data/lib/lorj/version.rb +1 -1
  42. data/lib/lorj.rb +2 -1
  43. data/lib/lorj_account.rb +137 -90
  44. data/lib/lorj_config.rb +13 -19
  45. data/lib/lorj_defaults.rb +46 -292
  46. data/lib/lorj_meta.rb +729 -0
  47. data/lib/prc.rb +119 -30
  48. data/lib/prc_base_config.rb +53 -47
  49. data/lib/prc_core_config.rb +837 -565
  50. data/lib/prc_section_config.rb +44 -16
  51. data/lib/providers/hpcloud/hpcloud.rb +1 -1
  52. data/lib/providers/openstack/openstack.rb +278 -21
  53. data/lib/providers/openstack/openstack_create.rb +205 -0
  54. data/lib/providers/openstack/openstack_delete.rb +28 -0
  55. data/lib/providers/openstack/openstack_get.rb +39 -0
  56. data/lib/providers/openstack/openstack_process.rb +26 -0
  57. data/lib/providers/openstack/openstack_query.rb +96 -0
  58. data/lib/providers/openstack/openstack_update.rb +35 -0
  59. data/lib/rh.rb +91 -6
  60. data/lorj-spec/defaults.yaml +18 -12
  61. data/lorj.gemspec +1 -0
  62. data/spec/01_hash_rh_spec.rb +41 -2
  63. data/spec/02_prc_base_config_spec.rb +1 -1
  64. data/spec/03_prc_section_config_spec.rb +1 -1
  65. data/spec/04_prc_core_config_spec.rb +148 -4
  66. data/spec/09_prc_spec.rb +104 -0
  67. data/spec/{00_lorj_log_spec.rb → 10_lorj_log_spec.rb} +23 -2
  68. data/spec/11_lorj_config_spec.rb +9 -27
  69. data/spec/12_lorj_account_spec.rb +36 -20
  70. data/spec/20_lorj_meta_spec.rb +271 -0
  71. data/spec/21_lorj_defaults_spec.rb +85 -0
  72. metadata +31 -4
@@ -0,0 +1,26 @@
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
+ # Specific openstack process added to the application process.
18
+ class OpenstackProcess
19
+ def openstack_get_tenant(sObjectType, hParams)
20
+ tenant_name = hParams[:tenant]
21
+ query = { :name => tenant_name }
22
+ PrcLib.state("searching for tenant '%s'", tenant_name)
23
+ list = query_single(sObjectType, query, tenant_name)
24
+ return list[0] if list.length > 0
25
+ end
26
+ end
@@ -0,0 +1,96 @@
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
+ # Defined Openstack object query.
18
+ class OpenstackController
19
+ def self.def_basic_query(connection, name, property_name = nil)
20
+ property_name = property_name.nil? ? name.to_s + 's' : property_name.to_s
21
+
22
+ define_method("query_#{name}") do |hParams, _query|
23
+ required?(hParams, connection)
24
+ hParams[connection].send(property_name).all
25
+ end
26
+ end
27
+
28
+ # Implementation of API supporting query Hash
29
+ def self.def_simple_query(connection, name, property_name = nil)
30
+ property_name = property_name.nil? ? name.to_s + 's' : property_name.to_s
31
+
32
+ define_method("query_#{name}") do |hParams, query|
33
+ required?(hParams, connection)
34
+ hParams[connection].send(property_name).all query
35
+ end
36
+ end
37
+
38
+ # Implementation of API NOT supporting query Hash
39
+ # The function will filter itself.
40
+ def self.def_complex_query(connection, name, property_name = nil)
41
+ property_name = property_name.nil? ? name.to_s + 's' : property_name.to_s
42
+
43
+ define_method("query_#{name}") do |hParams, query|
44
+ required?(hParams, connection)
45
+
46
+ key_pairs = hParams[connection].send(property_name).all
47
+ results = []
48
+ key_pairs.each do |sElem|
49
+ selected = true
50
+ attributes = sElem.instance_variable_get(:@attributes)
51
+ query.each do |key, value|
52
+ if attributes[key] != value
53
+ selected = false
54
+ break
55
+ end
56
+ end
57
+ results.push sElem if selected
58
+ end
59
+ results
60
+ end
61
+ end
62
+
63
+ def_simple_query :compute_connection, :tenant
64
+
65
+ def_simple_query :compute_connection, :image
66
+
67
+ def_simple_query :compute_connection, :flavor
68
+
69
+ def_simple_query :compute_connection, :server
70
+
71
+ def_simple_query :network_connection, :network
72
+
73
+ def_simple_query :network_connection, :subnetwork, :subnets
74
+
75
+ def_simple_query :network_connection, :router
76
+
77
+ def_simple_query :network_connection, :port
78
+
79
+ # def_simple_query :network_connection, :security_groups, :security_groups
80
+
81
+ def_simple_query :network_connection, :rule, :security_group_rules
82
+
83
+ def_complex_query :compute_connection, :keypairs, :key_pairs
84
+
85
+ def_complex_query :compute_connection, :public_ip, :addresses
86
+
87
+ def_complex_query :compute_connection, :tenants, :tenants
88
+
89
+ def query_security_groups(hParams, query)
90
+ required?(hParams, :network_connection)
91
+ required?(hParams, :tenants)
92
+
93
+ query[:tenant_id] = hParams[:tenants].id
94
+ hParams[:network_connection].send(:security_groups).all query
95
+ end
96
+ end
@@ -0,0 +1,35 @@
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
+ # Define Openstack update controller
18
+ class OpenstackController
19
+ def update_router(obj_to_save, _hParams)
20
+ router = obj_to_save[:object]
21
+ # The optional external_gateway_info must be a The network_id for the
22
+ # external gateway. It cannot be a Hash
23
+ # See API : http://developer.openstack.org/api-ref-networking-v2.html
24
+ router.external_gateway_info = router.external_gateway_info['network_id']
25
+ # Save will restore the Hash.
26
+ begin
27
+ router.save
28
+ true
29
+ rescue => e
30
+ Lorj.error "OpenStack: Router save error.\n%s\n%s",
31
+ e.message, e.backtrace.join("\n")
32
+ false
33
+ end
34
+ end
35
+ end
data/lib/rh.rb CHANGED
@@ -18,6 +18,12 @@
18
18
  require 'rubygems'
19
19
  require 'yaml'
20
20
 
21
+ # Adding rh_clone at object level. This be able to use a generic rh_clone
22
+ # redefined per object Hash and Array.
23
+ class Object
24
+ alias_method :rh_clone, :clone
25
+ end
26
+
21
27
  # Recursive Hash added to the Hash class
22
28
  class Hash
23
29
  # Recursive Hash deep level found counter
@@ -125,6 +131,8 @@ class Hash
125
131
  # # it is like searching for nothing...
126
132
  # yVal.rh_exist? => nil
127
133
  def rh_exist?(*p)
134
+ p = p.flatten
135
+
128
136
  return nil if p.length == 0
129
137
 
130
138
  count = p.length
@@ -283,8 +291,8 @@ class Hash
283
291
  # 'text' => 'blabla' },
284
292
  # 'test5' => 'test' }}
285
293
  #
286
- # rh_key_to_symbol(1) return no diff
287
- # rh_key_to_symbol(2) return "test5" is replaced by :test5
294
+ # hdata.rh_key_to_symbol(1) return no diff
295
+ # hdata.rh_key_to_symbol(2) return "test5" is replaced by :test5
288
296
  # # hdata = { :test => { :test2 => { :test5 => :test,
289
297
  # # 'text' => 'blabla' },
290
298
  # # :test5 => 'test' }}
@@ -322,10 +330,10 @@ class Hash
322
330
  # 'text' => 'blabla' },
323
331
  # 'test5' => 'test' }}
324
332
  #
325
- # rh_key_to_symbol?(1) return false
326
- # rh_key_to_symbol?(2) return true
327
- # rh_key_to_symbol?(3) return true
328
- # rh_key_to_symbol?(4) return true
333
+ # hdata.rh_key_to_symbol?(1) return false
334
+ # hdata.rh_key_to_symbol?(2) return true
335
+ # hdata.rh_key_to_symbol?(3) return true
336
+ # hdata.rh_key_to_symbol?(4) return true
329
337
  def rh_key_to_symbol?(levels = 1)
330
338
  each do |key, value|
331
339
  return true if key.is_a?(String)
@@ -338,4 +346,81 @@ class Hash
338
346
  end
339
347
  false
340
348
  end
349
+
350
+ # return an exact clone of the recursive Array and Hash contents.
351
+ #
352
+ # * *Args* :
353
+ #
354
+ # * *Returns* :
355
+ # - Recursive Array/Hash cloned. Other kind of objects are kept referenced.
356
+ # * *Raises* :
357
+ # Nothing
358
+ #
359
+ # examples:
360
+ # hdata = { :test => { :test2 => { :test5 => :test,
361
+ # 'text' => 'blabla' },
362
+ # 'test5' => 'test' },
363
+ # :array => [{ :test => :value1 }, 2, { :test => :value3 }]}
364
+ #
365
+ # hclone = hdata.rh_clone
366
+ # hclone[:test] = "test"
367
+ # hdata[:test] == { :test2 => { :test5 => :test,'text' => 'blabla' }
368
+ # # => true
369
+ # hclone[:array].pop
370
+ # hdata[:array].length != hclone[:array].length
371
+ # # => true
372
+ # hclone[:array][0][:test] = "value2"
373
+ # hdata[:array][0][:test] != hclone[:array][0][:test]
374
+ # # => true
375
+ def rh_clone
376
+ result = {}
377
+ each do |key, value|
378
+ if [Array, Hash].include?(value.class)
379
+ result[key] = value.rh_clone
380
+ else
381
+ result[key] = value
382
+ end
383
+ end
384
+ result
385
+ end
386
+ end
387
+
388
+ # Defines rh_clone for Array
389
+ class Array
390
+ # return an exact clone of the recursive Array and Hash contents.
391
+ #
392
+ # * *Args* :
393
+ #
394
+ # * *Returns* :
395
+ # - Recursive Array/Hash cloned.
396
+ # * *Raises* :
397
+ # Nothing
398
+ #
399
+ # examples:
400
+ # hdata = { :test => { :test2 => { :test5 => :test,
401
+ # 'text' => 'blabla' },
402
+ # 'test5' => 'test' },
403
+ # :array => [{ :test => :value1 }, 2, { :test => :value3 }]}
404
+ #
405
+ # hclone = hdata.rh_clone
406
+ # hclone[:test] = "test"
407
+ # hdata[:test] == { :test2 => { :test5 => :test,'text' => 'blabla' }
408
+ # # => true
409
+ # hclone[:array].pop
410
+ # hdata[:array].length != hclone[:array].length
411
+ # # => true
412
+ # hclone[:array][0][:test] = "value2"
413
+ # hdata[:array][0][:test] != hclone[:array][0][:test]
414
+ # # => true
415
+ def rh_clone
416
+ result = []
417
+ each do |value|
418
+ begin
419
+ result << value.rh_clone
420
+ rescue
421
+ result << value
422
+ end
423
+ end
424
+ result
425
+ end
341
426
  end
@@ -14,17 +14,23 @@
14
14
 
15
15
  # Defaults yaml file used for rspec.
16
16
  :default:
17
- :maestro_url: http://example.org
18
- :keypair_name: default_key
19
- :data: None
20
-
17
+ :maestro_url: http://example.org
18
+ :keypair_name: default_key
19
+ :data: None
21
20
  :description:
22
- :FORJ_HPC: Testing extra application default value.
23
-
21
+ :FORJ_HPC: Testing extra application default value.
22
+ :setup:
23
+ - :desc: 'Step 1'
24
+ :explanation: |-
25
+ My complete explanation is in
26
+ multiline <%= config['text'] %>
27
+ - :desc: 'Step 2'
28
+ :add:
29
+ - :data
24
30
  :sections:
25
- :credentials:
26
- :keypair_name:
27
- :data:
28
- :account_exclusive: true
29
- :maestro:
30
- :maestro_url:
31
+ :credentials:
32
+ :keypair_name:
33
+ :data:
34
+ :account_exclusive: true
35
+ :maestro:
36
+ :maestro_url:
data/lorj.gemspec CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.add_development_dependency 'bundler'
30
30
  spec.add_development_dependency 'rake', '~> 10.0'
31
31
  spec.add_development_dependency 'rspec', '~> 3.1.0'
32
+ spec.add_development_dependency 'rubocop', '>= 0.29.0'
32
33
  spec.add_development_dependency 'byebug' unless less_than_two
33
34
  spec.rdoc_options << \
34
35
  '--title Lorj - The Process Controllers framework system' << \
@@ -15,11 +15,13 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- $LOAD_PATH << File.join('..', 'lib')
18
+ # require 'byebug'
19
+
20
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
19
21
 
20
22
  require 'rh'
21
23
 
22
- describe 'Recursive Hash extension,' do
24
+ describe 'Recursive Hash/Array extension,' do
23
25
  context "With { :test => {:test2 => 'value1', :test3 => 'value2'},"\
24
26
  ":test4 => 'value3'}" do
25
27
  before(:all) do
@@ -196,6 +198,43 @@ describe 'Recursive Hash extension,' do
196
198
  expect(@hdata).to eq({})
197
199
  end
198
200
  end
201
+
202
+ context "With hdata = { :test => { :test2 => { :test5 => :test,\n"\
203
+ " 'text' => 'blabla' },\n"\
204
+ " 'test5' => 'test' },\n"\
205
+ ' :array => [{ :test => :value1 }, '\
206
+ '2, { :test => :value3 }]}' do
207
+ before(:all) do
208
+ @hdata = { :test => { :test2 => { :test5 => :test,
209
+ 'text' => 'blabla' },
210
+ 'test5' => 'test' },
211
+ :array => [{ :test => :value1 }, 2, { :test => :value3 }]
212
+ }
213
+ end
214
+ it 'rh_clone is done without error' do
215
+ expect { @hdata.rh_clone }.to_not raise_error
216
+ end
217
+ it 'hclone[:test] = "test" => hdata[:test] != hclone[:test]' do
218
+ hclone = @hdata.rh_clone
219
+ hclone[:test] = 'test'
220
+ expect(@hdata[:test]).to eq(:test2 => { :test5 => :test,
221
+ 'text' => 'blabla' },
222
+ 'test5' => 'test')
223
+ end
224
+ it 'hclone[:array].pop => hdata[:array].length != hclone[:array].length' do
225
+ hclone = @hdata.rh_clone
226
+ hclone[:array].pop
227
+ expect(@hdata[:array].length).not_to eq(hclone[:array].length)
228
+ end
229
+
230
+ it 'hclone[:array][0][:test] = "value2" '\
231
+ '=> hdata[:array][0][:test] != hclone[:array][0][:test]' do
232
+ hclone = @hdata.rh_clone
233
+ hclone[:array][0][:test] = 'value2'
234
+ expect(@hdata[:array][0][:test]).to eq(:value1)
235
+ end
236
+ end
237
+
199
238
  context 'With hdata = { :test => { :test2 => { :test5 => :test,'\
200
239
  "'text' => 'blabla' },"\
201
240
  "'test5' => 'test' }}" do
@@ -17,7 +17,7 @@
17
17
 
18
18
  # require 'byebug'
19
19
 
20
- $LOAD_PATH << File.join('..', 'lib')
20
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
21
21
 
22
22
  require 'rh.rb'
23
23
  require 'prc.rb'
@@ -17,7 +17,7 @@
17
17
 
18
18
  # require 'byebug'
19
19
 
20
- $LOAD_PATH << File.join('..', 'lib')
20
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
21
21
 
22
22
  require 'rh.rb'
23
23
  require 'prc.rb'
@@ -17,7 +17,7 @@
17
17
 
18
18
  # require 'byebug'
19
19
 
20
- $LOAD_PATH << File.join('..', 'lib')
20
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
21
21
 
22
22
  require 'rh.rb'
23
23
  require 'prc.rb'
@@ -41,13 +41,14 @@ describe 'class: PRC::CoreConfig,' do
41
41
  end
42
42
  end
43
43
 
44
- context 'from a child class, with local layer set to :test => :found_local'\
45
- ' and runtime layer' do
44
+ context 'from a child class, with local layer set to :test => :found_local, '\
45
+ ':test2 => {:test => :subhash} and runtime layer' do
46
46
  before(:all) do
47
47
  # Child class definition for rSpec.
48
48
  class Test1 < PRC::CoreConfig
49
49
  def initialize
50
- local = PRC::BaseConfig.new(:test => :found_local)
50
+ local = PRC::BaseConfig.new(:test => :found_local,
51
+ :test2 => { :test => :subhash })
51
52
  layers = []
52
53
  layers << PRC::CoreConfig.define_layer(:name => 'local',
53
54
  :config => local)
@@ -55,6 +56,14 @@ describe 'class: PRC::CoreConfig,' do
55
56
 
56
57
  initialize_layers(layers)
57
58
  end
59
+
60
+ def set(options)
61
+ p_set(options)
62
+ end
63
+
64
+ def get(options)
65
+ p_get(options)
66
+ end
58
67
  end
59
68
  @config = Test1.new
60
69
  end
@@ -64,10 +73,26 @@ describe 'class: PRC::CoreConfig,' do
64
73
  expect(@config.layers).to eq(%w(runtime local))
65
74
  end
66
75
 
76
+ it 'config.exist?(:test) returns true' do
77
+ expect(@config.exist?(:test)).to equal(true)
78
+ end
79
+
80
+ it 'config.exist?(:test2, :test) returns true' do
81
+ expect(@config.exist?(:test2, :test)).to equal(true)
82
+ end
83
+
67
84
  it 'config.where?(:test) should be ["local"]' do
68
85
  expect(@config.where?(:test)).to eq(['local'])
69
86
  end
70
87
 
88
+ it 'config.where?(:test2) should be ["local"]' do
89
+ expect(@config.where?(:test2)).to eq(['local'])
90
+ end
91
+
92
+ it 'config.where?(:test2, :test) should be ["local"]' do
93
+ expect(@config.where?(:test2, :test)).to eq(['local'])
94
+ end
95
+
71
96
  it 'config.[:test] = :where set in "runtime".' do
72
97
  expect(@config[:test] = :where).to eq(:where)
73
98
  expect(@config.where?(:test)).to eq(%w(runtime local))
@@ -131,5 +156,124 @@ describe 'class: PRC::CoreConfig,' do
131
156
  expect(@config.layer_remove(:name => 'runtime')).to equal(nil)
132
157
  expect(@config.layers).to eq(%w(runtime local))
133
158
  end
159
+
160
+ it 'a child set(keys, value, name => "local") works.' do
161
+ value = { :data1 => 'test_data1', :data2 => 'test_data2' }
162
+ expect(@config.set(:keys => [:merge1],
163
+ :value => value,
164
+ :name => 'local')).to eq(value)
165
+ expect(@config.where?(:merge1)).to eq(%w(local))
166
+ end
167
+
168
+ it 'a child set(keys, value, names => ["local"]) works '\
169
+ 'but set in runtime. :names is ignored.' do
170
+ value = { :data1 => 'test_data1', :data2 => 'test_data3' }
171
+ expect(@config.set(:keys => [:merge1],
172
+ :value => value,
173
+ :names => ['local'])).to eq(value)
174
+ expect(@config.where?(:merge1)).to eq(%w(runtime local))
175
+ end
176
+
177
+ it 'a child set(keys, value, name => "runtime") works.' do
178
+ value = { :data2 => 'value_runtime', :test_runtime => true }
179
+ expect(@config.set(:keys => [:merge1],
180
+ :value => value,
181
+ :name => 'runtime')).to eq(value)
182
+ expect(@config.where?(:merge1)).to eq(%w(runtime local))
183
+ expect(@config[:merge1]).to eq(value)
184
+ end
185
+
186
+ it 'a child get(keys, name) can do merge '\
187
+ 'even with only one layer selected.' do
188
+ value_local = { :data1 => 'test_data1', :data2 => 'test_data2' }
189
+ expect(@config.get(:keys => [:merge1], :merge => true,
190
+ :names => ['local'])).to eq(value_local)
191
+ value_runtime = { :data2 => 'value_runtime', :test_runtime => true }
192
+ expect(@config.get(:keys => [:merge1], :merge => true,
193
+ :names => ['runtime'])).to eq(value_runtime)
194
+ end
195
+
196
+ context "with config[:merge1] = {:data2 => {:test_runtime => true} }\n"\
197
+ 'and local: :merge1: => {:data1: test_data1, :data2: test_data3}' do
198
+ before(:all) do
199
+ @config[:merge1] = { :data2 => { :test_runtime => true } }
200
+ value = { :data1 => 'test_data1', :data2 => 'test_data3' }
201
+ @config.set(:keys => [:merge1], :value => value, :name => 'local')
202
+ end
203
+
204
+ it 'config.mergeable?(:keys => [:merge1, :data2]) return false, '\
205
+ 'because the first found in the deepest layers is not a Hash/Array.' do
206
+ expect(@config.where?(:merge1, :data2)).to eq(%w(runtime local))
207
+ expect(@config.mergeable?(:keys => [:merge1, :data2])).to equal(false)
208
+ end
209
+
210
+ it 'config.mergeable?(:keys => [:merge1, :data2], '\
211
+ ':exclusive => true) return false '\
212
+ '- "runtime" layer :data2 is not a Hash' do
213
+ expect(@config.where?(:merge1, :data2)).to eq(%w(runtime local))
214
+ expect(@config.mergeable?(:keys => [:merge1, :data2],
215
+ :exclusive => true)).to equal(false)
216
+ end
217
+
218
+ it 'config.merge() return "test_data3" a single data, first found in '\
219
+ 'the deepest layers.' do
220
+ expect(@config.merge(:merge1, :data2)).to eq('test_data3')
221
+ end
222
+ end
223
+
224
+ context "with config[:merge1] = {:data2 => :test_runtime}\n"\
225
+ 'and local: :merge1: => {:data2 => {:test => :test_data2} }' do
226
+ before(:all) do
227
+ @config[:merge1] = { :data2 => :test_runtime }
228
+ value = { :data2 => { :test => :test_data2 } }
229
+ @config.set(:keys => [:merge1], :value => value, :name => 'local')
230
+ end
231
+
232
+ it 'config.mergeable?(:keys => [:merge1, :data2]) return true, '\
233
+ 'because the first found in the deepest layers is a Hash.' do
234
+ expect(@config.where?(:merge1)).to eq(%w(runtime local))
235
+ expect(@config.mergeable?(:keys => [:merge1, :data2])).to equal(true)
236
+ end
237
+
238
+ it 'config.mergeable?(:keys => [:merge1, :data2], '\
239
+ ':exclusive => true) return false '\
240
+ '- "runtime" layer :data2 is not a Hash' do
241
+ expect(@config.mergeable?(:keys => [:merge1, :data2],
242
+ :exclusive => true)).to equal(false)
243
+ end
244
+
245
+ it 'config.merge() return a single data, first found in the '\
246
+ 'deepest layers.' do
247
+ expect(@config.merge(:merge1, :data2)).to eq(:test => :test_data2)
248
+ end
249
+ end
250
+
251
+ context "with config[:merge1] = {:data2 => {:test_runtime => true} }\n"\
252
+ 'and local: :merge1: => {:data2 => {:test => :test_data2} }' do
253
+ before(:all) do
254
+ @config[:merge1] = { :data2 => { :test_runtime => true } }
255
+ value = { :data2 => { :test => :test_data2 } }
256
+ @config.set(:keys => [:merge1], :value => value, :name => 'local')
257
+ end
258
+
259
+ it 'config.mergeable?(:keys => [:merge1, :data2]) return true, '\
260
+ 'because the first found in the deepest layers is a Hash.' do
261
+ expect(@config.where?(:merge1, :data2)).to eq(%w(runtime local))
262
+ expect(@config.mergeable?(:keys => [:merge1, :data2])).to equal(true)
263
+ end
264
+
265
+ it 'config.mergeable?(:keys => [:merge1, :data2], '\
266
+ ':exclusive => true) return true '\
267
+ '- All layers data found are Hash type.' do
268
+ expect(@config.mergeable?(:keys => [:merge1, :data2],
269
+ :exclusive => true)).to equal(true)
270
+ end
271
+
272
+ it 'config.merge() return a single data, first found in the '\
273
+ 'deepest layers.' do
274
+ expect(@config.merge(:merge1, :data2)).to eq(:test_runtime => true,
275
+ :test => :test_data2)
276
+ end
277
+ end
134
278
  end
135
279
  end