lorj 1.0.3 → 1.0.4

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