puppet 4.9.4 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puppet might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/Rakefile +6 -0
- data/ext/project_data.yaml +2 -2
- data/lib/hiera/puppet_function.rb +1 -1
- data/lib/puppet.rb +1 -0
- data/lib/puppet/application.rb +14 -0
- data/lib/puppet/application/inspect.rb +3 -0
- data/lib/puppet/defaults.rb +12 -2
- data/lib/puppet/etc.rb +125 -0
- data/lib/puppet/face/help.rb +1 -1
- data/lib/puppet/functions.rb +49 -4
- data/lib/puppet/functions/eyaml_lookup_key.rb +12 -3
- data/lib/puppet/functions/hocon_data.rb +9 -0
- data/lib/puppet/functions/json_data.rb +9 -0
- data/lib/puppet/functions/yaml_data.rb +9 -0
- data/lib/puppet/indirector/file_bucket_file/file.rb +69 -22
- data/lib/puppet/indirector/key/file.rb +2 -1
- data/lib/puppet/indirector/ssl_file.rb +24 -3
- data/lib/puppet/module.rb +28 -22
- data/lib/puppet/network/http/compression.rb +2 -1
- data/lib/puppet/parser/compiler.rb +15 -38
- data/lib/puppet/parser/functions/hiera.rb +1 -1
- data/lib/puppet/parser/functions/hiera_array.rb +1 -1
- data/lib/puppet/parser/functions/hiera_hash.rb +1 -1
- data/lib/puppet/parser/functions/hiera_include.rb +1 -1
- data/lib/puppet/parser/scope.rb +59 -17
- data/lib/puppet/pops/evaluator/callable_signature.rb +7 -0
- data/lib/puppet/pops/functions/dispatch.rb +18 -5
- data/lib/puppet/pops/functions/dispatcher.rb +7 -13
- data/lib/puppet/pops/issue_reporter.rb +1 -1
- data/lib/puppet/pops/issues.rb +84 -0
- data/lib/puppet/pops/loader/base_loader.rb +13 -5
- data/lib/puppet/pops/lookup/configured_data_provider.rb +8 -2
- data/lib/puppet/pops/lookup/data_dig_function_provider.rb +109 -19
- data/lib/puppet/pops/lookup/data_hash_function_provider.rb +19 -4
- data/lib/puppet/pops/lookup/data_provider.rb +43 -29
- data/lib/puppet/pops/lookup/environment_data_provider.rb +1 -1
- data/lib/puppet/pops/lookup/explainer.rb +1 -0
- data/lib/puppet/pops/lookup/function_provider.rb +36 -11
- data/lib/puppet/pops/lookup/global_data_provider.rb +18 -5
- data/lib/puppet/pops/lookup/hiera_config.rb +203 -84
- data/lib/puppet/pops/lookup/interpolation.rb +21 -6
- data/lib/puppet/pops/lookup/invocation.rb +14 -9
- data/lib/puppet/pops/lookup/location_resolver.rb +27 -0
- data/lib/puppet/pops/lookup/lookup_adapter.rb +59 -6
- data/lib/puppet/pops/lookup/lookup_key_function_provider.rb +9 -77
- data/lib/puppet/pops/lookup/module_data_provider.rb +27 -4
- data/lib/puppet/pops/parser/lexer2.rb +1 -1
- data/lib/puppet/pops/pcore.rb +3 -3
- data/lib/puppet/pops/types/p_object_type.rb +4 -6
- data/lib/puppet/pops/types/ruby_generator.rb +2 -2
- data/lib/puppet/pops/types/type_asserter.rb +3 -3
- data/lib/puppet/pops/types/type_mismatch_describer.rb +25 -7
- data/lib/puppet/pops/types/types.rb +20 -29
- data/lib/puppet/provider/exec.rb +4 -2
- data/lib/puppet/provider/nameservice.rb +8 -8
- data/lib/puppet/provider/selmodule/semodule.rb +20 -16
- data/lib/puppet/provider/service/src.rb +39 -39
- data/lib/puppet/provider/service/systemd.rb +1 -1
- data/lib/puppet/provider/user/aix.rb +7 -2
- data/lib/puppet/settings.rb +30 -17
- data/lib/puppet/ssl/base.rb +14 -1
- data/lib/puppet/ssl/certificate_authority.rb +4 -2
- data/lib/puppet/ssl/configuration.rb +4 -1
- data/lib/puppet/ssl/inventory.rb +10 -3
- data/lib/puppet/ssl/key.rb +7 -3
- data/lib/puppet/test/test_helper.rb +3 -0
- data/lib/puppet/type.rb +13 -1
- data/lib/puppet/type/exec.rb +16 -1
- data/lib/puppet/type/group.rb +17 -11
- data/lib/puppet/type/user.rb +3 -1
- data/lib/puppet/util.rb +1 -0
- data/lib/puppet/util/character_encoding.rb +95 -0
- data/lib/puppet/util/execution.rb +9 -6
- data/lib/puppet/util/reference.rb +4 -2
- data/lib/puppet/util/windows/file.rb +5 -1
- data/lib/puppet/version.rb +6 -2
- data/locales/config.yaml +1 -1
- data/locales/puppet.pot +18 -4
- data/spec/integration/ssl/autosign_spec.rb +18 -3
- data/spec/integration/ssl/key_spec.rb +104 -0
- data/spec/integration/type/user_spec.rb +13 -6
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/application/inspect_spec.rb +9 -2
- data/spec/unit/data_providers/function_data_provider_spec.rb +2 -2
- data/spec/unit/etc_spec.rb +234 -0
- data/spec/unit/face/certificate_spec.rb +10 -2
- data/spec/unit/functions/dig_spec.rb +1 -1
- data/spec/unit/functions/hiera_spec.rb +40 -1
- data/spec/unit/functions/lookup_fixture_spec.rb +10 -10
- data/spec/unit/functions/lookup_spec.rb +1217 -357
- data/spec/unit/functions4_spec.rb +37 -1
- data/spec/unit/indirector/file_bucket_file/file_spec.rb +33 -2
- data/spec/unit/indirector/key/file_spec.rb +1 -1
- data/spec/unit/indirector/ssl_file_spec.rb +3 -3
- data/spec/unit/module_spec.rb +52 -59
- data/spec/unit/network/http/compression_spec.rb +39 -8
- data/spec/unit/parser/compiler_spec.rb +14 -0
- data/spec/unit/pops/loaders/loaders_spec.rb +21 -3
- data/spec/unit/pops/loaders/module_loaders_spec.rb +61 -0
- data/spec/unit/pops/lookup/context_spec.rb +56 -8
- data/spec/unit/pops/lookup/lookup_spec.rb +32 -1
- data/spec/unit/pops/parser/lexer2_spec.rb +8 -0
- data/spec/unit/pops/types/ruby_generator_spec.rb +48 -0
- data/spec/unit/pops/types/type_mismatch_describer_spec.rb +12 -3
- data/spec/unit/pops/types/types_spec.rb +6 -7
- data/spec/unit/provider/nameservice_spec.rb +12 -12
- data/spec/unit/provider/package/pkg_spec.rb +2 -0
- data/spec/unit/provider/service/src_spec.rb +5 -0
- data/spec/unit/ssl/base_spec.rb +9 -0
- data/spec/unit/ssl/certificate_authority_spec.rb +2 -2
- data/spec/unit/ssl/certificate_request_attributes_spec.rb +6 -0
- data/spec/unit/ssl/certificate_request_spec.rb +1 -1
- data/spec/unit/ssl/certificate_spec.rb +1 -1
- data/spec/unit/ssl/configuration_spec.rb +11 -2
- data/spec/unit/ssl/inventory_spec.rb +27 -3
- data/spec/unit/ssl/key_spec.rb +7 -7
- data/spec/unit/type/exec_spec.rb +41 -4
- data/spec/unit/type/file_spec.rb +4 -1
- data/spec/unit/util/character_encoding_spec.rb +88 -0
- data/spec/unit/util/execution_spec.rb +12 -0
- data/spec/unit/version_spec.rb +4 -0
- metadata +3803 -3808
- data/tasks/i18n.rake +0 -20
@@ -9,6 +9,13 @@ describe Puppet::Face[:certificate, '0.0.1'] do
|
|
9
9
|
|
10
10
|
let(:ca) { Puppet::SSL::CertificateAuthority.instance }
|
11
11
|
|
12
|
+
# different UTF-8 widths
|
13
|
+
# 1-byte A
|
14
|
+
# 2-byte ۿ - http://www.fileformat.info/info/unicode/char/06ff/index.htm - 0xDB 0xBF / 219 191
|
15
|
+
# 3-byte ᚠ - http://www.fileformat.info/info/unicode/char/16A0/index.htm - 0xE1 0x9A 0xA0 / 225 154 160
|
16
|
+
# 4-byte - http://www.fileformat.info/info/unicode/char/2070E/index.htm - 0xF0 0xA0 0x9C 0x8E / 240 160 156 142
|
17
|
+
let (:mixed_utf8) { "A\u06FF\u16A0\u{2070E}" } # Aۿᚠ
|
18
|
+
|
12
19
|
before :each do
|
13
20
|
Puppet[:confdir] = tmpdir('conf')
|
14
21
|
Puppet::SSL::CertificateAuthority.stubs(:ca?).returns true
|
@@ -84,9 +91,10 @@ describe Puppet::Face[:certificate, '0.0.1'] do
|
|
84
91
|
it "should add the provided dns_alt_names if they are specified" do
|
85
92
|
Puppet[:dns_alt_names] = 'from,the,config'
|
86
93
|
|
87
|
-
subject.generate(hostname, options.merge(:dns_alt_names =>
|
94
|
+
subject.generate(hostname, options.merge(:dns_alt_names => "explicit,alt,#{mixed_utf8}"))
|
88
95
|
|
89
|
-
|
96
|
+
# CSRs will return subject_alt_names as BINARY strings
|
97
|
+
expected = %W[DNS:explicit DNS:alt DNS:#{mixed_utf8.force_encoding(Encoding::BINARY)} DNS:#{hostname}]
|
90
98
|
|
91
99
|
expect(csr.subject_alt_names).to match_array(expected)
|
92
100
|
end
|
@@ -50,7 +50,7 @@ describe 'the dig function' do
|
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'errors if not given a non Collection as the starting point' do
|
53
|
-
expect { compile_to_catalog(<<-SOURCE)}.to raise_error(/'dig' parameter 'data' expects a Collection
|
53
|
+
expect { compile_to_catalog(<<-SOURCE)}.to raise_error(/'dig' parameter 'data' expects a value of type Undef or Collection, got String/)
|
54
54
|
"hello".dig(1, yes, 2)
|
55
55
|
SOURCE
|
56
56
|
end
|
@@ -66,6 +66,8 @@ describe 'when calling' do
|
|
66
66
|
name: postgres
|
67
67
|
uid: 500
|
68
68
|
gid: 500
|
69
|
+
groups:
|
70
|
+
db: 520
|
69
71
|
b:
|
70
72
|
b1: first b1
|
71
73
|
b2: first b2
|
@@ -74,6 +76,19 @@ describe 'when calling' do
|
|
74
76
|
- mod::bar
|
75
77
|
- mod::baz
|
76
78
|
empty_array: []
|
79
|
+
nested_array:
|
80
|
+
first:
|
81
|
+
- 10
|
82
|
+
- 11
|
83
|
+
second:
|
84
|
+
- 21
|
85
|
+
- 22
|
86
|
+
dotted.key:
|
87
|
+
a: dotted.key a
|
88
|
+
b: dotted.key b
|
89
|
+
dotted.array:
|
90
|
+
- a
|
91
|
+
- b
|
77
92
|
YAML
|
78
93
|
'second.yaml' => <<-YAML.unindent,
|
79
94
|
---
|
@@ -193,6 +208,14 @@ describe 'when calling' do
|
|
193
208
|
expect(func('a')).to eql('first a')
|
194
209
|
end
|
195
210
|
|
211
|
+
it 'should allow lookup with quoted dotted key' do
|
212
|
+
expect(func("'dotted.key'")).to eql({'a' => 'dotted.key a', 'b' => 'dotted.key b'})
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'should allow lookup with dotted key' do
|
216
|
+
expect(func('database_user.groups.db')).to eql(520)
|
217
|
+
end
|
218
|
+
|
196
219
|
it 'should not find data in module' do
|
197
220
|
expect(func('mod::c', 'default mod::c')).to eql('default mod::c')
|
198
221
|
end
|
@@ -292,6 +315,14 @@ describe 'when calling' do
|
|
292
315
|
expect(func('fbb', {'fbb' => 'foo_result'})).to eql(%w[mod::foo mod::bar mod::baz])
|
293
316
|
end
|
294
317
|
|
318
|
+
it 'should allow lookup with quoted dotted key' do
|
319
|
+
expect(func("'dotted.array'")).to eql(['a', 'b'])
|
320
|
+
end
|
321
|
+
|
322
|
+
it 'should fail lookup with dotted key' do
|
323
|
+
expect{ func('nested_array.0.first') }.to raise_error(/Resolution type :array is illegal when accessing values using dotted keys. Offending key was 'nested_array.0.first'/)
|
324
|
+
end
|
325
|
+
|
295
326
|
it 'should use default block' do
|
296
327
|
expect(func('foo') { |k| ['key', k] }).to eql(%w[key foo])
|
297
328
|
end
|
@@ -313,7 +344,15 @@ describe 'when calling' do
|
|
313
344
|
end
|
314
345
|
|
315
346
|
it 'should lookup and return a hash' do
|
316
|
-
expect(func('database_user')).to eql({ 'name' => 'postgres', 'uid' => 500, 'gid' => 500})
|
347
|
+
expect(func('database_user')).to eql({ 'name' => 'postgres', 'uid' => 500, 'gid' => 500, 'groups' => { 'db' => 520 }})
|
348
|
+
end
|
349
|
+
|
350
|
+
it 'should allow lookup with quoted dotted key' do
|
351
|
+
expect(func("'dotted.key'")).to eql({'a' => 'dotted.key a', 'b' => 'dotted.key b'})
|
352
|
+
end
|
353
|
+
|
354
|
+
it 'should fail lookup with dotted key' do
|
355
|
+
expect{ func('database_user.groups') }.to raise_error(/Resolution type :hash is illegal when accessing values using dotted keys. Offending key was 'database_user.groups'/)
|
317
356
|
end
|
318
357
|
|
319
358
|
it 'should log deprecation errors' do
|
@@ -383,7 +383,7 @@ describe 'The lookup function' do
|
|
383
383
|
expect { compiler.compile }.to raise_error(Puppet::ParseError, /did not find a value for the name 'bad_data::b'/)
|
384
384
|
end
|
385
385
|
warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
|
386
|
-
expect(warnings).to include("Module 'bad_data': deprecated API function
|
386
|
+
expect(warnings).to include("Module 'bad_data': Value returned from deprecated API function 'bad_data::data' must use keys qualified with the name of the module")
|
387
387
|
end
|
388
388
|
|
389
389
|
it 'will succeed finding prefixed keys even when a key in the function provided module data is not prefixed' do
|
@@ -397,7 +397,7 @@ describe 'The lookup function' do
|
|
397
397
|
expect(resources).to include('module_c')
|
398
398
|
end
|
399
399
|
warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
|
400
|
-
expect(warnings).to include("Module 'bad_data': deprecated API function
|
400
|
+
expect(warnings).to include("Module 'bad_data': Value returned from deprecated API function 'bad_data::data' must use keys qualified with the name of the module")
|
401
401
|
end
|
402
402
|
|
403
403
|
it 'will resolve global, environment, and module correctly' do
|
@@ -429,7 +429,7 @@ describe 'The lookup function' do
|
|
429
429
|
compiler.compile
|
430
430
|
end
|
431
431
|
warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
|
432
|
-
expect(warnings).to include("Module 'bad_data': deprecated API function
|
432
|
+
expect(warnings).to include("Module 'bad_data': Value returned from deprecated API function 'bad_data::data' must use keys qualified with the name of the module")
|
433
433
|
end
|
434
434
|
|
435
435
|
it 'a warning will be logged when key in the hiera provided module data is not prefixed' do
|
@@ -439,7 +439,7 @@ describe 'The lookup function' do
|
|
439
439
|
compiler.compile
|
440
440
|
end
|
441
441
|
warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
|
442
|
-
expect(warnings).to include("Module 'hieraprovider':
|
442
|
+
expect(warnings).to include("Module 'hieraprovider': Value returned from data_hash function 'json_data', when using location '#{environmentpath}/production/modules/hieraprovider/data/first.json', must use keys qualified with the name of the module")
|
443
443
|
end
|
444
444
|
end
|
445
445
|
|
@@ -514,7 +514,7 @@ describe 'The lookup function' do
|
|
514
514
|
end
|
515
515
|
expect(lookup_invocation.explainer.explain).to include(<<-EOS.unindent(' '))
|
516
516
|
Module "abc" Data Provider (hiera configuration version 5)
|
517
|
-
|
517
|
+
Deprecated API function "abc::data"
|
518
518
|
No such key: "abc::x"
|
519
519
|
EOS
|
520
520
|
end
|
@@ -530,13 +530,13 @@ describe 'The lookup function' do
|
|
530
530
|
Global Data Provider (hiera configuration version 5)
|
531
531
|
No such key: "abc::e"
|
532
532
|
Environment Data Provider (hiera configuration version 5)
|
533
|
-
|
533
|
+
Deprecated API function "environment::data"
|
534
534
|
Found key: "abc::e" value: {
|
535
535
|
"k1" => "env_e1",
|
536
536
|
"k3" => "env_e3"
|
537
537
|
}
|
538
538
|
Module "abc" Data Provider (hiera configuration version 5)
|
539
|
-
|
539
|
+
Deprecated API function "abc::data"
|
540
540
|
Found key: "abc::e" value: {
|
541
541
|
"k1" => "module_e1",
|
542
542
|
"k2" => "module_e2"
|
@@ -576,7 +576,7 @@ describe 'The lookup function' do
|
|
576
576
|
Global Data Provider (hiera configuration version 5)
|
577
577
|
No such key: "hieraprovider::test::not_found"
|
578
578
|
Environment Data Provider (hiera configuration version 5)
|
579
|
-
|
579
|
+
Deprecated API function "environment::data"
|
580
580
|
No such key: "hieraprovider::test::not_found"
|
581
581
|
Module "hieraprovider" Data Provider (hiera configuration version 4)
|
582
582
|
Using configuration "#{environmentpath}/production/modules/hieraprovider/hiera.yaml"
|
@@ -636,7 +636,7 @@ describe 'The lookup function' do
|
|
636
636
|
:branches => [
|
637
637
|
{
|
638
638
|
:type => :data_provider,
|
639
|
-
:name => '
|
639
|
+
:name => 'Deprecated API function "environment::data"',
|
640
640
|
:key => 'abc::e',
|
641
641
|
:value => { 'k1' => 'env_e1', 'k3' => 'env_e3' },
|
642
642
|
:event => :found
|
@@ -650,7 +650,7 @@ describe 'The lookup function' do
|
|
650
650
|
:branches => [
|
651
651
|
{
|
652
652
|
:type => :data_provider,
|
653
|
-
:name => '
|
653
|
+
:name => 'Deprecated API function "abc::data"',
|
654
654
|
:key => 'abc::e',
|
655
655
|
:event => :found,
|
656
656
|
:value => {
|
@@ -9,205 +9,429 @@ describe "The lookup function" do
|
|
9
9
|
include PuppetSpec::Compiler
|
10
10
|
include PuppetSpec::Files
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
12
|
+
let(:env_name) { 'spec' }
|
13
|
+
let(:code_dir_files) { {} }
|
14
|
+
let(:code_dir) { tmpdir('code') }
|
15
|
+
let(:ruby_dir) { tmpdir('ruby') }
|
16
|
+
let(:env_modules) { {} }
|
17
|
+
let(:env_hiera_yaml) do
|
18
|
+
<<-YAML.unindent
|
19
|
+
---
|
20
|
+
version: 5
|
21
|
+
hierarchy:
|
22
|
+
- name: "Common"
|
23
|
+
data_hash: yaml_data
|
24
|
+
path: "common.yaml"
|
25
|
+
YAML
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
{
|
31
|
-
'common.yaml' => <<-YAML.unindent
|
32
|
-
---
|
33
|
-
a: value a (from environment)
|
34
|
-
c:
|
35
|
-
c_b: value c_b (from environment)
|
36
|
-
mod_a::a: value mod_a::a (from environment)
|
37
|
-
mod_a::hash_a:
|
38
|
-
a: value mod_a::hash_a.a (from environment)
|
39
|
-
mod_a::hash_b:
|
40
|
-
a: value mod_a::hash_b.a (from environment)
|
41
|
-
hash_b:
|
42
|
-
hash_ba:
|
43
|
-
bab: value hash_b.hash_ba.bab (from environment)
|
44
|
-
hash_c:
|
45
|
-
hash_ca:
|
46
|
-
caa: value hash_c.hash_ca.caa (from environment)
|
47
|
-
lookup_options:
|
48
|
-
mod_a::hash_b:
|
49
|
-
merge: hash
|
50
|
-
hash_c:
|
51
|
-
merge: hash
|
52
|
-
YAML
|
53
|
-
}
|
54
|
-
end
|
28
|
+
let(:env_data) { {} }
|
55
29
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
}
|
30
|
+
let(:environment_files) do
|
31
|
+
{
|
32
|
+
env_name => {
|
33
|
+
'modules' => env_modules,
|
34
|
+
'hiera.yaml' => env_hiera_yaml,
|
35
|
+
'data' => env_data
|
63
36
|
}
|
64
|
-
|
37
|
+
}
|
38
|
+
end
|
65
39
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
end
|
87
|
-
RUBY
|
88
|
-
'other_backend.rb' => <<-RUBY.unindent,
|
89
|
-
class Hiera::Backend::Other_backend
|
90
|
-
def lookup(key, scope, order_override, resolution_type, context)
|
91
|
-
value = Hiera::Config[:other][key.to_sym]
|
92
|
-
throw :no_such_key if value.nil?
|
93
|
-
value
|
94
|
-
end
|
95
|
-
end
|
96
|
-
RUBY
|
97
|
-
}
|
98
|
-
}
|
99
|
-
}
|
100
|
-
end
|
40
|
+
let(:ruby_dir_files) { {} }
|
41
|
+
|
42
|
+
let(:logs) { [] }
|
43
|
+
let(:scope_additions ) { {} }
|
44
|
+
let(:notices) { logs.select { |log| log.level == :notice }.map { |log| log.message } }
|
45
|
+
let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
|
46
|
+
let(:debugs) { logs.select { |log| log.level == :debug }.map { |log| log.message } }
|
47
|
+
let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, env_name, 'modules')]) }
|
48
|
+
let(:environments) { Puppet::Environments::Directories.new(populated_env_dir, []) }
|
49
|
+
let(:node) { Puppet::Node.new('test_lookup', :environment => env) }
|
50
|
+
let(:compiler) { Puppet::Parser::Compiler.new(node) }
|
51
|
+
let(:lookup_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'lookup') }
|
52
|
+
let(:invocation_with_explain) { Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true) }
|
53
|
+
let(:explanation) { invocation_with_explain.explainer.explain }
|
54
|
+
|
55
|
+
let(:populated_code_dir) do
|
56
|
+
dir_contained_in(code_dir, code_dir_files)
|
57
|
+
code_dir
|
58
|
+
end
|
101
59
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
let(:debugs) { logs.select { |log| log.level == :debug }.map { |log| log.message } }
|
107
|
-
let(:env) { Puppet::Node::Environment.create(env_name.to_sym, [File.join(populated_env_dir, env_name, 'modules')]) }
|
108
|
-
let(:environments) { Puppet::Environments::Directories.new(populated_env_dir, []) }
|
109
|
-
let(:node) { Puppet::Node.new('test_lookup', :environment => env) }
|
110
|
-
let(:compiler) { Puppet::Parser::Compiler.new(node) }
|
111
|
-
let(:lookup_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'lookup') }
|
112
|
-
let(:defaults) {
|
113
|
-
{
|
114
|
-
'mod_a::xd' => 'value mod_a::xd (from default)',
|
115
|
-
'mod_a::xd_found' => 'value mod_a::xd_found (from default)',
|
116
|
-
'scope_xd' => 'value scope_xd (from default)'
|
117
|
-
}}
|
118
|
-
let(:overrides) {
|
119
|
-
{
|
120
|
-
'mod_a::xo' => 'value mod_a::xo (from override)',
|
121
|
-
'scope_xo' => 'value scope_xo (from override)'
|
122
|
-
}}
|
123
|
-
let(:invocation_with_explain) { Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true) }
|
124
|
-
let(:explanation) { invocation_with_explain.explainer.explain }
|
125
|
-
|
126
|
-
let(:populated_code_dir) do
|
127
|
-
dir_contained_in(code_dir, code_dir_files)
|
128
|
-
code_dir
|
129
|
-
end
|
60
|
+
let(:populated_ruby_dir) do
|
61
|
+
dir_contained_in(ruby_dir, ruby_dir_files)
|
62
|
+
ruby_dir
|
63
|
+
end
|
130
64
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
65
|
+
let(:env_dir) do
|
66
|
+
d = File.join(populated_code_dir, 'environments')
|
67
|
+
Dir.mkdir(d)
|
68
|
+
d
|
69
|
+
end
|
70
|
+
|
71
|
+
let(:populated_env_dir) do
|
72
|
+
dir_contained_in(env_dir, environment_files)
|
73
|
+
env_dir
|
74
|
+
end
|
135
75
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
76
|
+
before(:each) do
|
77
|
+
Puppet.settings[:codedir] = code_dir
|
78
|
+
Puppet.push_context(:environments => environments, :current_environment => env)
|
79
|
+
end
|
80
|
+
|
81
|
+
after(:each) do
|
82
|
+
Puppet.pop_context
|
83
|
+
if Object.const_defined?(:Hiera)
|
84
|
+
Hiera.send(:remove_instance_variable, :@config) if Hiera.instance_variable_defined?(:@config)
|
85
|
+
Hiera.send(:remove_instance_variable, :@logger) if Hiera.instance_variable_defined?(:@logger)
|
86
|
+
if Hiera.const_defined?(:Config)
|
87
|
+
Hiera::Config.send(:remove_instance_variable, :@config) if Hiera::Config.instance_variable_defined?(:@config)
|
88
|
+
end
|
89
|
+
if Hiera.const_defined?(:Backend) && Hiera::Backend.respond_to?(:clear!)
|
90
|
+
Hiera::Backend.clear!
|
91
|
+
end
|
140
92
|
end
|
93
|
+
end
|
141
94
|
|
142
|
-
|
143
|
-
|
144
|
-
|
95
|
+
def collect_notices(code, explain = false, &block)
|
96
|
+
Puppet[:code] = code
|
97
|
+
Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
|
98
|
+
scope = compiler.topscope
|
99
|
+
scope['environment'] = env_name
|
100
|
+
scope['domain'] = 'example.com'
|
101
|
+
scope_additions.each_pair { |k, v| scope[k] = v }
|
102
|
+
if explain
|
103
|
+
begin
|
104
|
+
invocation_with_explain.lookup('dummy', nil) do
|
105
|
+
if block_given?
|
106
|
+
compiler.compile { |catalog| block.call(compiler.topscope); catalog }
|
107
|
+
else
|
108
|
+
compiler.compile
|
109
|
+
end
|
110
|
+
end
|
111
|
+
rescue RuntimeError => e
|
112
|
+
invocation_with_explain.report_text { e.message }
|
113
|
+
end
|
114
|
+
else
|
115
|
+
if block_given?
|
116
|
+
compiler.compile { |catalog| block.call(compiler.topscope); catalog }
|
117
|
+
else
|
118
|
+
compiler.compile
|
119
|
+
end
|
120
|
+
end
|
145
121
|
end
|
122
|
+
nil
|
123
|
+
end
|
146
124
|
|
147
|
-
|
148
|
-
|
149
|
-
|
125
|
+
def lookup(key, options = {}, explain = false)
|
126
|
+
nc_opts = options.empty? ? '' : ", #{Puppet::Pops::Types::TypeFormatter.string(options)}"
|
127
|
+
keys = key.is_a?(Array) ? key : [key]
|
128
|
+
collect_notices(keys.map { |k| "notice(String(lookup('#{k}'#{nc_opts}), '%p'))" }.join("\n"), explain)
|
129
|
+
if explain
|
130
|
+
explanation
|
131
|
+
else
|
132
|
+
result = notices.map { |n| Puppet::Pops::Types::TypeParser.singleton.parse_literal(n) }
|
133
|
+
key.is_a?(Array) ? result : result[0]
|
150
134
|
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def explain(key, options = {})
|
138
|
+
lookup(key, options, true)[1]
|
139
|
+
explanation
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'with faulty hiera.yaml configuration' do
|
143
|
+
context 'in global layer' do
|
144
|
+
let(:global_data) do
|
145
|
+
{
|
146
|
+
'common.yaml' => <<-YAML.unindent
|
147
|
+
a: value a (from global)
|
148
|
+
YAML
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
let(:code_dir_files) do
|
153
|
+
{
|
154
|
+
'hiera.yaml' => hiera_yaml,
|
155
|
+
'data' => global_data
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
before(:each) do
|
160
|
+
# Need to set here since spec_helper defines these settings in its "before each"
|
161
|
+
Puppet.settings[:codedir] = populated_code_dir
|
162
|
+
Puppet.settings[:hiera_config] = File.join(code_dir, 'hiera.yaml')
|
163
|
+
end
|
151
164
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
165
|
+
context 'using a not yet supported hiera version' do
|
166
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
167
|
+
version: 6
|
168
|
+
YAML
|
169
|
+
|
170
|
+
it 'fails and reports error' do
|
171
|
+
expect { lookup('a') }.to raise_error("This runtime does not support hiera.yaml version 6 in #{code_dir}/hiera.yaml")
|
159
172
|
end
|
160
|
-
|
161
|
-
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'with multiply defined backend using hiera version 3' do
|
176
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
177
|
+
:version: 3
|
178
|
+
:backends:
|
179
|
+
- yaml
|
180
|
+
- json
|
181
|
+
- yaml
|
182
|
+
YAML
|
183
|
+
|
184
|
+
it 'fails and reports error' do
|
185
|
+
expect { lookup('a') }.to raise_error(
|
186
|
+
"Backend 'yaml' is defined more than once. First defined at line 3 at #{code_dir}/hiera.yaml:5")
|
162
187
|
end
|
163
188
|
end
|
164
|
-
end
|
165
189
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
190
|
+
context 'using hiera version 4' do
|
191
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
192
|
+
version: 4
|
193
|
+
YAML
|
194
|
+
|
195
|
+
it 'fails and reports error' do
|
196
|
+
expect { lookup('a') }.to raise_error(
|
197
|
+
"hiera.yaml version 4 cannot be used in the global layer in #{code_dir}/hiera.yaml")
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'using hiera version 5' do
|
202
|
+
context 'with multiply defined hierarchy' do
|
203
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
204
|
+
version: 5
|
205
|
+
hierarchy:
|
206
|
+
- name: Common
|
207
|
+
path: common.yaml
|
208
|
+
- name: Other
|
209
|
+
path: other.yaml
|
210
|
+
- name: Common
|
211
|
+
path: common.yaml
|
212
|
+
YAML
|
213
|
+
|
214
|
+
it 'fails and reports error' do
|
215
|
+
expect { lookup('a') }.to raise_error(
|
216
|
+
"Hierarchy name 'Common' defined more than once. First defined at line 3 at #{code_dir}/hiera.yaml:7")
|
184
217
|
end
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
218
|
+
end
|
219
|
+
|
220
|
+
context 'with hiera3_backend that is provided as data_hash function' do
|
221
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
222
|
+
version: 5
|
223
|
+
hierarchy:
|
224
|
+
- name: Common
|
225
|
+
hiera3_backend: hocon
|
226
|
+
path: common.conf
|
227
|
+
YAML
|
228
|
+
|
229
|
+
it 'fails and reports error' do
|
230
|
+
expect { lookup('a') }.to raise_error(
|
231
|
+
"Use \"data_hash: hocon_data\" instead of \"hiera3_backend: hocon\" at #{code_dir}/hiera.yaml:4")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
context 'with no data provider function defined' do
|
236
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
237
|
+
version: 5
|
238
|
+
defaults:
|
239
|
+
datadir: data
|
240
|
+
hierarchy:
|
241
|
+
- name: Common
|
242
|
+
path: common.txt
|
243
|
+
YAML
|
244
|
+
|
245
|
+
it 'fails and reports error' do
|
246
|
+
expect { lookup('a') }.to raise_error(
|
247
|
+
"One of data_hash, lookup_key, data_dig, or hiera3_backend must be defined in hierarchy 'Common' in #{code_dir}/hiera.yaml")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
context 'with multiple data providers in defaults' do
|
252
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
253
|
+
version: 5
|
254
|
+
defaults:
|
255
|
+
data_hash: yaml_data
|
256
|
+
lookup_key: eyaml_lookup_key
|
257
|
+
datadir: data
|
258
|
+
hierarchy:
|
259
|
+
- name: Common
|
260
|
+
path: common.txt
|
261
|
+
YAML
|
262
|
+
|
263
|
+
it 'fails and reports error' do
|
264
|
+
expect { lookup('a') }.to raise_error(
|
265
|
+
"Only one of data_hash, lookup_key, data_dig, or hiera3_backend can be defined in defaults in #{code_dir}/hiera.yaml")
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
context 'with non existing data provider function' do
|
270
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
271
|
+
version: 5
|
272
|
+
hierarchy:
|
273
|
+
- name: Common
|
274
|
+
data_hash: nonesuch_txt_data
|
275
|
+
path: common.yaml
|
276
|
+
YAML
|
277
|
+
|
278
|
+
it 'fails and reports error' do
|
279
|
+
Puppet[:strict] = :error
|
280
|
+
expect { lookup('a') }.to raise_error(
|
281
|
+
"Unable to find 'data_hash' function named 'nonesuch_txt_data' in #{code_dir}/hiera.yaml")
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context 'with a declared default_hierarchy' do
|
286
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
287
|
+
version: 5
|
288
|
+
hierarchy:
|
289
|
+
- name: Common
|
290
|
+
path: common.yaml
|
291
|
+
default_hierarchy:
|
292
|
+
- name: Defaults
|
293
|
+
path: defaults.yaml
|
294
|
+
YAML
|
295
|
+
|
296
|
+
it 'fails and reports error' do
|
297
|
+
Puppet[:strict] = :error
|
298
|
+
expect { lookup('a') }.to raise_error(
|
299
|
+
"'default_hierarchy' is only allowed in the module layer at #{code_dir}/hiera.yaml:5")
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context 'with missing variables' do
|
304
|
+
let(:scope_additions) { { 'fqdn' => 'test.example.com' } }
|
305
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
306
|
+
version: 5
|
307
|
+
hierarchy:
|
308
|
+
- name: Common # don't report this line %{::nonesuch}
|
309
|
+
path: "%{::fqdn}/%{::nonesuch}/data.yaml"
|
310
|
+
YAML
|
311
|
+
|
312
|
+
it 'fails and reports errors when strict == error' do
|
313
|
+
Puppet[:strict] = :error
|
314
|
+
expect { lookup('a') }.to raise_error("Undefined variable '::nonesuch' at #{code_dir}/hiera.yaml:4")
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
context 'using interpolation functions' do
|
319
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
320
|
+
version: 5
|
321
|
+
hierarchy:
|
322
|
+
- name: Common # don't report this line %{::nonesuch}
|
323
|
+
path: "%{lookup('fqdn')}/data.yaml"
|
324
|
+
YAML
|
325
|
+
|
326
|
+
it 'fails and reports errors when strict == error' do
|
327
|
+
Puppet[:strict] = :error
|
328
|
+
expect { lookup('a') }.to raise_error("Interpolation using method syntax is not allowed in this context in #{code_dir}/hiera.yaml")
|
190
329
|
end
|
191
330
|
end
|
192
331
|
end
|
193
|
-
nil
|
194
332
|
end
|
195
333
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
334
|
+
context 'in environment layer' do
|
335
|
+
context 'using hiera version 4' do
|
336
|
+
context 'with an unknown backend' do
|
337
|
+
let(:env_hiera_yaml) { <<-YAML.unindent }
|
338
|
+
version: 4
|
339
|
+
hierarchy:
|
340
|
+
- name: Common
|
341
|
+
backend: nonesuch
|
342
|
+
path: common.yaml
|
343
|
+
YAML
|
344
|
+
|
345
|
+
it 'fails and reports error' do
|
346
|
+
expect { lookup('a') }.to raise_error(
|
347
|
+
"No data provider is registered for backend 'nonesuch' at #{env_dir}/spec/hiera.yaml:4")
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
context 'with multiply defined hierarchy' do
|
352
|
+
let(:env_hiera_yaml) { <<-YAML.unindent }
|
353
|
+
version: 4
|
354
|
+
hierarchy:
|
355
|
+
- name: Common
|
356
|
+
backend: yaml
|
357
|
+
path: common.yaml
|
358
|
+
- name: Other
|
359
|
+
backend: yaml
|
360
|
+
path: other.yaml
|
361
|
+
- name: Common
|
362
|
+
backend: yaml
|
363
|
+
path: common.yaml
|
364
|
+
YAML
|
365
|
+
|
366
|
+
it 'fails and reports error' do
|
367
|
+
expect { lookup('a') }.to raise_error(
|
368
|
+
"Hierarchy name 'Common' defined more than once. First defined at line 3 at #{env_dir}/spec/hiera.yaml:9")
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
context 'using hiera version 5' do
|
374
|
+
context 'with a hiera3_backend declaration' do
|
375
|
+
let(:env_hiera_yaml) { <<-YAML.unindent }
|
376
|
+
version: 5
|
377
|
+
hierarchy:
|
378
|
+
- name: Common
|
379
|
+
hiera3_backend: something
|
380
|
+
YAML
|
381
|
+
|
382
|
+
it 'fails and reports error' do
|
383
|
+
expect { lookup('a') }.to raise_error(
|
384
|
+
"'hiera3_backend' is only allowed in the global layer at #{env_dir}/spec/hiera.yaml:4")
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
context 'with a declared default_hierarchy' do
|
389
|
+
let(:env_hiera_yaml) { <<-YAML.unindent }
|
390
|
+
version: 5
|
391
|
+
hierarchy:
|
392
|
+
- name: Common
|
393
|
+
path: common.yaml
|
394
|
+
default_hierarchy:
|
395
|
+
- name: Defaults
|
396
|
+
path: defaults.yaml
|
397
|
+
YAML
|
398
|
+
|
399
|
+
it 'fails and reports error' do
|
400
|
+
Puppet[:strict] = :error
|
401
|
+
expect { lookup('a') }.to raise_error(
|
402
|
+
"'default_hierarchy' is only allowed in the module layer at #{env_dir}/spec/hiera.yaml:5")
|
403
|
+
end
|
404
|
+
end
|
205
405
|
end
|
206
406
|
end
|
407
|
+
end
|
207
408
|
|
208
|
-
|
209
|
-
|
210
|
-
|
409
|
+
context 'with an environment' do
|
410
|
+
let(:env_data) do
|
411
|
+
{
|
412
|
+
'common.yaml' => <<-YAML.unindent
|
413
|
+
---
|
414
|
+
a: value a (from environment)
|
415
|
+
c:
|
416
|
+
c_b: value c_b (from environment)
|
417
|
+
mod_a::a: value mod_a::a (from environment)
|
418
|
+
mod_a::hash_a:
|
419
|
+
a: value mod_a::hash_a.a (from environment)
|
420
|
+
mod_a::hash_b:
|
421
|
+
a: value mod_a::hash_b.a (from environment)
|
422
|
+
hash_b:
|
423
|
+
hash_ba:
|
424
|
+
bab: value hash_b.hash_ba.bab (from environment)
|
425
|
+
hash_c:
|
426
|
+
hash_ca:
|
427
|
+
caa: value hash_c.hash_ca.caa (from environment)
|
428
|
+
lookup_options:
|
429
|
+
mod_a::hash_b:
|
430
|
+
merge: hash
|
431
|
+
hash_c:
|
432
|
+
merge: hash
|
433
|
+
YAML
|
434
|
+
}
|
211
435
|
end
|
212
436
|
|
213
437
|
it 'finds data in the environment' do
|
@@ -303,7 +527,7 @@ describe "The lookup function" do
|
|
303
527
|
hierarchy:
|
304
528
|
- name: "Varying"
|
305
529
|
data_hash: yaml_data
|
306
|
-
path: "
|
530
|
+
path: "#{data_path}"
|
307
531
|
YAML
|
308
532
|
end
|
309
533
|
|
@@ -315,83 +539,144 @@ describe "The lookup function" do
|
|
315
539
|
'data' => {
|
316
540
|
'x.yaml' => <<-YAML.unindent,
|
317
541
|
y: value y from x
|
318
|
-
|
542
|
+
YAML
|
319
543
|
'x_d.yaml' => <<-YAML.unindent,
|
320
544
|
y: value y from x_d
|
321
|
-
|
322
|
-
'x_e.yaml' => <<-YAML.unindent
|
545
|
+
YAML
|
546
|
+
'x_e.yaml' => <<-YAML.unindent,
|
323
547
|
y: value y from x_e
|
324
|
-
|
548
|
+
YAML
|
325
549
|
}
|
326
550
|
}
|
327
551
|
}
|
328
552
|
end
|
329
553
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
554
|
+
context 'using local variable reference' do
|
555
|
+
let(:data_path) { 'x%{var.sub}.yaml' }
|
556
|
+
|
557
|
+
it 'reloads the configuration if interpolated values change' do
|
558
|
+
Puppet[:log_level] = 'debug'
|
559
|
+
collect_notices("notice('success')") do |scope|
|
560
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x')
|
561
|
+
scope['var'] = { 'sub' => '_d' }
|
562
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
|
563
|
+
nested_scope = scope.compiler.newscope(scope)
|
564
|
+
nested_scope['var'] = { 'sub' => '_e' }
|
565
|
+
expect(lookup_func.call(nested_scope, 'y')).to eql('value y from x_e')
|
566
|
+
end
|
567
|
+
expect(notices).to eql(['success'])
|
568
|
+
expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_truthy
|
569
|
+
end
|
570
|
+
|
571
|
+
it 'does not include the lookups performed during stability check in explain output' do
|
572
|
+
Puppet[:log_level] = 'debug'
|
573
|
+
collect_notices("notice('success')") do |scope|
|
574
|
+
var = { 'sub' => '_d' }
|
575
|
+
scope['var'] = var
|
576
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
|
577
|
+
|
578
|
+
# Second call triggers the check
|
579
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
|
580
|
+
end
|
581
|
+
expect(notices).to eql(['success'])
|
582
|
+
expect(debugs.any? { |m| m =~ /Sub key: "sub"/ }).to be_falsey
|
339
583
|
end
|
340
|
-
expect(notices).to eql(['success'])
|
341
|
-
expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_truthy
|
342
584
|
end
|
343
585
|
|
344
|
-
|
345
|
-
|
346
|
-
collect_notices("notice('success')") do |scope|
|
347
|
-
var = { 'sub' => '_d' }
|
348
|
-
scope['var'] = var
|
349
|
-
expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
|
586
|
+
context 'using global variable reference' do
|
587
|
+
let(:data_path) { 'x%{::var.sub}.yaml' }
|
350
588
|
|
351
|
-
|
352
|
-
|
589
|
+
it 'reloads the configuration if interpolated that was previously undefined, gets defined' do
|
590
|
+
Puppet[:log_level] = 'debug'
|
591
|
+
collect_notices("notice('success')") do |scope|
|
592
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x')
|
593
|
+
scope['var'] = { 'sub' => '_d' }
|
594
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
|
595
|
+
end
|
596
|
+
expect(notices).to eql(['success'])
|
597
|
+
expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_truthy
|
598
|
+
end
|
599
|
+
|
600
|
+
it 'does not reload the configuration if value changes locally' do
|
601
|
+
Puppet[:log_level] = 'debug'
|
602
|
+
collect_notices("notice('success')") do |scope|
|
603
|
+
scope['var'] = { 'sub' => '_d' }
|
604
|
+
expect(lookup_func.call(scope, 'y')).to eql('value y from x_d')
|
605
|
+
nested_scope = scope.compiler.newscope(scope)
|
606
|
+
nested_scope['var'] = { 'sub' => '_e' }
|
607
|
+
expect(lookup_func.call(nested_scope, 'y')).to eql('value y from x_d')
|
608
|
+
end
|
609
|
+
expect(notices).to eql(['success'])
|
610
|
+
expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_falsey
|
353
611
|
end
|
354
|
-
expect(notices).to eql(['success'])
|
355
|
-
expect(debugs.any? { |m| m =~ /Sub key: "sub"/ }).to be_falsey
|
356
612
|
end
|
357
613
|
end
|
358
614
|
|
359
|
-
context 'that uses reserved
|
360
|
-
|
361
|
-
{
|
362
|
-
env_name => {
|
363
|
-
'hiera.yaml' => <<-YAML.unindent,
|
364
|
-
---
|
365
|
-
version: 5
|
366
|
-
hierarchy:
|
367
|
-
- name: "Illegal"
|
368
|
-
options:
|
369
|
-
#{opt_spec}
|
370
|
-
data_hash: yaml_data
|
371
|
-
YAML
|
372
|
-
'data' => {
|
373
|
-
'foo.yaml' => "a: The value a\n"
|
374
|
-
}
|
375
|
-
}
|
376
|
-
}
|
615
|
+
context 'that uses reserved' do
|
616
|
+
let(:environment_files) do
|
617
|
+
{ env_name => { 'hiera.yaml' => hiera_yaml } }
|
377
618
|
end
|
378
619
|
|
379
|
-
context '
|
380
|
-
|
620
|
+
context 'option' do
|
621
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
622
|
+
version: 5
|
623
|
+
hierarchy:
|
624
|
+
- name: "Illegal"
|
625
|
+
options:
|
626
|
+
#{opt_spec}
|
627
|
+
data_hash: yaml_data
|
628
|
+
YAML
|
381
629
|
|
382
|
-
|
383
|
-
|
384
|
-
|
630
|
+
context 'path' do
|
631
|
+
let(:opt_spec) { 'path: data/foo.yaml' }
|
632
|
+
|
633
|
+
it 'fails and reports the reserved option key' do
|
634
|
+
expect { lookup('a') }.to raise_error do |e|
|
635
|
+
expect(e.message).to match(/Option key 'path' used in hierarchy 'Illegal' is reserved by Puppet/)
|
636
|
+
end
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
context 'uri' do
|
641
|
+
let(:opt_spec) { 'uri: file:///data/foo.yaml' }
|
642
|
+
|
643
|
+
it 'fails and reports the reserved option key' do
|
644
|
+
expect { lookup('a') }.to raise_error do |e|
|
645
|
+
expect(e.message).to match(/Option key 'uri' used in hierarchy 'Illegal' is reserved by Puppet/)
|
646
|
+
end
|
385
647
|
end
|
386
648
|
end
|
387
649
|
end
|
388
650
|
|
389
|
-
context '
|
390
|
-
let(:
|
651
|
+
context 'default option' do
|
652
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
653
|
+
---
|
654
|
+
version: 5
|
655
|
+
defaults:
|
656
|
+
options:
|
657
|
+
#{opt_spec}
|
658
|
+
hierarchy:
|
659
|
+
- name: "Illegal"
|
660
|
+
data_hash: yaml_data
|
661
|
+
YAML
|
391
662
|
|
392
|
-
|
393
|
-
|
394
|
-
|
663
|
+
context 'path' do
|
664
|
+
let(:opt_spec) { 'path: data/foo.yaml' }
|
665
|
+
|
666
|
+
it 'fails and reports the reserved option key' do
|
667
|
+
expect { lookup('a') }.to raise_error do |e|
|
668
|
+
expect(e.message).to match(/Option key 'path' used in defaults is reserved by Puppet/)
|
669
|
+
end
|
670
|
+
end
|
671
|
+
end
|
672
|
+
|
673
|
+
context 'uri' do
|
674
|
+
let(:opt_spec) { 'uri: file:///data/foo.yaml' }
|
675
|
+
|
676
|
+
it 'fails and reports the reserved option key' do
|
677
|
+
expect { lookup('a') }.to raise_error do |e|
|
678
|
+
expect(e.message).to match(/Option key 'uri' used in defaults is reserved by Puppet/)
|
679
|
+
end
|
395
680
|
end
|
396
681
|
end
|
397
682
|
end
|
@@ -505,7 +790,31 @@ describe "The lookup function" do
|
|
505
790
|
|
506
791
|
it 'fails lookup and reports a type mismatch' do
|
507
792
|
expect { lookup('a') }.to raise_error do |e|
|
508
|
-
expect(e.message).to match(/
|
793
|
+
expect(e.message).to match(/key 'a'.*data_hash function 'yaml_data'.*using location.*wrong type, expects Puppet::LookupValue, got Runtime/)
|
794
|
+
end
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
context 'that contains illegal interpolations' do
|
799
|
+
context 'in the form of an alias that is not the entire string' do
|
800
|
+
let(:common_yaml) { <<-YAML.unindent }
|
801
|
+
a: "%{alias('x')} and then some"
|
802
|
+
x: value x
|
803
|
+
YAML
|
804
|
+
|
805
|
+
it 'fails lookup and reports a type mismatch' do
|
806
|
+
expect { lookup('a') }.to raise_error("'alias' interpolation is only permitted if the expression is equal to the entire string")
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
810
|
+
context 'in the form of an unknown function name' do
|
811
|
+
let(:common_yaml) { <<-YAML.unindent }
|
812
|
+
a: "%{what('x')}"
|
813
|
+
x: value x
|
814
|
+
YAML
|
815
|
+
|
816
|
+
it 'fails lookup and reports a type mismatch' do
|
817
|
+
expect { lookup('a') }.to raise_error("Unknown interpolation method 'what'")
|
509
818
|
end
|
510
819
|
end
|
511
820
|
end
|
@@ -561,56 +870,59 @@ describe "The lookup function" do
|
|
561
870
|
YAML
|
562
871
|
end
|
563
872
|
|
873
|
+
let(:env_lookup_options) { <<-YAML.unindent }
|
874
|
+
lookup_options:
|
875
|
+
b:
|
876
|
+
merge: hash
|
877
|
+
'^[^b]$':
|
878
|
+
merge: deep
|
879
|
+
'^c':
|
880
|
+
merge: first
|
881
|
+
'^b':
|
882
|
+
merge: first
|
883
|
+
'^mod::ha.*_b':
|
884
|
+
merge: hash
|
885
|
+
YAML
|
886
|
+
|
564
887
|
let(:env_data) do
|
565
888
|
{
|
566
|
-
'first.yaml' => <<-YAML.unindent,
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
aa:
|
604
|
-
aab: a.aa.aab
|
605
|
-
b:
|
606
|
-
ba:
|
607
|
-
bab: b.ba.bab
|
608
|
-
bb:
|
609
|
-
bbb: b.bb.bbb
|
610
|
-
c:
|
611
|
-
ca:
|
612
|
-
cab: c.ca.cab
|
613
|
-
YAML
|
889
|
+
'first.yaml' => <<-YAML.unindent + env_lookup_options,
|
890
|
+
a:
|
891
|
+
aa:
|
892
|
+
aaa: a.aa.aaa
|
893
|
+
b:
|
894
|
+
ba:
|
895
|
+
baa: b.ba.baa
|
896
|
+
bb:
|
897
|
+
bba: b.bb.bba
|
898
|
+
c:
|
899
|
+
ca:
|
900
|
+
caa: c.ca.caa
|
901
|
+
mod::hash_a:
|
902
|
+
aa:
|
903
|
+
aab: aab (from environment)
|
904
|
+
ab:
|
905
|
+
aba: aba (from environment)
|
906
|
+
abb: abb (from environment)
|
907
|
+
mod::hash_b:
|
908
|
+
ba:
|
909
|
+
bab: bab (from environment)
|
910
|
+
bc:
|
911
|
+
bca: bca (from environment)
|
912
|
+
YAML
|
913
|
+
'second.yaml' => <<-YAML.unindent,
|
914
|
+
a:
|
915
|
+
aa:
|
916
|
+
aab: a.aa.aab
|
917
|
+
b:
|
918
|
+
ba:
|
919
|
+
bab: b.ba.bab
|
920
|
+
bb:
|
921
|
+
bbb: b.bb.bbb
|
922
|
+
c:
|
923
|
+
ca:
|
924
|
+
cab: c.ca.cab
|
925
|
+
YAML
|
614
926
|
}
|
615
927
|
end
|
616
928
|
|
@@ -671,26 +983,24 @@ describe "The lookup function" do
|
|
671
983
|
expect { lookup('mod::a') }.to raise_error(Puppet::DataBinding::LookupError, /all lookup_options patterns must match a key starting with module name/)
|
672
984
|
end
|
673
985
|
end
|
674
|
-
end
|
675
|
-
|
676
|
-
context 'and a global Hiera v4 configuration' do
|
677
|
-
let(:code_dir_files) do
|
678
|
-
{
|
679
|
-
'hiera.yaml' => <<-YAML.unindent,
|
680
|
-
---
|
681
|
-
version: 4
|
682
|
-
YAML
|
683
|
-
}
|
684
|
-
end
|
685
986
|
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
987
|
+
context 'and there are no lookup options that do not use patterns' do
|
988
|
+
|
989
|
+
let(:env_lookup_options) { <<-YAML.unindent }
|
990
|
+
lookup_options:
|
991
|
+
'^[^b]$':
|
992
|
+
merge: deep
|
993
|
+
'^c':
|
994
|
+
merge: first
|
995
|
+
'^b':
|
996
|
+
merge: first
|
997
|
+
'^mod::ha.*_b':
|
998
|
+
merge: hash
|
999
|
+
YAML
|
691
1000
|
|
692
|
-
|
693
|
-
|
1001
|
+
it 'finds lookup_options that matches a pattern' do
|
1002
|
+
expect(lookup('a')).to eql({'aa' => { 'aaa' => 'a.aa.aaa', 'aab' => 'a.aa.aab' }})
|
1003
|
+
end
|
694
1004
|
end
|
695
1005
|
end
|
696
1006
|
|
@@ -732,6 +1042,30 @@ describe "The lookup function" do
|
|
732
1042
|
}
|
733
1043
|
}
|
734
1044
|
end
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
context 'and an environment Hiera v5 configuration using mapped_paths' do
|
1048
|
+
let(:scope_additions) do
|
1049
|
+
{
|
1050
|
+
'mapped' => {
|
1051
|
+
'array_var' => ['a', 'b', 'c'],
|
1052
|
+
'hash_var' => { 'x' => 'a', 'y' => 'b', 'z' => 'c' },
|
1053
|
+
'string_var' => 's' },
|
1054
|
+
'var' => 'global_var' # overridden by mapped path variable
|
1055
|
+
}
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
let(:env_hiera_yaml) do
|
1059
|
+
<<-YAML.unindent
|
1060
|
+
---
|
1061
|
+
version: 5
|
1062
|
+
hierarchy:
|
1063
|
+
- name: Mapped Paths
|
1064
|
+
mapped_paths: #{mapped_paths}
|
1065
|
+
- name: Global Path
|
1066
|
+
path: "%{var}.yaml"
|
1067
|
+
YAML
|
1068
|
+
end
|
735
1069
|
|
736
1070
|
let(:environment_files) do
|
737
1071
|
{
|
@@ -742,20 +1076,199 @@ describe "The lookup function" do
|
|
742
1076
|
}
|
743
1077
|
end
|
744
1078
|
|
745
|
-
|
746
|
-
|
747
|
-
|
1079
|
+
context 'that originates from an array' do
|
1080
|
+
let (:mapped_paths) { '[mapped.array_var, var, "paths/%{var}.yaml"]' }
|
1081
|
+
|
1082
|
+
let(:env_data) do
|
1083
|
+
{
|
1084
|
+
'paths' => {
|
1085
|
+
'a.yaml' => <<-YAML.unindent,
|
1086
|
+
path_a: value path_a
|
1087
|
+
path_h:
|
1088
|
+
a: value path_h.a
|
1089
|
+
c: value path_h.c
|
1090
|
+
YAML
|
1091
|
+
'b.yaml' => <<-YAML.unindent,
|
1092
|
+
path_h:
|
1093
|
+
b: value path_h.b
|
1094
|
+
d: value path_h.d
|
1095
|
+
YAML
|
1096
|
+
'd.yaml' => <<-YAML.unindent
|
1097
|
+
path_h:
|
1098
|
+
b: value path_h.b (from d.yaml)
|
1099
|
+
d: value path_h.d (from d.yaml)
|
1100
|
+
YAML
|
1101
|
+
},
|
1102
|
+
'global_var.yaml' => <<-YAML.unindent,
|
1103
|
+
path_h:
|
1104
|
+
e: value path_h.e
|
1105
|
+
YAML
|
1106
|
+
'other_var.yaml' => <<-YAML.unindent
|
1107
|
+
path_h:
|
1108
|
+
e: value path_h.e (from other_var.yaml)
|
1109
|
+
YAML
|
1110
|
+
}
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
it 'finds environment data using mapped_paths' do
|
1114
|
+
expect(lookup('path_a')).to eql('value path_a')
|
1115
|
+
expect(warnings).to be_empty
|
1116
|
+
end
|
1117
|
+
|
1118
|
+
it 'includes mapped path in explain output' do
|
1119
|
+
explanation = explain('path_h', 'merge' => 'deep')
|
1120
|
+
['a', 'b', 'c'].each do |var|
|
1121
|
+
expect(explanation).to match(/^\s+Path "#{env_dir}\/spec\/data\/paths\/#{var}\.yaml"\n\s+Original path: "paths\/%\{var\}\.yaml"/)
|
1122
|
+
end
|
1123
|
+
expect(warnings).to be_empty
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
it 'performs merges between mapped paths and global path interpolated using same key' do
|
1127
|
+
expect(lookup('path_h', 'merge' => 'hash')).to eql(
|
1128
|
+
{
|
1129
|
+
'a' => 'value path_h.a',
|
1130
|
+
'b' => 'value path_h.b',
|
1131
|
+
'c' => 'value path_h.c',
|
1132
|
+
'd' => 'value path_h.d',
|
1133
|
+
'e' => 'value path_h.e'
|
1134
|
+
})
|
1135
|
+
expect(warnings).to be_empty
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
it 'keeps track of changes in key overridden by interpolated key' do
|
1139
|
+
Puppet[:log_level] = 'debug'
|
1140
|
+
collect_notices("notice('success')") do |scope|
|
1141
|
+
expect(lookup_func.call(scope, 'path_h', 'merge' => 'hash')).to eql(
|
1142
|
+
{
|
1143
|
+
'a' => 'value path_h.a',
|
1144
|
+
'b' => 'value path_h.b',
|
1145
|
+
'c' => 'value path_h.c',
|
1146
|
+
'd' => 'value path_h.d',
|
1147
|
+
'e' => 'value path_h.e'
|
1148
|
+
})
|
1149
|
+
scope.with_local_scope('var' => 'other_var') do
|
1150
|
+
expect(lookup_func.call(scope, 'path_h', 'merge' => 'hash')).to eql(
|
1151
|
+
{
|
1152
|
+
'a' => 'value path_h.a',
|
1153
|
+
'b' => 'value path_h.b',
|
1154
|
+
'c' => 'value path_h.c',
|
1155
|
+
'd' => 'value path_h.d',
|
1156
|
+
'e' => 'value path_h.e (from other_var.yaml)'
|
1157
|
+
})
|
1158
|
+
end
|
1159
|
+
end
|
1160
|
+
expect(notices).to eql(['success'])
|
1161
|
+
expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_truthy
|
1162
|
+
end
|
1163
|
+
|
1164
|
+
it 'keeps track of changes in elements of mapped key' do
|
1165
|
+
Puppet[:log_level] = 'debug'
|
1166
|
+
collect_notices("notice('success')") do |scope|
|
1167
|
+
expect(lookup_func.call(scope, 'path_h', 'merge' => 'hash')).to eql(
|
1168
|
+
{
|
1169
|
+
'a' => 'value path_h.a',
|
1170
|
+
'b' => 'value path_h.b',
|
1171
|
+
'c' => 'value path_h.c',
|
1172
|
+
'd' => 'value path_h.d',
|
1173
|
+
'e' => 'value path_h.e'
|
1174
|
+
})
|
1175
|
+
scope['mapped']['array_var'] = ['a', 'c', 'd']
|
1176
|
+
expect(lookup_func.call(scope, 'path_h', 'merge' => 'hash')).to eql(
|
1177
|
+
{
|
1178
|
+
'a' => 'value path_h.a',
|
1179
|
+
'b' => 'value path_h.b (from d.yaml)',
|
1180
|
+
'c' => 'value path_h.c',
|
1181
|
+
'd' => 'value path_h.d (from d.yaml)',
|
1182
|
+
'e' => 'value path_h.e'
|
1183
|
+
})
|
1184
|
+
end
|
1185
|
+
expect(notices).to eql(['success'])
|
1186
|
+
expect(debugs.any? { |m| m =~ /Hiera configuration recreated due to change of scope variables used in interpolation expressions/ }).to be_truthy
|
1187
|
+
end
|
1188
|
+
end
|
1189
|
+
|
1190
|
+
context 'that originates from a hash' do
|
1191
|
+
let (:mapped_paths) { '[mapped.hash_var, var, "paths/%{var.0}.%{var.1}.yaml"]' }
|
1192
|
+
|
1193
|
+
let(:env_data) do
|
1194
|
+
{
|
1195
|
+
'paths' => {
|
1196
|
+
'x.a.yaml' => <<-YAML.unindent,
|
1197
|
+
path_xa: value path_xa
|
1198
|
+
path_m:
|
1199
|
+
a: value path_m.a
|
1200
|
+
c: value path_m.c
|
1201
|
+
YAML
|
1202
|
+
'y.b.yaml' => <<-YAML.unindent
|
1203
|
+
path_m:
|
1204
|
+
b: value path_m.b
|
1205
|
+
d: value path_m.d
|
1206
|
+
YAML
|
1207
|
+
},
|
1208
|
+
'global_var.yaml' => <<-YAML.unindent
|
1209
|
+
path_m:
|
1210
|
+
e: value path_m.e
|
1211
|
+
YAML
|
1212
|
+
}
|
1213
|
+
end
|
1214
|
+
|
1215
|
+
it 'finds environment data using mapped_paths' do
|
1216
|
+
expect(lookup('path_xa')).to eql('value path_xa')
|
1217
|
+
expect(warnings).to be_empty
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
it 'includes mapped path in explain output' do
|
1221
|
+
explanation = explain('path_h', 'merge' => 'deep')
|
1222
|
+
['x\.a', 'y\.b', 'z\.c'].each do |var|
|
1223
|
+
expect(explanation).to match(/^\s+Path "#{env_dir}\/spec\/data\/paths\/#{var}\.yaml"\n\s+Original path: "paths\/%\{var\.0\}\.%\{var\.1\}\.yaml"/)
|
1224
|
+
end
|
1225
|
+
expect(warnings).to be_empty
|
1226
|
+
end
|
1227
|
+
|
1228
|
+
it 'performs merges between mapped paths' do
|
1229
|
+
expect(lookup('path_m', 'merge' => 'hash')).to eql(
|
1230
|
+
{
|
1231
|
+
'a' => 'value path_m.a',
|
1232
|
+
'b' => 'value path_m.b',
|
1233
|
+
'c' => 'value path_m.c',
|
1234
|
+
'd' => 'value path_m.d',
|
1235
|
+
'e' => 'value path_m.e'
|
1236
|
+
})
|
1237
|
+
expect(warnings).to be_empty
|
1238
|
+
end
|
748
1239
|
end
|
749
1240
|
|
750
|
-
|
751
|
-
|
1241
|
+
context 'that originates from a string' do
|
1242
|
+
let (:mapped_paths) { '[mapped.string_var, var, "paths/%{var}.yaml"]' }
|
1243
|
+
|
1244
|
+
let(:env_data) do
|
752
1245
|
{
|
753
|
-
'
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
1246
|
+
'paths' => {
|
1247
|
+
's.yaml' => <<-YAML.unindent,
|
1248
|
+
path_s: value path_s
|
1249
|
+
YAML
|
1250
|
+
}
|
1251
|
+
}
|
1252
|
+
end
|
1253
|
+
|
1254
|
+
it 'includes mapped path in explain output' do
|
1255
|
+
expect(explain('path_s')).to match(/^\s+Path "#{env_dir}\/spec\/data\/paths\/s\.yaml"\n\s+Original path: "paths\/%\{var\}\.yaml"/)
|
1256
|
+
expect(warnings).to be_empty
|
1257
|
+
end
|
1258
|
+
|
1259
|
+
it 'finds environment data using mapped_paths' do
|
1260
|
+
expect(lookup('path_s')).to eql('value path_s')
|
1261
|
+
expect(warnings).to be_empty
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
context 'where the enty does not exist' do
|
1266
|
+
let (:mapped_paths) { '[mapped.nosuch_var, var, "paths/%{var}.yaml"]' }
|
1267
|
+
|
1268
|
+
it 'finds environment data using mapped_paths' do
|
1269
|
+
expect(explain('hello')).to match(/No such key: "hello"/)
|
1270
|
+
expect(warnings).to be_empty
|
1271
|
+
end
|
759
1272
|
end
|
760
1273
|
end
|
761
1274
|
|
@@ -784,7 +1297,7 @@ describe "The lookup function" do
|
|
784
1297
|
|
785
1298
|
it 'will raise an error if --strict is set to error' do
|
786
1299
|
Puppet[:strict] = :error
|
787
|
-
expect { lookup('g') }.to raise_error(Puppet::Error, /hiera
|
1300
|
+
expect { lookup('g') }.to raise_error(Puppet::Error, /hiera.yaml version 3 cannot be used in an environment/)
|
788
1301
|
end
|
789
1302
|
|
790
1303
|
it 'will log a warning and ignore the file if --strict is set to warning' do
|
@@ -879,6 +1392,9 @@ describe "The lookup function" do
|
|
879
1392
|
hash_c:
|
880
1393
|
hash_ca:
|
881
1394
|
cab: value hash_c.hash_ca.cab (from global)
|
1395
|
+
ipl_hiera_env: "environment value '%{hiera('mod_a::hash_a.a')}'"
|
1396
|
+
ipl_hiera_mod: "module value '%{hiera('mod_a::abc')}'"
|
1397
|
+
ipl_hiera_modc: "module value '%{hiera('mod_a::caller')}'"
|
882
1398
|
YAML
|
883
1399
|
'example.com.yaml' => <<-YAML.unindent,
|
884
1400
|
x: value x (from global example.com.yaml)
|
@@ -905,6 +1421,44 @@ describe "The lookup function" do
|
|
905
1421
|
}
|
906
1422
|
end
|
907
1423
|
|
1424
|
+
let(:ruby_dir_files) do
|
1425
|
+
{
|
1426
|
+
'hiera' => {
|
1427
|
+
'backend' => {
|
1428
|
+
'custom_backend.rb' => <<-RUBY.unindent,
|
1429
|
+
class Hiera::Backend::Custom_backend
|
1430
|
+
def lookup(key, scope, order_override, resolution_type, context)
|
1431
|
+
case key
|
1432
|
+
when 'hash_c'
|
1433
|
+
{ 'hash_ca' => { 'cad' => 'value hash_c.hash_ca.cad (from global custom)' }}
|
1434
|
+
when 'hash'
|
1435
|
+
{ 'array' => [ 'x5,x6' ] }
|
1436
|
+
when 'array'
|
1437
|
+
[ 'x5,x6' ]
|
1438
|
+
when 'datasources'
|
1439
|
+
Hiera::Backend.datasources(scope, order_override) { |source| source }
|
1440
|
+
when 'dotted.key'
|
1441
|
+
'custom backend received request for dotted.key value'
|
1442
|
+
else
|
1443
|
+
throw :no_such_key
|
1444
|
+
end
|
1445
|
+
end
|
1446
|
+
end
|
1447
|
+
RUBY
|
1448
|
+
'other_backend.rb' => <<-RUBY.unindent,
|
1449
|
+
class Hiera::Backend::Other_backend
|
1450
|
+
def lookup(key, scope, order_override, resolution_type, context)
|
1451
|
+
value = Hiera::Config[:other][key.to_sym]
|
1452
|
+
throw :no_such_key if value.nil?
|
1453
|
+
value
|
1454
|
+
end
|
1455
|
+
end
|
1456
|
+
RUBY
|
1457
|
+
}
|
1458
|
+
}
|
1459
|
+
}
|
1460
|
+
end
|
1461
|
+
|
908
1462
|
before(:each) do
|
909
1463
|
# Need to set here since spec_helper defines these settings in its "before each"
|
910
1464
|
Puppet.settings[:codedir] = populated_code_dir
|
@@ -929,7 +1483,7 @@ describe "The lookup function" do
|
|
929
1483
|
end
|
930
1484
|
|
931
1485
|
context 'version 3' do
|
932
|
-
it 'finds data in
|
1486
|
+
it 'finds data in in global layer and reports deprecation warnings for hiera.yaml' do
|
933
1487
|
expect(lookup('a')).to eql('value a (from global)')
|
934
1488
|
expect(warnings).to include(/Use of 'hiera.yaml' version 3 is deprecated. It should be converted to version 5/)
|
935
1489
|
end
|
@@ -981,6 +1535,64 @@ describe "The lookup function" do
|
|
981
1535
|
expect(lookup('xs.subkey')).to eql('value xs.subkey (from global hocon)')
|
982
1536
|
end
|
983
1537
|
|
1538
|
+
context 'with a module data provider' do
|
1539
|
+
let(:module_files) do
|
1540
|
+
{
|
1541
|
+
'mod_a' => {
|
1542
|
+
'hiera.yaml' => <<-YAML.unindent,
|
1543
|
+
version: 5
|
1544
|
+
hierarchy:
|
1545
|
+
- name: Common
|
1546
|
+
path: common.yaml
|
1547
|
+
YAML
|
1548
|
+
'data' => {
|
1549
|
+
'common.yaml' => <<-YAML.unindent
|
1550
|
+
mod_a::abc: value mod_a::abc (from module)
|
1551
|
+
mod_a::caller: "calling module is %{calling_module}"
|
1552
|
+
YAML
|
1553
|
+
}
|
1554
|
+
}
|
1555
|
+
}
|
1556
|
+
end
|
1557
|
+
|
1558
|
+
let(:environment_files) do
|
1559
|
+
{
|
1560
|
+
env_name => {
|
1561
|
+
'hiera.yaml' => env_hiera_yaml,
|
1562
|
+
'data' => env_data,
|
1563
|
+
'modules' => module_files
|
1564
|
+
}
|
1565
|
+
}
|
1566
|
+
end
|
1567
|
+
|
1568
|
+
it "interpolation function 'hiera' finds values in environment" do
|
1569
|
+
expect(lookup('ipl_hiera_env')).to eql("environment value 'value mod_a::hash_a.a (from environment)'")
|
1570
|
+
end
|
1571
|
+
|
1572
|
+
it "interpolation function 'hiera' finds values in module" do
|
1573
|
+
expect(lookup('ipl_hiera_mod')).to eql("module value 'value mod_a::abc (from module)'")
|
1574
|
+
end
|
1575
|
+
|
1576
|
+
it "interpolation function 'hiera' finds values in module and that module does not find %{calling_module}" do
|
1577
|
+
expect(lookup('ipl_hiera_modc')).to eql("module value 'calling module is '")
|
1578
|
+
end
|
1579
|
+
|
1580
|
+
context 'but no environment data provider' do
|
1581
|
+
let(:environment_files) do
|
1582
|
+
{
|
1583
|
+
env_name => {
|
1584
|
+
'modules' => module_files
|
1585
|
+
}
|
1586
|
+
}
|
1587
|
+
end
|
1588
|
+
|
1589
|
+
it "interpolation function 'hiera' does not find values in a module" do
|
1590
|
+
expect(lookup('ipl_hiera_mod')).to eql("module value ''")
|
1591
|
+
end
|
1592
|
+
end
|
1593
|
+
end
|
1594
|
+
|
1595
|
+
|
984
1596
|
context 'using an eyaml backend' do
|
985
1597
|
let(:private_key_name) { 'private_key.pkcs7.pem' }
|
986
1598
|
let(:public_key_name) { 'public_key.pkcs7.pem' }
|
@@ -1309,6 +1921,10 @@ describe "The lookup function" do
|
|
1309
1921
|
expect(lookup('other_option')).to eql('value of other_option')
|
1310
1922
|
end
|
1311
1923
|
|
1924
|
+
it 'dotted keys are passed down to custom backend' do
|
1925
|
+
expect(lookup('dotted.key')).to eql('custom backend received request for dotted.key value')
|
1926
|
+
end
|
1927
|
+
|
1312
1928
|
it 'multiple hiera3_backend declarations can be used and are merged into the generated config' do
|
1313
1929
|
expect(lookup(['datasources', 'other_option'])).to eql([['common', 'example.com'], 'value of other_option'])
|
1314
1930
|
expect(Hiera::Config.instance_variable_get(:@config)).to eql(
|
@@ -1328,6 +1944,60 @@ describe "The lookup function" do
|
|
1328
1944
|
expect(e.message).to match(/Lookup using Hocon data_hash function is not supported without hocon library/)
|
1329
1945
|
end
|
1330
1946
|
end
|
1947
|
+
|
1948
|
+
context 'with missing path declaraion' do
|
1949
|
+
context 'and yaml_data function' do
|
1950
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
1951
|
+
version: 5
|
1952
|
+
hierarchy:
|
1953
|
+
- name: Yaml
|
1954
|
+
data_hash: yaml_data
|
1955
|
+
YAML
|
1956
|
+
|
1957
|
+
it 'fails and reports the missing path' do
|
1958
|
+
expect { lookup('a') }.to raise_error(/one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this data_hash function/)
|
1959
|
+
end
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
context 'and json_data function' do
|
1963
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
1964
|
+
version: 5
|
1965
|
+
hierarchy:
|
1966
|
+
- name: Json
|
1967
|
+
data_hash: json_data
|
1968
|
+
YAML
|
1969
|
+
|
1970
|
+
it 'fails and reports the missing path' do
|
1971
|
+
expect { lookup('a') }.to raise_error(/one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this data_hash function/)
|
1972
|
+
end
|
1973
|
+
end
|
1974
|
+
|
1975
|
+
context 'and hocon_data function' do
|
1976
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
1977
|
+
version: 5
|
1978
|
+
hierarchy:
|
1979
|
+
- name: Hocon
|
1980
|
+
data_hash: hocon_data
|
1981
|
+
YAML
|
1982
|
+
|
1983
|
+
it 'fails and reports the missing path' do
|
1984
|
+
expect { lookup('a') }.to raise_error(/one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this data_hash function/)
|
1985
|
+
end
|
1986
|
+
end
|
1987
|
+
|
1988
|
+
context 'and eyaml_lookup_key function' do
|
1989
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
1990
|
+
version: 5
|
1991
|
+
hierarchy:
|
1992
|
+
- name: Yaml
|
1993
|
+
lookup_key: eyaml_lookup_key
|
1994
|
+
YAML
|
1995
|
+
|
1996
|
+
it 'fails and reports the missing path' do
|
1997
|
+
expect { lookup('a') }.to raise_error(/one of 'path', 'paths' 'glob', 'globs' or 'mapped_paths' must be declared in hiera.yaml when using this lookup_key function/)
|
1998
|
+
end
|
1999
|
+
end
|
2000
|
+
end
|
1331
2001
|
end
|
1332
2002
|
|
1333
2003
|
context 'with a hiera3_backend that has no paths' do
|
@@ -1387,7 +2057,7 @@ describe "The lookup function" do
|
|
1387
2057
|
end
|
1388
2058
|
|
1389
2059
|
it 'raises an error' do
|
1390
|
-
expect { lookup('mod_a::a') }.to raise_error(Puppet::Error, /hiera
|
2060
|
+
expect { lookup('mod_a::a') }.to raise_error(Puppet::Error, /hiera.yaml version 3 cannot be used in a module/)
|
1391
2061
|
end
|
1392
2062
|
end
|
1393
2063
|
|
@@ -1438,13 +2108,24 @@ describe "The lookup function" do
|
|
1438
2108
|
end
|
1439
2109
|
|
1440
2110
|
context 'using a data_hash that reads a yaml file' do
|
2111
|
+
let(:defaults) {
|
2112
|
+
{
|
2113
|
+
'mod_a::xd' => 'value mod_a::xd (from default)',
|
2114
|
+
'mod_a::xd_found' => 'value mod_a::xd_found (from default)',
|
2115
|
+
'scope_xd' => 'value scope_xd (from default)'
|
2116
|
+
}}
|
2117
|
+
let(:overrides) {
|
2118
|
+
{
|
2119
|
+
'mod_a::xo' => 'value mod_a::xo (from override)',
|
2120
|
+
'scope_xo' => 'value scope_xo (from override)'
|
2121
|
+
}}
|
2122
|
+
|
1441
2123
|
let(:scope_additions) do
|
1442
2124
|
{
|
1443
2125
|
'scope_scalar' => 'scope scalar value',
|
1444
2126
|
'scope_hash' => { 'a' => 'scope hash a', 'b' => 'scope hash b' }
|
1445
2127
|
}
|
1446
2128
|
end
|
1447
|
-
|
1448
2129
|
let(:mod_a_files) do
|
1449
2130
|
{
|
1450
2131
|
'mod_a' => {
|
@@ -1628,55 +2309,57 @@ describe "The lookup function" do
|
|
1628
2309
|
end
|
1629
2310
|
|
1630
2311
|
context 'using a lookup_key that is a puppet function' do
|
2312
|
+
let(:puppet_function) { <<-PUPPET.unindent }
|
2313
|
+
function mod_a::pp_lookup_key(Puppet::LookupKey $key, Hash[String,String] $options, Puppet::LookupContext $context) >> Puppet::LookupValue {
|
2314
|
+
case $key {
|
2315
|
+
'mod_a::really_interpolated': { $context.interpolate("-- %{lookup('mod_a::a')} --") }
|
2316
|
+
'mod_a::recursive': { lookup($key) }
|
2317
|
+
default: {
|
2318
|
+
if $context.cache_has_key(mod_a::a) {
|
2319
|
+
$context.explain || { 'reusing cache' }
|
2320
|
+
} else {
|
2321
|
+
$context.explain || { 'initializing cache' }
|
2322
|
+
$context.cache_all({
|
2323
|
+
mod_a::a => 'value mod_a::a (from mod_a)',
|
2324
|
+
mod_a::b => 'value mod_a::b (from mod_a)',
|
2325
|
+
mod_a::c => 'value mod_a::c (from mod_a)',
|
2326
|
+
mod_a::hash_a => {
|
2327
|
+
a => 'value mod_a::hash_a.a (from mod_a)',
|
2328
|
+
b => 'value mod_a::hash_a.b (from mod_a)'
|
2329
|
+
},
|
2330
|
+
mod_a::hash_b => {
|
2331
|
+
a => 'value mod_a::hash_b.a (from mod_a)',
|
2332
|
+
b => 'value mod_a::hash_b.b (from mod_a)'
|
2333
|
+
},
|
2334
|
+
mod_a::interpolated => "-- %{lookup('mod_a::a')} --",
|
2335
|
+
mod_a::a_a => "-- %{lookup('mod_a::hash_a.a')} --",
|
2336
|
+
mod_a::a_b => "-- %{lookup('mod_a::hash_a.b')} --",
|
2337
|
+
mod_a::b_a => "-- %{lookup('mod_a::hash_b.a')} --",
|
2338
|
+
mod_a::b_b => "-- %{lookup('mod_a::hash_b.b')} --",
|
2339
|
+
'mod_a::a.quoted.key' => 'value mod_a::a.quoted.key (from mod_a)',
|
2340
|
+
mod_a::sensitive => Sensitive('reduct me please'),
|
2341
|
+
mod_a::type => Object[{name => 'FindMe', 'attributes' => {'x' => String}}],
|
2342
|
+
mod_a::version => SemVer('3.4.1'),
|
2343
|
+
mod_a::version_range => SemVerRange('>=3.4.1'),
|
2344
|
+
mod_a::timestamp => Timestamp("1994-03-25T19:30:00"),
|
2345
|
+
mod_a::timespan => Timespan("3-10:00:00")
|
2346
|
+
})
|
2347
|
+
}
|
2348
|
+
if !$context.cache_has_key($key) {
|
2349
|
+
$context.not_found
|
2350
|
+
}
|
2351
|
+
$context.explain || { "returning value for $key" }
|
2352
|
+
$context.cached_value($key)
|
2353
|
+
}
|
2354
|
+
}
|
2355
|
+
}
|
2356
|
+
PUPPET
|
2357
|
+
|
1631
2358
|
let(:mod_a_files) do
|
1632
2359
|
{
|
1633
2360
|
'mod_a' => {
|
1634
2361
|
'functions' => {
|
1635
|
-
'pp_lookup_key.pp' =>
|
1636
|
-
function mod_a::pp_lookup_key($key, $options, $context) {
|
1637
|
-
case $key {
|
1638
|
-
'mod_a::really_interpolated': { $context.interpolate("-- %{lookup('mod_a::a')} --") }
|
1639
|
-
'mod_a::recursive': { lookup($key) }
|
1640
|
-
default: {
|
1641
|
-
if $context.cache_has_key(mod_a::a) {
|
1642
|
-
$context.explain || { 'reusing cache' }
|
1643
|
-
} else {
|
1644
|
-
$context.explain || { 'initializing cache' }
|
1645
|
-
$context.cache_all({
|
1646
|
-
mod_a::a => 'value mod_a::a (from mod_a)',
|
1647
|
-
mod_a::b => 'value mod_a::b (from mod_a)',
|
1648
|
-
mod_a::c => 'value mod_a::c (from mod_a)',
|
1649
|
-
mod_a::hash_a => {
|
1650
|
-
a => 'value mod_a::hash_a.a (from mod_a)',
|
1651
|
-
b => 'value mod_a::hash_a.b (from mod_a)'
|
1652
|
-
},
|
1653
|
-
mod_a::hash_b => {
|
1654
|
-
a => 'value mod_a::hash_b.a (from mod_a)',
|
1655
|
-
b => 'value mod_a::hash_b.b (from mod_a)'
|
1656
|
-
},
|
1657
|
-
mod_a::interpolated => "-- %{lookup('mod_a::a')} --",
|
1658
|
-
mod_a::a_a => "-- %{lookup('mod_a::hash_a.a')} --",
|
1659
|
-
mod_a::a_b => "-- %{lookup('mod_a::hash_a.b')} --",
|
1660
|
-
mod_a::b_a => "-- %{lookup('mod_a::hash_b.a')} --",
|
1661
|
-
mod_a::b_b => "-- %{lookup('mod_a::hash_b.b')} --",
|
1662
|
-
'mod_a::a.quoted.key' => 'value mod_a::a.quoted.key (from mod_a)',
|
1663
|
-
mod_a::sensitive => Sensitive('reduct me please'),
|
1664
|
-
mod_a::type => Object[{name => 'FindMe', 'attributes' => {'x' => String}}],
|
1665
|
-
mod_a::version => SemVer('3.4.1'),
|
1666
|
-
mod_a::version_range => SemVerRange('>=3.4.1'),
|
1667
|
-
mod_a::timestamp => Timestamp("1994-03-25T19:30:00"),
|
1668
|
-
mod_a::timespan => Timespan("3-10:00:00")
|
1669
|
-
})
|
1670
|
-
}
|
1671
|
-
if !$context.cache_has_key($key) {
|
1672
|
-
$context.not_found
|
1673
|
-
}
|
1674
|
-
$context.explain || { "returning value for $key" }
|
1675
|
-
$context.cached_value($key)
|
1676
|
-
}
|
1677
|
-
}
|
1678
|
-
}
|
1679
|
-
PUPPET
|
2362
|
+
'pp_lookup_key.pp' => puppet_function
|
1680
2363
|
},
|
1681
2364
|
'hiera.yaml' => <<-YAML.unindent,
|
1682
2365
|
---
|
@@ -1749,6 +2432,19 @@ describe "The lookup function" do
|
|
1749
2432
|
expect(notices).to eql(['success'])
|
1750
2433
|
end
|
1751
2434
|
end
|
2435
|
+
|
2436
|
+
context 'with declared but incompatible return_type' do
|
2437
|
+
let(:puppet_function) { <<-PUPPET.unindent }
|
2438
|
+
function mod_a::pp_lookup_key(Puppet::LookupKey $key, Hash[String,String] $options, Puppet::LookupContext $context) >> Runtime['ruby','Symbol'] {
|
2439
|
+
undef
|
2440
|
+
}
|
2441
|
+
PUPPET
|
2442
|
+
|
2443
|
+
it 'fails and reports error' do
|
2444
|
+
expect{lookup('mod_a::a')}.to raise_error(
|
2445
|
+
"Return type of 'lookup_key' function named 'mod_a::pp_lookup_key' is incorrect, expects a value of type Undef, Scalar, Sensitive, Type, Hash, or Array, got Runtime")
|
2446
|
+
end
|
2447
|
+
end
|
1752
2448
|
end
|
1753
2449
|
|
1754
2450
|
context 'using a data_dig that is a ruby function' do
|
@@ -1765,6 +2461,7 @@ describe "The lookup function" do
|
|
1765
2461
|
param 'Array[String[1]]', :segments
|
1766
2462
|
param 'Hash[String,Any]', :options
|
1767
2463
|
param 'Puppet::LookupContext', :context
|
2464
|
+
return_type 'Puppet::LookupValue'
|
1768
2465
|
end
|
1769
2466
|
|
1770
2467
|
def ruby_dig(segments, options, context)
|
@@ -1813,6 +2510,11 @@ describe "The lookup function" do
|
|
1813
2510
|
'hiera.yaml' => <<-YAML.unindent,
|
1814
2511
|
---
|
1815
2512
|
version: 5
|
2513
|
+
defaults:
|
2514
|
+
options:
|
2515
|
+
option_b:
|
2516
|
+
z: Default option value b.z
|
2517
|
+
|
1816
2518
|
hierarchy:
|
1817
2519
|
- name: "Common"
|
1818
2520
|
data_dig: mod_a::ruby_dig
|
@@ -1822,7 +2524,9 @@ describe "The lookup function" do
|
|
1822
2524
|
option_b:
|
1823
2525
|
x: Option value b.x
|
1824
2526
|
y: Option value b.y
|
1825
|
-
|
2527
|
+
- name: "Extra"
|
2528
|
+
data_dig: mod_a::ruby_dig
|
2529
|
+
YAML
|
1826
2530
|
}
|
1827
2531
|
}
|
1828
2532
|
end
|
@@ -1844,11 +2548,13 @@ describe "The lookup function" do
|
|
1844
2548
|
end
|
1845
2549
|
|
1846
2550
|
it 'does not accept return of runtime type from function' do
|
1847
|
-
|
2551
|
+
# Message is produced by the called function, not by the lookup framework
|
2552
|
+
expect(explain('mod_a::bad_type')).to include("value returned from function 'ruby_dig' has wrong type")
|
1848
2553
|
end
|
1849
2554
|
|
1850
2555
|
it 'does not accept return of runtime type embedded in hash from function' do
|
1851
|
-
|
2556
|
+
# Message is produced by the called function, not by the lookup framework
|
2557
|
+
expect(explain('mod_a::bad_type_in_hash')).to include("value returned from function 'ruby_dig' has wrong type")
|
1852
2558
|
end
|
1853
2559
|
|
1854
2560
|
it 'will not merge hashes from environment and module unless strategy hash is used' do
|
@@ -1859,6 +2565,22 @@ describe "The lookup function" do
|
|
1859
2565
|
expect(lookup('mod_a::options.option_b.x')).to eql('Option value b.x')
|
1860
2566
|
end
|
1861
2567
|
|
2568
|
+
it 'default options are passed to the function' do
|
2569
|
+
expect(lookup('mod_a::options.option_b.z')).to eql('Default option value b.z')
|
2570
|
+
end
|
2571
|
+
|
2572
|
+
it 'default options are not merged with hierarchy options' do
|
2573
|
+
expect(lookup('mod_a::options')).to eql(
|
2574
|
+
{
|
2575
|
+
'option_a' => 'Option value a',
|
2576
|
+
'option_b' => {
|
2577
|
+
'y' => 'Option value b.y',
|
2578
|
+
'x' => 'Option value b.x'
|
2579
|
+
},
|
2580
|
+
'uri' => 'http://www.example.com/passed/as/option'
|
2581
|
+
})
|
2582
|
+
end
|
2583
|
+
|
1862
2584
|
it 'hierarchy entry "uri" is passed as location option to the function' do
|
1863
2585
|
expect(lookup('mod_a::options.uri')).to eql('http://www.example.com/passed/as/option')
|
1864
2586
|
end
|
@@ -1878,6 +2600,125 @@ describe "The lookup function" do
|
|
1878
2600
|
end
|
1879
2601
|
end
|
1880
2602
|
end
|
2603
|
+
|
2604
|
+
context 'that has a default_hierarchy' do
|
2605
|
+
let(:mod_a_hiera_yaml) { <<-YAML.unindent }
|
2606
|
+
version: 5
|
2607
|
+
hierarchy:
|
2608
|
+
- name: "Common"
|
2609
|
+
path: common.yaml
|
2610
|
+
- name: "Common 2"
|
2611
|
+
path: common2.yaml
|
2612
|
+
|
2613
|
+
default_hierarchy:
|
2614
|
+
- name: "Default"
|
2615
|
+
path: defaults.yaml
|
2616
|
+
- name: "Default 2"
|
2617
|
+
path: defaults2.yaml
|
2618
|
+
YAML
|
2619
|
+
|
2620
|
+
let(:mod_a_common) { <<-YAML.unindent }
|
2621
|
+
mod_a::a: value mod_a::a (from module)
|
2622
|
+
mod_a::d:
|
2623
|
+
a: value mod_a::d.a (from module)
|
2624
|
+
mod_a::f:
|
2625
|
+
a:
|
2626
|
+
a: value mod_a::f.a.a (from module)
|
2627
|
+
lookup_options:
|
2628
|
+
mod_a::e:
|
2629
|
+
merge: deep
|
2630
|
+
YAML
|
2631
|
+
|
2632
|
+
|
2633
|
+
let(:mod_a_common2) { <<-YAML.unindent }
|
2634
|
+
mod_a::b: value mod_a::b (from module)
|
2635
|
+
mod_a::d:
|
2636
|
+
c: value mod_a::d.c (from module)
|
2637
|
+
mod_a::f:
|
2638
|
+
a:
|
2639
|
+
b: value mod_a::f.a.b (from module)
|
2640
|
+
YAML
|
2641
|
+
|
2642
|
+
let(:mod_a_defaults) { <<-YAML.unindent }
|
2643
|
+
mod_a::a: value mod_a::a (from module defaults)
|
2644
|
+
mod_a::b: value mod_a::b (from module defaults)
|
2645
|
+
mod_a::c: value mod_a::c (from module defaults)
|
2646
|
+
mod_a::d:
|
2647
|
+
b: value mod_a::d.b (from module defaults)
|
2648
|
+
mod_a::e:
|
2649
|
+
a:
|
2650
|
+
a: value mod_a::e.a.a (from module defaults)
|
2651
|
+
mod_a::g:
|
2652
|
+
a:
|
2653
|
+
a: value mod_a::g.a.a (from module defaults)
|
2654
|
+
lookup_options:
|
2655
|
+
mod_a::d:
|
2656
|
+
merge: hash
|
2657
|
+
mod_a::g:
|
2658
|
+
merge: deep
|
2659
|
+
YAML
|
2660
|
+
|
2661
|
+
let(:mod_a_defaults2) { <<-YAML.unindent }
|
2662
|
+
mod_a::e:
|
2663
|
+
a:
|
2664
|
+
b: value mod_a::e.a.b (from module defaults)
|
2665
|
+
mod_a::g:
|
2666
|
+
a:
|
2667
|
+
b: value mod_a::g.a.b (from module defaults)
|
2668
|
+
YAML
|
2669
|
+
|
2670
|
+
let(:mod_a_files) do
|
2671
|
+
{
|
2672
|
+
'mod_a' => {
|
2673
|
+
'data' => {
|
2674
|
+
'common.yaml' => mod_a_common,
|
2675
|
+
'common2.yaml' => mod_a_common2,
|
2676
|
+
'defaults.yaml' => mod_a_defaults,
|
2677
|
+
'defaults2.yaml' => mod_a_defaults2
|
2678
|
+
},
|
2679
|
+
'hiera.yaml' => mod_a_hiera_yaml
|
2680
|
+
}
|
2681
|
+
}
|
2682
|
+
end
|
2683
|
+
|
2684
|
+
it 'the default hierarchy does not interfere with environment hierarchy' do
|
2685
|
+
expect(lookup('mod_a::a')).to eql('value mod_a::a (from environment)')
|
2686
|
+
end
|
2687
|
+
|
2688
|
+
it 'the default hierarchy does not interfere with regular hierarchy in module' do
|
2689
|
+
expect(lookup('mod_a::b')).to eql('value mod_a::b (from module)')
|
2690
|
+
end
|
2691
|
+
|
2692
|
+
it 'the default hierarchy is consulted when no value is found elsewhere' do
|
2693
|
+
expect(lookup('mod_a::c')).to eql('value mod_a::c (from module defaults)')
|
2694
|
+
end
|
2695
|
+
|
2696
|
+
it 'the default hierarchy does not participate in a merge' do
|
2697
|
+
expect(lookup('mod_a::d', 'merge' => 'hash')).to eql('a' => 'value mod_a::d.a (from module)', 'c' => 'value mod_a::d.c (from module)')
|
2698
|
+
end
|
2699
|
+
|
2700
|
+
it 'lookup_options from regular hierarchy does not effect values found in the default hierarchy' do
|
2701
|
+
expect(lookup('mod_a::e')).to eql('a' => { 'a' => 'value mod_a::e.a.a (from module defaults)' })
|
2702
|
+
end
|
2703
|
+
|
2704
|
+
it 'lookup_options from default hierarchy affects values found in the default hierarchy' do
|
2705
|
+
expect(lookup('mod_a::g')).to eql('a' => { 'a' => 'value mod_a::g.a.a (from module defaults)', 'b' => 'value mod_a::g.a.b (from module defaults)'})
|
2706
|
+
end
|
2707
|
+
|
2708
|
+
it 'merge parameter does not override lookup_options defined in the default hierarchy' do
|
2709
|
+
expect(lookup('mod_a::g', 'merge' => 'hash')).to eql(
|
2710
|
+
'a' => { 'a' => 'value mod_a::g.a.a (from module defaults)', 'b' => 'value mod_a::g.a.b (from module defaults)'})
|
2711
|
+
end
|
2712
|
+
|
2713
|
+
it 'lookup_options from default hierarchy does not effect values found in the regular hierarchy' do
|
2714
|
+
expect(lookup('mod_a::d')).to eql('a' => 'value mod_a::d.a (from module)')
|
2715
|
+
end
|
2716
|
+
|
2717
|
+
it 'the default hierarchy lookup is included in the explain output' do
|
2718
|
+
explanation = explain('mod_a::c')
|
2719
|
+
expect(explanation).to match(/Searching default_hierarchy of module "mod_a".+Original path: "defaults.yaml"/m)
|
2720
|
+
end
|
2721
|
+
end
|
1881
2722
|
end
|
1882
2723
|
|
1883
2724
|
context 'and an eyaml lookup_key function' do
|
@@ -1968,6 +2809,7 @@ describe "The lookup function" do
|
|
1968
2809
|
let(:data_files) do
|
1969
2810
|
{
|
1970
2811
|
'common.eyaml' => <<-YAML.unindent
|
2812
|
+
# a: Encrypted value 'a' (from environment)
|
1971
2813
|
a: >
|
1972
2814
|
ENC[PKCS7,MIIBmQYJKoZIhvcNAQcDoIIBijCCAYYCAQAxggEhMIIBHQIBADAFMAACAQEw
|
1973
2815
|
DQYJKoZIhvcNAQEBBQAEggEAUwwNRA5ZKM87SLnjnJfzDFRQbeheSYMTOhcr
|
@@ -1981,6 +2823,7 @@ describe "The lookup function" do
|
|
1981
2823
|
dCILO7I8QqU=]
|
1982
2824
|
hash_a:
|
1983
2825
|
"hash_%{ipl_suffix}":
|
2826
|
+
# aaa: Encrypted value hash_a.hash_aa.aaa (from environment)
|
1984
2827
|
aaa: >
|
1985
2828
|
ENC[PKCS7,MIIBqQYJKoZIhvcNAQcDoIIBmjCCAZYCAQAxggEhMIIBHQIBADAFMAACAQEw
|
1986
2829
|
DQYJKoZIhvcNAQEBBQAEggEAhvGXL5RxVUs9wdqJvpCyXtfCHrm2HbG/u30L
|
@@ -1993,6 +2836,7 @@ describe "The lookup function" do
|
|
1993
2836
|
ovm/gEB4oPlYJswoXuWqcEBfwZzbpy96x3b2Le/yoa72ylbPAUc5GfLENvFQ
|
1994
2837
|
zXpTtSmQE0fixY4JMaBTke65ZRvoiOQO]
|
1995
2838
|
array_a:
|
2839
|
+
# - "array_a[0]"
|
1996
2840
|
- >
|
1997
2841
|
ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEw
|
1998
2842
|
DQYJKoZIhvcNAQEBBQAEggEAmXZfyfU77vVCZqHpR10qhD0Jy9DpMGBgal97
|
@@ -2003,6 +2847,7 @@ describe "The lookup function" do
|
|
2003
2847
|
MieIkHj93bX3gIEcenECLdWaEzcPa7MHgl6zevQKg4H0JVmcvKYyfHYqcrVE
|
2004
2848
|
PqizKDA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBDf259KZEay1widVSFy
|
2005
2849
|
I9zGgBAICjm0x2GeqoCnHdiAA+jt]
|
2850
|
+
# - "array_a[1]"
|
2006
2851
|
- >
|
2007
2852
|
ENC[PKCS7,MIIBeQYJKoZIhvcNAQcDoIIBajCCAWYCAQAxggEhMIIBHQIBADAFMAACAQEw
|
2008
2853
|
DQYJKoZIhvcNAQEBBQAEggEATVy4hHG356INFKOswAhoravh66iJljp+Vn3o
|
@@ -2013,6 +2858,17 @@ describe "The lookup function" do
|
|
2013
2858
|
t22zpYK4J8lgCBV2gKfrOWSi9MAs6JhCeOb8wNLMmAUTbc0WrFJxoCwAPX0z
|
2014
2859
|
MAjsNjA8BgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBC4v4bNE4gFlbLmVY+9
|
2015
2860
|
BtSLgBBm7U0wu6d6s9wF9Ek9IHPe]
|
2861
|
+
# ref_a: "A resolved = '%{hiera('a')}'"
|
2862
|
+
ref_a: >
|
2863
|
+
ENC[PKCS7,MIIBiQYJKoZIhvcNAQcDoIIBejCCAXYCAQAxggEhMIIBHQIBADAFMAACAQEw
|
2864
|
+
DQYJKoZIhvcNAQEBBQAEggEAFSuUp+yk+oaA7b5ekT0u360CQ9Q2sIQ/bTcM
|
2865
|
+
jT3XLjm8HIGYPcysOEnuo8WcAxJFY5iya4yQ7Y/UhMWXaTi7Vzv/6BmyPDwz
|
2866
|
+
+7Z2Mf0r0PvS5+ylue6aem/3bXPOmXTKTf68OCehTRXlDUs8/av9gnsDzojp
|
2867
|
+
yiUTBZvKxhIP2n//GyoHgyATveHT0lxPVpdMycB347DtWS7IduCxx0+KiOOw
|
2868
|
+
DXYFlYbIVxVInwgERxtsfYSr+Fu0/mkjtRsQm+dPzMQOATE9Val2gGKsV6bi
|
2869
|
+
kdm1OM9HrwVsFj6Lma6FYmr89Bcm/1uEc8fiOMtNK3z2+nwunWBMNCGneMYD
|
2870
|
+
C5IJejBMBgkqhkiG9w0BBwEwHQYJYIZIAWUDBAEqBBAeiZDGQyXHkZlV5ceT
|
2871
|
+
iCxpgCDDatuVvbPEEi8rKOC7xhPHZ22zLEEV//l7C9jxq+DZcA==]
|
2016
2872
|
YAML
|
2017
2873
|
}
|
2018
2874
|
end
|
@@ -2027,6 +2883,10 @@ describe "The lookup function" do
|
|
2027
2883
|
expect(lookup('hash_a')).to include('hash_aa')
|
2028
2884
|
end
|
2029
2885
|
|
2886
|
+
it 'evaluates interpolations in encrypted values' do
|
2887
|
+
expect(lookup('ref_a')).to eql("A resolved = 'Encrypted value 'a' (from environment)'")
|
2888
|
+
end
|
2889
|
+
|
2030
2890
|
it 'can read encrypted values inside a hash' do
|
2031
2891
|
expect(lookup('hash_a.hash_aa.aaa')).to eql('Encrypted value hash_a.hash_aa.aaa (from environment)')
|
2032
2892
|
end
|