puppet 4.9.2 → 4.9.3
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.
- data/lib/hiera/puppet_function.rb +1 -0
- data/lib/puppet/feature/hiera_eyaml.rb +3 -0
- data/lib/puppet/functions/eyaml_lookup_key.rb +73 -0
- data/lib/puppet/pops/lookup/global_data_provider.rb +12 -1
- data/lib/puppet/pops/lookup/hiera_config.rb +6 -4
- data/lib/puppet/pops/lookup/invocation.rb +20 -0
- data/lib/puppet/pops/lookup/location_resolver.rb +2 -2
- data/lib/puppet/pops/lookup/lookup_key_function_provider.rb +46 -10
- data/lib/puppet/provider/package/rpm.rb +1 -1
- data/lib/puppet/version.rb +1 -1
- data/lib/semver.rb +2 -2
- data/spec/unit/functions/hiera_spec.rb +176 -94
- data/spec/unit/functions/lookup_spec.rb +383 -95
- data/spec/unit/provider/package/rpm_spec.rb +2 -1
- data/spec/unit/semver_spec.rb +234 -7
- metadata +4 -2
@@ -65,6 +65,7 @@ class Hiera::PuppetFunction < Puppet::Functions::InternalFunction
|
|
65
65
|
end
|
66
66
|
lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {})
|
67
67
|
adapter = lookup_invocation.lookup_adapter
|
68
|
+
lookup_invocation.set_hiera_xxx_call
|
68
69
|
lookup_invocation.set_global_only unless adapter.global_only? || adapter.has_environment_data_provider?(lookup_invocation)
|
69
70
|
lookup_invocation.set_hiera_v3_location_overrides(override) unless override.nil? || override.is_a?(Array) && override.empty?
|
70
71
|
Puppet::Pops::Lookup.lookup(key, nil, default, has_default, merge_type, lookup_invocation, &default_block)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# @since 5.0.0
|
2
|
+
#
|
3
|
+
Puppet::Functions.create_function(:eyaml_lookup_key) do
|
4
|
+
unless Puppet.features.hiera_eyaml?
|
5
|
+
raise Puppet::DataBinding::LookupError, 'Lookup using eyaml lookup_key function is only supported when the hiera_eyaml library is present'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'hiera/backend/eyaml/encryptor'
|
9
|
+
require 'hiera/backend/eyaml/utils'
|
10
|
+
require 'hiera/backend/eyaml/options'
|
11
|
+
require 'hiera/backend/eyaml/parser/parser'
|
12
|
+
|
13
|
+
dispatch :eyaml_lookup_key do
|
14
|
+
param 'String[1]', :key
|
15
|
+
param 'Hash[String[1],Any]', :options
|
16
|
+
param 'Puppet::LookupContext', :context
|
17
|
+
end
|
18
|
+
|
19
|
+
def eyaml_lookup_key(key, options, context)
|
20
|
+
return context.cached_value(key) if context.cache_has_key(key)
|
21
|
+
|
22
|
+
# nil key is used to indicate that the cache contains the raw content of the eyaml file
|
23
|
+
raw_data = context.cached_value(nil)
|
24
|
+
if raw_data.nil?
|
25
|
+
options.each_pair do |k, v|
|
26
|
+
unless k == 'path'
|
27
|
+
Hiera::Backend::Eyaml::Options[k.to_sym] = v
|
28
|
+
context.explain { "Setting Eyaml option '#{k}' to '#{v}'" }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
raw_data = load_data_hash(options)
|
32
|
+
context.cache(nil, raw_data)
|
33
|
+
end
|
34
|
+
context.not_found unless raw_data.include?(key)
|
35
|
+
context.cache(key, decrypt_value(raw_data[key], context))
|
36
|
+
end
|
37
|
+
|
38
|
+
def load_data_hash(options)
|
39
|
+
begin
|
40
|
+
data = YAML.load_file(options['path'])
|
41
|
+
Puppet::Pops::Lookup::HieraConfig.symkeys_to_string(data.is_a?(Hash) ? data : {})
|
42
|
+
rescue YAML::SyntaxError => ex
|
43
|
+
# Psych errors includes the absolute path to the file, so no need to add that
|
44
|
+
# to the message
|
45
|
+
raise Puppet::DataBinding::LookupError, "Unable to parse #{ex.message}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def decrypt_value(value, context)
|
50
|
+
case value
|
51
|
+
when String
|
52
|
+
decrypt(value, context)
|
53
|
+
when Hash
|
54
|
+
result = {}
|
55
|
+
value.each_pair { |k, v| result[k] = decrypt_value(v, context) }
|
56
|
+
result
|
57
|
+
when Array
|
58
|
+
value.map { |v| decrypt_value(v, context) }
|
59
|
+
else
|
60
|
+
value
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def decrypt(data, context)
|
65
|
+
return context.interpolate(data) unless encrypted?(data)
|
66
|
+
tokens = Hiera::Backend::Eyaml::Parser::ParserFactory.hiera_backend_parser.parse(data)
|
67
|
+
tokens.map(&:to_plain_text).join.chomp
|
68
|
+
end
|
69
|
+
|
70
|
+
def encrypted?(data)
|
71
|
+
/.*ENC\[.*?\]/ =~ data ? true : false
|
72
|
+
end
|
73
|
+
end
|
@@ -21,7 +21,18 @@ class GlobalDataProvider < ConfiguredDataProvider
|
|
21
21
|
lookup_invocation.default_values,
|
22
22
|
lookup_invocation.explainer)
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
|
+
unless config.merge_strategy.is_a?(DefaultMergeStrategy)
|
26
|
+
if lookup_invocation.hiera_xxx_call?
|
27
|
+
# Merge strategy of the hiera_xxx call should only be applied when no merge strategy is defined in the hiera config
|
28
|
+
merge = config.merge_strategy
|
29
|
+
lookup_invocation.set_hiera_v3_merge_behavior
|
30
|
+
elsif merge.is_a?(DefaultMergeStrategy)
|
31
|
+
# For all other calls, the strategy of the call overrides the strategy defined in the hiera config
|
32
|
+
merge = config.merge_strategy
|
33
|
+
lookup_invocation.set_hiera_v3_merge_behavior
|
34
|
+
end
|
35
|
+
end
|
25
36
|
end
|
26
37
|
super(key, lookup_invocation, merge)
|
27
38
|
end
|
@@ -44,6 +44,7 @@ class HieraConfig
|
|
44
44
|
KEY_LOOKUP_KEY = LookupKeyFunctionProvider::TAG
|
45
45
|
KEY_DATA_DIG = DataDigFunctionProvider::TAG
|
46
46
|
KEY_V3_DATA_HASH = V3DataHashFunctionProvider::TAG
|
47
|
+
KEY_V3_LOOKUP_KEY = V3LookupKeyFunctionProvider::TAG
|
47
48
|
KEY_V3_BACKEND = V3BackendFunctionProvider::TAG
|
48
49
|
KEY_V4_DATA_HASH = V4DataHashFunctionProvider::TAG
|
49
50
|
KEY_BACKEND = 'backend'.freeze
|
@@ -57,6 +58,7 @@ class HieraConfig
|
|
57
58
|
KEY_LOOKUP_KEY => LookupKeyFunctionProvider,
|
58
59
|
KEY_V3_DATA_HASH => V3DataHashFunctionProvider,
|
59
60
|
KEY_V3_BACKEND => V3BackendFunctionProvider,
|
61
|
+
KEY_V3_LOOKUP_KEY => V3LookupKeyFunctionProvider,
|
60
62
|
KEY_V4_DATA_HASH => V4DataHashFunctionProvider
|
61
63
|
}
|
62
64
|
|
@@ -294,7 +296,7 @@ class HieraConfigV3 < HieraConfig
|
|
294
296
|
|
295
297
|
[@config[KEY_BACKENDS]].flatten.each do |backend|
|
296
298
|
raise Puppet::DataBinding::LookupError, "#{@config_path}: Backend '#{backend}' defined more than once" if data_providers.include?(backend)
|
297
|
-
original_paths = @config[KEY_HIERARCHY]
|
299
|
+
original_paths = [@config[KEY_HIERARCHY]].flatten
|
298
300
|
backend_config = @config[backend] || EMPTY_HASH
|
299
301
|
datadir = Pathname(interpolate(backend_config[KEY_DATADIR] || default_datadir, lookup_invocation, false))
|
300
302
|
ext = backend == 'hocon' ? '.conf' : ".#{backend}"
|
@@ -304,6 +306,8 @@ class HieraConfigV3 < HieraConfig
|
|
304
306
|
create_data_provider(backend, parent_data_provider, KEY_V3_DATA_HASH, "#{backend}_data", { KEY_DATADIR => datadir }, paths)
|
305
307
|
when backend == 'hocon' && Puppet.features.hocon?
|
306
308
|
create_data_provider(backend, parent_data_provider, KEY_V3_DATA_HASH, 'hocon_data', { KEY_DATADIR => datadir }, paths)
|
309
|
+
when backend == 'eyaml' && Puppet.features.hiera_eyaml?
|
310
|
+
create_data_provider(backend, parent_data_provider, KEY_V3_LOOKUP_KEY, 'eyaml_lookup_key', backend_config.merge(KEY_DATADIR => datadir), paths)
|
307
311
|
else
|
308
312
|
create_hiera3_backend_provider(backend, backend, parent_data_provider, datadir, paths, @loaded_config)
|
309
313
|
end
|
@@ -352,10 +356,8 @@ class HieraConfigV3 < HieraConfig
|
|
352
356
|
def create_merge_strategy
|
353
357
|
key = @config[KEY_MERGE_BEHAVIOR]
|
354
358
|
case key
|
355
|
-
when nil
|
359
|
+
when nil, 'native'
|
356
360
|
MergeStrategy.strategy(nil)
|
357
|
-
when 'native'
|
358
|
-
MergeStrategy.strategy(:first)
|
359
361
|
when 'array'
|
360
362
|
MergeStrategy.strategy(:unique)
|
361
363
|
when 'deep', 'deeper'
|
@@ -38,6 +38,8 @@ class Invocation
|
|
38
38
|
else
|
39
39
|
@name_stack = parent_invocation.name_stack
|
40
40
|
@adapter_class = parent_invocation.adapter_class
|
41
|
+
set_hiera_xxx_call if parent_invocation.hiera_xxx_call?
|
42
|
+
set_hiera_v3_merge_behavior if parent_invocation.hiera_v3_merge_behavior?
|
41
43
|
set_global_only if parent_invocation.global_only?
|
42
44
|
povr = parent_invocation.hiera_v3_location_overrides
|
43
45
|
set_hiera_v3_location_overrides(povr) unless povr.empty?
|
@@ -193,6 +195,24 @@ class Invocation
|
|
193
195
|
lookup_adapter.global_hiera_config_path
|
194
196
|
end
|
195
197
|
|
198
|
+
# @return [Boolean] `true` if the invocation stems from the hiera_xxx function family
|
199
|
+
def hiera_xxx_call?
|
200
|
+
instance_variable_defined?(:@hiera_xxx_call)
|
201
|
+
end
|
202
|
+
|
203
|
+
def set_hiera_xxx_call
|
204
|
+
@hiera_xxx_call = true
|
205
|
+
end
|
206
|
+
|
207
|
+
# @return [Boolean] `true` if the invocation stems from the hiera_xxx function family
|
208
|
+
def hiera_v3_merge_behavior?
|
209
|
+
instance_variable_defined?(:@hiera_v3_merge_behavior)
|
210
|
+
end
|
211
|
+
|
212
|
+
def set_hiera_v3_merge_behavior
|
213
|
+
@hiera_v3_merge_behavior = true
|
214
|
+
end
|
215
|
+
|
196
216
|
# Overrides passed from hiera_xxx functions down to V3DataHashFunctionProvider
|
197
217
|
def set_hiera_v3_location_overrides(overrides)
|
198
218
|
@hiera_v3_location_overrides = [overrides].flatten unless overrides.nil?
|
@@ -35,8 +35,8 @@ module Lookup
|
|
35
35
|
|
36
36
|
def expand_globs(datadir, declared_globs, lookup_invocation)
|
37
37
|
declared_globs.map do |declared_glob|
|
38
|
-
glob = interpolate(declared_glob, lookup_invocation, false)
|
39
|
-
Pathname.glob(
|
38
|
+
glob = datadir + interpolate(declared_glob, lookup_invocation, false)
|
39
|
+
Pathname.glob(glob).reject { |path| path.directory? }.map { |path| ResolvedLocation.new(glob.to_s, path, true) }
|
40
40
|
end.flatten
|
41
41
|
end
|
42
42
|
|
@@ -14,17 +14,22 @@ class LookupKeyFunctionProvider < FunctionProvider
|
|
14
14
|
# @return [Object] the found object
|
15
15
|
# @throw :no_such_key when the object is not found
|
16
16
|
def unchecked_key_lookup(key, lookup_invocation, merge)
|
17
|
+
root_key = key.root_key
|
17
18
|
lookup_invocation.with(:data_provider, self) do
|
18
19
|
MergeStrategy.strategy(merge).lookup(locations, lookup_invocation) do |location|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
invoke_with_location(lookup_invocation, location, root_key, merge)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def invoke_with_location(lookup_invocation, location, root_key, merge)
|
26
|
+
if location.nil?
|
27
|
+
value = lookup_key(root_key, lookup_invocation, nil, merge)
|
28
|
+
lookup_invocation.report_found(root_key, validate_data_value(self, value))
|
29
|
+
else
|
30
|
+
lookup_invocation.with(:location, location) do
|
31
|
+
value = lookup_key(root_key, lookup_invocation, location.location, merge)
|
32
|
+
lookup_invocation.report_found(root_key, validate_data_value(self, value))
|
28
33
|
end
|
29
34
|
end
|
30
35
|
end
|
@@ -52,12 +57,43 @@ class LookupKeyFunctionProvider < FunctionProvider
|
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
60
|
+
# @api private
|
61
|
+
class V3LookupKeyFunctionProvider < LookupKeyFunctionProvider
|
62
|
+
TAG = 'v3_lookup_key'.freeze
|
63
|
+
|
64
|
+
def initialize(name, parent_data_provider, function_name, options, locations)
|
65
|
+
@datadir = options.delete(HieraConfig::KEY_DATADIR)
|
66
|
+
super
|
67
|
+
end
|
68
|
+
|
69
|
+
def unchecked_key_lookup(key, lookup_invocation, merge)
|
70
|
+
extra_paths = lookup_invocation.hiera_v3_location_overrides
|
71
|
+
if extra_paths.nil? || extra_paths.empty?
|
72
|
+
super
|
73
|
+
else
|
74
|
+
# Extra paths provided. Must be resolved and placed in front of known paths
|
75
|
+
paths = parent_data_provider.config(lookup_invocation).resolve_paths(@datadir, extra_paths, lookup_invocation, false, ".#{@name}")
|
76
|
+
all_locations = paths + locations
|
77
|
+
root_key = key.root_key
|
78
|
+
lookup_invocation.with(:data_provider, self) do
|
79
|
+
MergeStrategy.strategy(merge).lookup(all_locations, lookup_invocation) do |location|
|
80
|
+
invoke_with_location(lookup_invocation, location, root_key, merge)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
55
87
|
class V3BackendFunctionProvider < LookupKeyFunctionProvider
|
56
88
|
TAG = 'hiera3_backend'.freeze
|
57
89
|
|
58
90
|
def lookup_key(key, lookup_invocation, location, merge)
|
59
91
|
@backend ||= instantiate_backend(lookup_invocation)
|
60
|
-
|
92
|
+
config = parent_data_provider.config(lookup_invocation)
|
93
|
+
|
94
|
+
# Never pass hiera.yaml defined merge_behavior down to the backend. It will pick it up from the config
|
95
|
+
resolution_type = lookup_invocation.hiera_v3_merge_behavior? ? nil : convert_merge(merge)
|
96
|
+
@backend.lookup(key, lookup_invocation.scope, lookup_invocation.hiera_v3_location_overrides, resolution_type, context = {:recurse_guard => nil})
|
61
97
|
end
|
62
98
|
|
63
99
|
private
|
@@ -19,7 +19,7 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
|
|
19
19
|
# eventually become this Puppet::Type::Package::ProviderRpm class.
|
20
20
|
# The query format by which we identify installed packages
|
21
21
|
self::NEVRA_FORMAT = %Q{%{NAME} %|EPOCH?{%{EPOCH}}:{0}| %{VERSION} %{RELEASE} %{ARCH}\\n}
|
22
|
-
self::NEVRA_REGEX = %r{^(\S+) (\S+) (\S+) (\S+) (\S+)$}
|
22
|
+
self::NEVRA_REGEX = %r{^'?(\S+) (\S+) (\S+) (\S+) (\S+)$}
|
23
23
|
self::NEVRA_FIELDS = [:name, :epoch, :version, :release, :arch]
|
24
24
|
|
25
25
|
ARCH_LIST = [
|
data/lib/puppet/version.rb
CHANGED
data/lib/semver.rb
CHANGED
@@ -29,10 +29,10 @@ class SemVer < Numeric
|
|
29
29
|
SemVer.new(pre(r), suppress_deprecation_warning) .. SemVer.new(r, suppress_deprecation_warning)
|
30
30
|
when SemVer::SIMPLE_RANGE
|
31
31
|
r += ".0" unless SemVer.valid?(r.gsub(/x/i, '0'))
|
32
|
-
SemVer.new(r.gsub(/x/i, '0'))...SemVer.new(r.gsub(/(\d+)\.x/i) { "#{$1.to_i + 1}.0" } + '-', suppress_deprecation_warning)
|
32
|
+
SemVer.new(r.gsub(/x/i, '0'), suppress_deprecation_warning)...SemVer.new(r.gsub(/(\d+)\.x/i) { "#{$1.to_i + 1}.0" } + '-', suppress_deprecation_warning)
|
33
33
|
when /\s+-\s+/
|
34
34
|
a, b = r.split(/\s+-\s+/)
|
35
|
-
SemVer.new(pre(a)) .. SemVer.new(b, suppress_deprecation_warning)
|
35
|
+
SemVer.new(pre(a), suppress_deprecation_warning) .. SemVer.new(b, suppress_deprecation_warning)
|
36
36
|
when /^~/
|
37
37
|
ver = r.sub(/~/, '').split('.').map(&:to_i)
|
38
38
|
start = (ver + [0] * (3 - ver.length)).join('.')
|
@@ -8,107 +8,123 @@ describe 'when calling' do
|
|
8
8
|
|
9
9
|
let(:global_dir) { tmpdir('global') }
|
10
10
|
let(:env_config) { {} }
|
11
|
-
let(:
|
11
|
+
let(:hiera_yaml) { <<-YAML.unindent }
|
12
|
+
---
|
13
|
+
:backends:
|
14
|
+
- yaml
|
15
|
+
- custom
|
16
|
+
:yaml:
|
17
|
+
:datadir: #{global_dir}/hieradata
|
18
|
+
:hierarchy:
|
19
|
+
- first
|
20
|
+
- second
|
21
|
+
YAML
|
22
|
+
|
23
|
+
let(:ruby_stuff_files) do
|
24
|
+
{
|
25
|
+
'hiera' => {
|
26
|
+
'backend' => {
|
27
|
+
'custom_backend.rb' => <<-RUBY.unindent
|
28
|
+
class Hiera::Backend::Custom_backend
|
29
|
+
def initialize(cache = nil)
|
30
|
+
Hiera.debug('Custom_backend starting')
|
31
|
+
end
|
32
|
+
|
33
|
+
def lookup(key, scope, order_override, resolution_type, context)
|
34
|
+
case key
|
35
|
+
when 'datasources'
|
36
|
+
Hiera::Backend.datasources(scope, order_override) { |source| source }
|
37
|
+
when 'resolution_type'
|
38
|
+
"resolution_type=\#{resolution_type}"
|
39
|
+
else
|
40
|
+
throw :no_such_key
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
RUBY
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:hieradata_files) do
|
12
51
|
{
|
13
|
-
'
|
52
|
+
'first.yaml' => <<-YAML.unindent,
|
14
53
|
---
|
15
|
-
:
|
16
|
-
|
17
|
-
|
18
|
-
:
|
19
|
-
|
20
|
-
:
|
21
|
-
|
22
|
-
|
54
|
+
a: first a
|
55
|
+
class_name: "-- %{calling_class} --"
|
56
|
+
class_path: "-- %{calling_class_path} --"
|
57
|
+
module: "-- %{calling_module} --"
|
58
|
+
mod_name: "-- %{module_name} --"
|
59
|
+
database_user:
|
60
|
+
name: postgres
|
61
|
+
uid: 500
|
62
|
+
gid: 500
|
63
|
+
b:
|
64
|
+
b1: first b1
|
65
|
+
b2: first b2
|
66
|
+
fbb:
|
67
|
+
- mod::foo
|
68
|
+
- mod::bar
|
69
|
+
- mod::baz
|
70
|
+
empty_array: []
|
23
71
|
YAML
|
24
|
-
'
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
b:
|
59
|
-
b1: first b1
|
60
|
-
b2: first b2
|
61
|
-
fbb:
|
62
|
-
- mod::foo
|
63
|
-
- mod::bar
|
64
|
-
- mod::baz
|
65
|
-
empty_array: []
|
66
|
-
YAML
|
67
|
-
'second.yaml' => <<-YAML.unindent,
|
68
|
-
---
|
69
|
-
a: second a
|
70
|
-
b:
|
71
|
-
b1: second b1
|
72
|
-
b3: second b3
|
73
|
-
YAML
|
74
|
-
'the_override.yaml' => <<-YAML.unindent
|
75
|
-
---
|
76
|
-
key: foo_result
|
77
|
-
YAML
|
78
|
-
},
|
79
|
-
'environments' => {
|
80
|
-
'test' => {
|
81
|
-
'modules' => {
|
82
|
-
'mod' => {
|
83
|
-
'manifests' => {
|
84
|
-
'foo.pp' => <<-PUPPET.unindent,
|
85
|
-
class mod::foo {
|
86
|
-
notice(hiera('class_name'))
|
87
|
-
notice(hiera('class_path'))
|
88
|
-
notice(hiera('module'))
|
89
|
-
notice(hiera('mod_name'))
|
90
|
-
}
|
91
|
-
PUPPET
|
92
|
-
'bar.pp' => <<-PUPPET.unindent,
|
93
|
-
class mod::bar {}
|
94
|
-
PUPPET
|
95
|
-
'baz.pp' => <<-PUPPET.unindent
|
96
|
-
class mod::baz {}
|
97
|
-
PUPPET
|
72
|
+
'second.yaml' => <<-YAML.unindent,
|
73
|
+
---
|
74
|
+
a: second a
|
75
|
+
b:
|
76
|
+
b1: second b1
|
77
|
+
b3: second b3
|
78
|
+
YAML
|
79
|
+
'the_override.yaml' => <<-YAML.unindent
|
80
|
+
---
|
81
|
+
key: foo_result
|
82
|
+
YAML
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
let(:environment_files) do
|
87
|
+
{
|
88
|
+
'test' => {
|
89
|
+
'modules' => {
|
90
|
+
'mod' => {
|
91
|
+
'manifests' => {
|
92
|
+
'foo.pp' => <<-PUPPET.unindent,
|
93
|
+
class mod::foo {
|
94
|
+
notice(hiera('class_name'))
|
95
|
+
notice(hiera('class_path'))
|
96
|
+
notice(hiera('module'))
|
97
|
+
notice(hiera('mod_name'))
|
98
|
+
}
|
99
|
+
PUPPET
|
100
|
+
'bar.pp' => <<-PUPPET.unindent,
|
101
|
+
class mod::bar {}
|
102
|
+
PUPPET
|
103
|
+
'baz.pp' => <<-PUPPET.unindent
|
104
|
+
class mod::baz {}
|
105
|
+
PUPPET
|
98
106
|
},
|
99
|
-
|
100
|
-
|
101
|
-
|
107
|
+
'hiera.yaml' => <<-YAML.unindent,
|
108
|
+
---
|
109
|
+
version: 5
|
110
|
+
YAML
|
111
|
+
'data' => {
|
112
|
+
'common.yaml' => <<-YAML.unindent
|
113
|
+
mod::c: mod::c (from module)
|
102
114
|
YAML
|
103
|
-
'data' => {
|
104
|
-
'common.yaml' => <<-YAML.unindent
|
105
|
-
mod::c: mod::c (from module)
|
106
|
-
YAML
|
107
|
-
}
|
108
115
|
}
|
109
116
|
}
|
110
117
|
}
|
111
|
-
}
|
118
|
+
}.merge(env_config)
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
let(:global_files) do
|
123
|
+
{
|
124
|
+
'hiera.yaml' => hiera_yaml,
|
125
|
+
'ruby_stuff' => ruby_stuff_files,
|
126
|
+
'hieradata' => hieradata_files,
|
127
|
+
'environments' => environment_files
|
112
128
|
}
|
113
129
|
end
|
114
130
|
|
@@ -129,7 +145,7 @@ describe 'when calling' do
|
|
129
145
|
around(:each) do |example|
|
130
146
|
# Faking the load path to enable 'require' to load from 'ruby_stuff'. It removes the need for a static fixture
|
131
147
|
# for the custom backend
|
132
|
-
dir_contained_in(global_dir,
|
148
|
+
dir_contained_in(global_dir, global_files)
|
133
149
|
$LOAD_PATH.unshift(File.join(global_dir, 'ruby_stuff'))
|
134
150
|
begin
|
135
151
|
Puppet.override(:environments => environments, :current_environment => env) do
|
@@ -332,4 +348,70 @@ describe 'when calling' do
|
|
332
348
|
expect(func('foo') { |k| ['mod::bar', "mod::#{k}"] }.map { |c| c.class_name }).to eql(%w[mod::bar mod::foo])
|
333
349
|
end
|
334
350
|
end
|
351
|
+
|
352
|
+
context 'with merge_behavior declared in hiera.yaml' do
|
353
|
+
let(:hiera_yaml) do
|
354
|
+
<<-YAML.unindent
|
355
|
+
---
|
356
|
+
:backends:
|
357
|
+
- yaml
|
358
|
+
- custom
|
359
|
+
:yaml:
|
360
|
+
:datadir: #{global_dir}/hieradata
|
361
|
+
:hierarchy:
|
362
|
+
- other
|
363
|
+
- common
|
364
|
+
:merge_behavior: deeper
|
365
|
+
YAML
|
366
|
+
end
|
367
|
+
|
368
|
+
let(:global_files) do
|
369
|
+
{
|
370
|
+
'hiera.yaml' => hiera_yaml,
|
371
|
+
'hieradata' => {
|
372
|
+
'common.yaml' => <<-YAML.unindent,
|
373
|
+
dm:
|
374
|
+
dm1:
|
375
|
+
dm11: value of dm11 (from common)
|
376
|
+
dm12: value of dm12 (from common)
|
377
|
+
dm2:
|
378
|
+
dm21: value of dm21 (from common)
|
379
|
+
YAML
|
380
|
+
'other.yaml' => <<-YAML.unindent,
|
381
|
+
dm:
|
382
|
+
dm1:
|
383
|
+
dm11: value of dm11 (from other)
|
384
|
+
dm13: value of dm13 (from other)
|
385
|
+
dm3:
|
386
|
+
dm31: value of dm31 (from other)
|
387
|
+
YAML
|
388
|
+
},
|
389
|
+
'ruby_stuff' => ruby_stuff_files
|
390
|
+
}
|
391
|
+
end
|
392
|
+
|
393
|
+
context 'hiera_hash' do
|
394
|
+
let(:the_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'hiera_hash') }
|
395
|
+
|
396
|
+
it 'the imposed hash strategy does not override declared merge_behavior' do
|
397
|
+
expect(func('dm')).to eql({
|
398
|
+
'dm1' => {
|
399
|
+
'dm11' => 'value of dm11 (from other)',
|
400
|
+
'dm12' => 'value of dm12 (from common)',
|
401
|
+
'dm13' => 'value of dm13 (from other)'
|
402
|
+
},
|
403
|
+
'dm2' => {
|
404
|
+
'dm21' => 'value of dm21 (from common)'
|
405
|
+
},
|
406
|
+
'dm3' => {
|
407
|
+
'dm31' => 'value of dm31 (from other)'
|
408
|
+
}
|
409
|
+
})
|
410
|
+
end
|
411
|
+
|
412
|
+
it "the merge behavior is not propagated to a custom backend as 'resolution_type'" do
|
413
|
+
expect(func('resolution_type')).to eql('resolution_type=')
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
335
417
|
end
|