puppet 4.3.1 → 4.3.2

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.

Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +1 -1
  3. data/lib/hiera/scope.rb +1 -1
  4. data/lib/puppet/application/lookup.rb +41 -43
  5. data/lib/puppet/data_providers/lookup_adapter.rb +73 -26
  6. data/lib/puppet/functions/lookup.rb +126 -150
  7. data/lib/puppet/functions/match.rb +1 -0
  8. data/lib/puppet/indirector/hiera.rb +3 -1
  9. data/lib/puppet/indirector/indirection.rb +6 -2
  10. data/lib/puppet/indirector/json.rb +2 -2
  11. data/lib/puppet/module.rb +3 -2
  12. data/lib/puppet/node.rb +11 -2
  13. data/lib/puppet/parser/compiler.rb +1 -8
  14. data/lib/puppet/parser/functions/lookup.rb +128 -149
  15. data/lib/puppet/parser/functions/match.rb +1 -0
  16. data/lib/puppet/plugins/data_providers/data_provider.rb +3 -2
  17. data/lib/puppet/pops/adapters.rb +43 -0
  18. data/lib/puppet/pops/evaluator/access_operator.rb +3 -3
  19. data/lib/puppet/pops/evaluator/closure.rb +51 -51
  20. data/lib/puppet/pops/evaluator/collector_transformer.rb +16 -0
  21. data/lib/puppet/pops/evaluator/runtime3_support.rb +11 -2
  22. data/lib/puppet/pops/functions/function.rb +6 -2
  23. data/lib/puppet/pops/issues.rb +16 -0
  24. data/lib/puppet/pops/loader/puppet_function_instantiator.rb +3 -2
  25. data/lib/puppet/pops/lookup.rb +3 -0
  26. data/lib/puppet/pops/lookup/explainer.rb +73 -3
  27. data/lib/puppet/pops/lookup/invocation.rb +21 -19
  28. data/lib/puppet/pops/model/factory.rb +153 -155
  29. data/lib/puppet/pops/model/model.rb +9 -0
  30. data/lib/puppet/pops/model/model_label_provider.rb +1 -0
  31. data/lib/puppet/pops/parser/evaluating_parser.rb +3 -3
  32. data/lib/puppet/pops/parser/lexer2.rb +411 -393
  33. data/lib/puppet/pops/parser/slurp_support.rb +5 -1
  34. data/lib/puppet/pops/types/type_calculator.rb +2 -6
  35. data/lib/puppet/pops/types/types.rb +3 -9
  36. data/lib/puppet/pops/validation/checker4_0.rb +36 -12
  37. data/lib/puppet/provider/group/windows_adsi.rb +2 -2
  38. data/lib/puppet/provider/package/pip.rb +11 -1
  39. data/lib/puppet/provider/package/rpm.rb +0 -1
  40. data/lib/puppet/provider/package/yum.rb +1 -1
  41. data/lib/puppet/provider/service/debian.rb +5 -18
  42. data/lib/puppet/provider/service/init.rb +7 -0
  43. data/lib/puppet/provider/service/launchd.rb +6 -0
  44. data/lib/puppet/provider/service/systemd.rb +1 -1
  45. data/lib/puppet/provider/user/windows_adsi.rb +2 -2
  46. data/lib/puppet/provider/yumrepo/inifile.rb +6 -3
  47. data/lib/puppet/resource/type.rb +2 -1
  48. data/lib/puppet/transaction/additional_resource_generator.rb +17 -3
  49. data/lib/puppet/type/group.rb +6 -2
  50. data/lib/puppet/util/windows.rb +4 -0
  51. data/lib/puppet/util/windows/adsi.rb +61 -24
  52. data/lib/puppet/util/windows/principal.rb +181 -0
  53. data/lib/puppet/util/windows/registry.rb +21 -15
  54. data/lib/puppet/util/windows/sid.rb +42 -11
  55. data/lib/puppet/version.rb +1 -1
  56. data/spec/fixtures/unit/application/environments/production/data/common.yaml +4 -0
  57. data/spec/fixtures/unit/application/environments/production/manifests/site.pp +1 -0
  58. data/spec/fixtures/unit/application/environments/puppet_func_provider/environment.conf +1 -0
  59. data/spec/fixtures/unit/application/environments/puppet_func_provider/functions/data.pp +10 -0
  60. data/spec/fixtures/unit/application/environments/puppet_func_provider/manifests/site.pp +1 -0
  61. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/data/common.yaml +4 -0
  62. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/data/specific.yaml +4 -0
  63. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/hiera.yaml +7 -0
  64. data/spec/fixtures/unit/data_providers/environments/hiera_modules/data/common.yaml +4 -0
  65. data/spec/fixtures/unit/data_providers/environments/hiera_modules/data/specific.yaml +4 -0
  66. data/spec/fixtures/unit/data_providers/environments/hiera_modules/environment.conf +2 -0
  67. data/spec/fixtures/unit/data_providers/environments/hiera_modules/hiera.yaml +7 -0
  68. data/spec/fixtures/unit/data_providers/environments/hiera_modules/manifests/site.pp +1 -0
  69. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/data/common.yaml +6 -0
  70. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/hiera.yaml +5 -0
  71. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/manifests/init.pp +2 -0
  72. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/metadata.json +9 -0
  73. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/data/common.yaml +4 -0
  74. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/hiera.yaml +5 -0
  75. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/manifests/init.pp +3 -0
  76. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/metadata.json +9 -0
  77. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/functions/usee_puppet.pp +3 -0
  78. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{usee → modules/usee}/lib/puppet/functions/usee/callee.rb +0 -0
  79. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/functions/usee/usee_ruby.rb +6 -0
  80. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/manifests/init.pp +6 -0
  81. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee2/lib/puppet/functions/usee2/callee.rb +5 -0
  82. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_puppet.pp +5 -0
  83. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_puppet_init.pp +5 -0
  84. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_ruby.pp +5 -0
  85. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{user → modules/user}/lib/puppet/functions/user/caller.rb +0 -0
  86. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/caller2.rb +5 -0
  87. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_puppet.rb +5 -0
  88. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_puppet_init.rb +5 -0
  89. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_ruby.rb +5 -0
  90. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +81 -0
  91. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{user → modules/user}/metadata.json +2 -1
  92. data/spec/integration/parser/collection_spec.rb +8 -0
  93. data/spec/integration/util/windows/principal_spec.rb +115 -0
  94. data/spec/{unit → integration}/util/windows/registry_spec.rb +91 -1
  95. data/spec/integration/util/windows/security_spec.rb +2 -2
  96. data/spec/unit/application/lookup_spec.rb +138 -28
  97. data/spec/unit/data_providers/hiera_data_provider_spec.rb +182 -5
  98. data/spec/unit/face/epp_face_spec.rb +2 -2
  99. data/spec/unit/functions/epp_spec.rb +6 -6
  100. data/spec/unit/functions/inline_epp_spec.rb +4 -4
  101. data/spec/unit/functions/lookup_spec.rb +30 -3
  102. data/spec/unit/functions4_spec.rb +1 -1
  103. data/spec/unit/hiera/scope_spec.rb +5 -2
  104. data/spec/unit/indirector/json_spec.rb +1 -1
  105. data/spec/unit/node_spec.rb +8 -0
  106. data/spec/unit/parser/compiler_spec.rb +0 -18
  107. data/spec/unit/pops/evaluator/access_ops_spec.rb +4 -4
  108. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +1 -1
  109. data/spec/unit/pops/loaders/loaders_spec.rb +84 -2
  110. data/spec/unit/pops/parser/lexer2_spec.rb +6 -0
  111. data/spec/unit/pops/parser/parser_rspec_helper.rb +5 -0
  112. data/spec/unit/pops/types/type_calculator_spec.rb +0 -17
  113. data/spec/unit/pops/validator/validator_spec.rb +87 -0
  114. data/spec/unit/provider/group/windows_adsi_spec.rb +8 -8
  115. data/spec/unit/provider/package/pip_spec.rb +41 -13
  116. data/spec/unit/provider/package/rpm_spec.rb +2 -25
  117. data/spec/unit/provider/package/yum_spec.rb +1 -1
  118. data/spec/unit/provider/service/debian_spec.rb +6 -24
  119. data/spec/unit/provider/service/init_spec.rb +11 -1
  120. data/spec/unit/provider/service/launchd_spec.rb +11 -0
  121. data/spec/unit/provider/service/systemd_spec.rb +18 -12
  122. data/spec/unit/provider/service/upstart_spec.rb +57 -0
  123. data/spec/unit/provider/user/windows_adsi_spec.rb +5 -5
  124. data/spec/unit/provider/yumrepo/inifile_spec.rb +16 -0
  125. data/spec/unit/resource_spec.rb +12 -2
  126. data/spec/unit/util/windows/adsi_spec.rb +44 -36
  127. data/spec/unit/util/windows/sid_spec.rb +47 -10
  128. metadata +77 -10
@@ -30,6 +30,7 @@
30
30
  # ~~~ ruby
31
31
  # $matches = ["abc123","def456"].match(/([a-z]+)([1-9]+)/)
32
32
  # # $matches contains [[abc123, abc, 123], [def456, def, 456]]
33
+ # ~~~
33
34
  #
34
35
  # @since 4.0.0
35
36
  #
@@ -23,7 +23,9 @@ class Puppet::Indirector::Hiera < Puppet::Indirector::Terminus
23
23
  throw :no_such_key if value.equal?(not_found)
24
24
  value
25
25
  rescue *DataBindingExceptions => detail
26
- raise Puppet::DataBinding::LookupError.new(detail.message, detail)
26
+ error = Puppet::DataBinding::LookupError.new("DataBinding 'hiera': #{detail.message}")
27
+ error.set_backtrace(detail.backtrace)
28
+ raise error
27
29
  end
28
30
 
29
31
  private
@@ -207,10 +207,14 @@ class Puppet::Indirector::Indirection
207
207
  filtered = result
208
208
  if terminus.respond_to?(:filter)
209
209
  Puppet::Util::Profiler.profile("Filtered result for #{self.name} #{request.key}", [:indirector, :filter, self.name, request.key]) do
210
- filtered = terminus.filter(result)
210
+ begin
211
+ filtered = terminus.filter(result)
212
+ rescue Puppet::Error => detail
213
+ Puppet.log_exception(detail)
214
+ raise detail
215
+ end
211
216
  end
212
217
  end
213
-
214
218
  filtered
215
219
  end
216
220
  end
@@ -15,7 +15,7 @@ class Puppet::Indirector::JSON < Puppet::Indirector::Terminus
15
15
  filename = path(request.key)
16
16
  FileUtils.mkdir_p(File.dirname(filename))
17
17
 
18
- Puppet::Util.replace_file(filename, 0660) {|f| f.print to_json(request.instance) }
18
+ Puppet::Util.replace_file(filename, 0660) {|f| f.print to_json(request.instance).force_encoding(Encoding::ASCII_8BIT) }
19
19
  rescue TypeError => detail
20
20
  Puppet.log_exception(detail, "Could not save #{self.name} #{request.key}: #{detail}")
21
21
  end
@@ -52,7 +52,7 @@ class Puppet::Indirector::JSON < Puppet::Indirector::Terminus
52
52
  json = nil
53
53
 
54
54
  begin
55
- json = File.read(file)
55
+ json = Puppet::FileSystem.read(file).force_encoding(Encoding::ASCII_8BIT)
56
56
  rescue Errno::ENOENT
57
57
  return nil
58
58
  rescue => detail
@@ -155,6 +155,8 @@ class Puppet::Module
155
155
 
156
156
  if attr == :dependencies
157
157
  value.each do |dep|
158
+ name = dep['name']
159
+ dep['name'] = name.tr('-', '/') unless name.nil?
158
160
  dep['version_requirement'] ||= '>= 0.0.0'
159
161
  end
160
162
  end
@@ -269,11 +271,10 @@ class Puppet::Module
269
271
 
270
272
  dependencies.each do |dependency|
271
273
  name = dependency['name']
272
- forge_name = name.tr('-', '/')
273
274
  version_string = dependency['version_requirement'] || '>= 0.0.0'
274
275
 
275
276
  dep_mod = begin
276
- environment.module_by_forge_name(forge_name)
277
+ environment.module_by_forge_name(name)
277
278
  rescue
278
279
  nil
279
280
  end
@@ -21,6 +21,8 @@ class Puppet::Node
21
21
 
22
22
  attr_reader :server_facts
23
23
 
24
+ ENVIRONMENT = 'environment'.freeze
25
+
24
26
  def initialize_from_hash(data)
25
27
  @name = data['name'] || (raise ArgumentError, "No name provided in serialized data")
26
28
  @classes = data['classes'] || []
@@ -48,7 +50,7 @@ class Puppet::Node
48
50
  if @environment
49
51
  @environment
50
52
  else
51
- if env = parameters["environment"]
53
+ if env = parameters[ENVIRONMENT]
52
54
  self.environment = env
53
55
  elsif environment_name
54
56
  self.environment = environment_name
@@ -70,6 +72,13 @@ class Puppet::Node
70
72
  else
71
73
  @environment = env
72
74
  end
75
+
76
+ # Keep environment_name attribute and parameter in sync if they have been set
77
+ unless @environment.nil?
78
+ @parameters[ENVIRONMENT] = @environment.name if @parameters.include?(ENVIRONMENT)
79
+ self.environment_name = @environment.name if instance_variable_defined?(:@environment_name)
80
+ end
81
+ @environment
73
82
  end
74
83
 
75
84
  def has_environment_instance?
@@ -125,7 +134,7 @@ class Puppet::Node
125
134
  end
126
135
  end
127
136
 
128
- @parameters["environment"] ||= self.environment.name.to_s
137
+ @parameters[ENVIRONMENT] ||= self.environment.name.to_s
129
138
  end
130
139
 
131
140
  def add_server_facts(facts)
@@ -803,14 +803,7 @@ class Puppet::Parser::Compiler
803
803
  if trusted_param
804
804
  # Blows up if it is a parameter as it will be set as $trusted by the compiler as if it was a variable
805
805
  node.parameters.delete('trusted')
806
- if trusted_param.is_a?(Hash) && %w{authenticated certname extensions}.all? {|key| trusted_param.has_key?(key) }
807
- # looks like a hash of trusted data - resurrect it
808
- # Allow root to trust the authenticated information if option --trusted is given
809
- if !Puppet.features.root?
810
- # Set as not trusted - but keep the information
811
- trusted_param['authenticated'] = false
812
- end
813
- else
806
+ unless trusted_param.is_a?(Hash) && %w{authenticated certname extensions}.all? {|key| trusted_param.has_key?(key) }
814
807
  # trusted is some kind of garbage, do not resurrect
815
808
  trusted_param = nil
816
809
  end
@@ -1,154 +1,133 @@
1
1
  Puppet::Parser::Functions.newfunction(:lookup, :type => :rvalue, :arity => -2, :doc => <<-'ENDHEREDOC') do |args|
2
- Looks up data defined using Data Binding, and Data Providers using different strategies. The lookup searches in
3
- Data Bindings first (if configured; typically Hiera), then in the environments data provider (if any), and last in
4
- the module's data provider (if any) of the module the call to lookup originates from. Thus, the global Data Binding
5
- has higher priority than data provided in the environment, which has higher priority than data provided in a module,
6
-
7
- The lookup function can be called in one of these ways:
8
-
9
- lookup(name)
10
- lookup(name, value_type)
11
- lookup(name, value_type, merge)
12
- lookup(name, value_type, merge, default_value)
13
- lookup(options_hash)
14
- lookup(name, options_hash)
15
-
16
- The function may optionally be called with a code block / lambda with the following signature:
17
-
18
- lookup(...) |$name| { ... }
19
-
20
- The block, if present, is mutually exclusive to the `default_value` and will be called with the `name` used in the
21
- lookup when no value is found. The value produced by the block then becomes the value produced by the lookup.
22
-
23
- The meaning of the parameters or content of the options hash is:
24
-
25
- * `name` - The name or array of names to lookup (first found is returned)
26
- * `value_type` - The type to assert. Defaults to 'Data' See 'Type Specification' below.
27
- * `default_value` - The default value if there was no value found (must comply with the data type)
28
- * `override` - a hash with map from names to values that are used instead of the underlying bindings. If the name
29
- is found here it wins. Defaults to an empty hash.
30
- * `default_values_hash` - a hash with map from names to values that are used as a last resort to obtain a value.
31
- Defaults to an empty hash.
32
- * `merge` - A string of type Enum[unique, hash, merge] or a hash with the key 'strategy' set to that string. See
33
- 'Merge Strategies' below.
34
-
35
- It is not permitted to pass the `name` as both a parameter and in the options hash.
36
-
37
- The search will proceed as follows:
38
- 1. For each name given in the `name` array (or once, if it's just one name):
39
- - If a matching key is found in the `override` hash, it's value is immediately type checked and returned
40
- - Search and optionally merge Data Binding, environment data providers, and module data providers
41
- - Type check and return the value if a matching key is found
42
- 2. For each name given in the `name` array (or once, if it's just one name):
43
- - Type check and return the value if a matching key is found in the `default_values_hash`
44
- 3. Type check and return either the given `default_value` or the result of calling the code block if either exist
45
- 4. Raise an error indicating that no matching value was found
46
-
47
- *Merge Strategies*
48
-
49
- The default behavior of the lookup is to return the first value that is found for the given `name`. The optional
50
- `merge` parameter will change this so that a lookup makes an attempt to find values in all three sources (the Data
51
- Binder, the environment, and the module scope) and then merge these values according to the given strategy. This
52
- does not apply to values found in the 'override' hash. Such values are returned immediately without merging.
53
- Note that `merge` is passed on to allow the underlying provider to return a merged result
54
-
55
- The valid strategies are:
56
- - 'hash' Performs a simple hash-merge by overwriting keys of lower lookup priority. Merged values must be of Hash type
57
- - 'unique' Appends everything to an array containing no nested arrays and where all duplicates have been removed. Can
58
- append values of Scalar or Array[Scalar] type
59
- - 'deep' Performs a deep merge on values of Array and Hash type. See documentation for the DeepMerge gem's deep_merge
60
- operation for details and options.
61
-
62
- The 'deep' strategy can use additional options to control its behavior. Options can be passed as top level
63
- keys in the `merge` parameter when it is a given as a hash. Recognized options are:
64
- - 'knockout_prefix' Set to string value to signify prefix which deletes elements from existing element. Defaults is _undef_
65
- - 'sort_merged_arrays' Set to _true_ to sort all arrays that are merged together. Default is _false_
66
- - 'unpack_arrays' Set to string value used as a deliminator to join all array values and then split them again. Default is _undef_
67
- - 'merge_hash_arrays' Set to _true_ to merge hashes within arrays. Default is _false_
68
-
69
- *Type Specification*
70
-
71
- The type specification is a type in the Puppet Type System, e.g.:
72
- * `Integer`, an integral value with optional range e.g.:
73
- * `Integer[0, default]` - 0 or positive
74
- * `Integer[default, -1]` - negative,
75
- * `Integer[1,100]` - value between 1 and 100 inclusive
76
- * `String`- any string
77
- * `Float` - floating point number (same signature as for Integer for `Integer` ranges)
78
- * `Boolean` - true of false (strict)
79
- * `Array` - an array (of Data by default), or parameterized as `Array[<element_type>]`, where
80
- `<element_type>` is the expected type of elements
81
- * `Hash`, - a hash (of default `Literal` keys and `Data` values), or parameterized as
82
- `Hash[<value_type>]`, `Hash[<key_type>, <value_type>]`, where `<key_type>`, and
83
- `<value_type>` are the types of the keys and values respectively
84
- (key is `Literal` by default).
85
- * `Data` - abstract type representing any `Literal` (including _undef_), `Array[Data]`, or `Hash[Literal, Data]`
86
- * `Pattern[<p1>, <p2>, ..., <pn>]` - an enumeration of valid patterns (one or more) where
87
- a pattern is a regular expression string or regular expression,
88
- e.g. `Pattern['.com$', '.net$']`, `Pattern[/[a-z]+[0-9]+/]`
89
- * `Enum[<s1>, <s2>, ..., <sn>]`, - an enumeration of exact string values (one or more)
90
- e.g. `Enum[blue, red, green]`.
91
- * `Variant[<t1>, <t2>,...<tn>]` - matches one of the listed types (at least one must be given)
92
- e.g. `Variant[Integer[8000,8999], Integer[20000, 99999]]` to accept a value in either range
93
- * `Regexp`- a regular expression (i.e. the result is a regular expression, not a string
94
- matching a regular expression).
95
-
96
- For more options and details about types, see the Puppet Language Reference
97
-
98
- *Handling of undef*
99
-
100
- When no match is found for the given `name` when searching all sources, (including the `override`and
101
- `default_values_hash`), then the value used is either the `default_value` or the value produced by the given block.
102
- If neither is provided, then the lookup will always raise an error. Note that this only applies when there's no
103
- match for the given `name`. It does not happen when a value is found and that value happens to be _undef_.
104
-
105
- *Validation of returned value*
2
+ Uses the Puppet lookup system to retrieve a value for a given key. By default,
3
+ this returns the first value found (and fails compilation if no values are
4
+ available), but you can configure it to merge multiple values into one, fail
5
+ gracefully, and more.
6
+
7
+ When looking up a key, Puppet will search up to three tiers of data, in the
8
+ following order:
9
+
10
+ 1. Hiera.
11
+ 2. The current environment's data provider.
12
+ 3. The indicated module's data provider, if the key is of the form
13
+ `<MODULE NAME>::<SOMETHING>`.
14
+
15
+ #### Arguments
16
+
17
+ You must provide the name of a key to look up, and can optionally provide other
18
+ arguments. You can combine these arguments in the following ways:
19
+
20
+ * `lookup( <NAME>, [<VALUE TYPE>], [<MERGE BEHAVIOR>], [<DEFAULT VALUE>] )`
21
+ * `lookup( [<NAME>], <OPTIONS HASH> )`
22
+ * `lookup( as above ) |$key| { # lambda returns a default value }`
23
+
24
+ Arguments in `[square brackets]` are optional.
25
+
26
+ The arguments accepted by `lookup` are as follows:
27
+
28
+ 1. `<NAME>` (string or array) --- The name of the key to look up.
29
+ * This can also be an array of keys. If Puppet doesn't find anything for the
30
+ first key, it will try again with the subsequent ones, only resorting to a
31
+ default value if none of them succeed.
32
+ 2. `<VALUE TYPE>` (data type) --- A
33
+ [data type](https://docs.puppetlabs.com/puppet/latest/reference/lang_data_type.html)
34
+ that must match the retrieved value; if not, the lookup (and catalog
35
+ compilation) will fail. Defaults to `Data` (accepts any normal value).
36
+ 3. `<MERGE BEHAVIOR>` (string or hash; see **"Merge Behaviors"** below) ---
37
+ Whether (and how) to combine multiple values. If present, this overrides any
38
+ merge behavior specified in the data sources. Defaults to no value; Puppet will
39
+ use merge behavior from the data sources if present, and will otherwise do a
40
+ first-found lookup.
41
+ 4. `<DEFAULT VALUE>` (any normal value) --- If present, `lookup` returns this
42
+ when it can't find a normal value. Default values are never merged with found
43
+ values. Like a normal value, the default must match the value type. Defaults to
44
+ no value; if Puppet can't find a normal value, the lookup (and compilation) will
45
+ fail.
46
+ 5. `<OPTIONS HASH>` (hash) --- Alternate way to set the arguments above, plus
47
+ some less-common extra options. If you pass an options hash, you can't combine
48
+ it with any regular arguments (except `<NAME>`). An options hash can have the
49
+ following keys:
50
+ * `'name'` --- Same as `<NAME>` (argument 1). You can pass this as an
51
+ argument or in the hash, but not both.
52
+ * `'value_type'` --- Same as `<VALUE TYPE>` (argument 2).
53
+ * `'merge'` --- Same as `<MERGE BEHAVIOR>` (argument 3).
54
+ * `'default_value'` --- Same as `<DEFAULT VALUE>` (argument 4).
55
+ * `'default_values_hash'` (hash) --- A hash of lookup keys and default
56
+ values. If Puppet can't find a normal value, it will check this hash for the
57
+ requested key before giving up. You can combine this with `default_value` or
58
+ a lambda, which will be used if the key isn't present in this hash. Defaults
59
+ to an empty hash.
60
+ * `'override'` (hash) --- A hash of lookup keys and override values. Puppet
61
+ will check for the requested key in the overrides hash _first;_ if found, it
62
+ returns that value as the _final_ value, ignoring merge behavior. Defaults
63
+ to an empty hash.
64
+
65
+ Finally, `lookup` can take a lambda, which must accept a single parameter.
66
+ This is yet another way to set a default value for the lookup; if no results are
67
+ found, Puppet will pass the requested key to the lambda and use its result as
68
+ the default value.
69
+
70
+ #### Merge Behaviors
71
+
72
+ Puppet lookup uses a hierarchy of data sources, and a given key might have
73
+ values in multiple sources. By default, Puppet returns the first value it finds,
74
+ but it can also continue searching and merge all the values together.
75
+
76
+ > **Note:** Data sources can use the special `lookup_options` metadata key to
77
+ request a specific merge behavior for a key. The `lookup` function will use that
78
+ requested behavior unless you explicitly specify one.
79
+
80
+ The valid merge behaviors are:
81
+
82
+ * `'first'` --- Returns the first value found, with no merging. Puppet lookup's
83
+ default behavior.
84
+ * `'unique'` (called "array merge" in classic Hiera) --- Combines any number of
85
+ arrays and scalar values to return a merged, flattened array with all duplicate
86
+ values removed. The lookup will fail if any hash values are found.
87
+ * `'hash'` --- Combines the keys and values of any number of hashes to return a
88
+ merged hash. If the same key exists in multiple source hashes, Puppet will use
89
+ the value from the highest-priority data source; it won't recursively merge the
90
+ values.
91
+ * `'deep'` --- Combines the keys and values of any number of hashes to return a
92
+ merged hash. If the same key exists in multiple source hashes, Puppet will
93
+ recursively merge hash or array values (with duplicate values removed from
94
+ arrays). For conflicting scalar values, the highest-priority value will win.
95
+ * `{'strategy' => 'first|unique|hash'}` --- Same as the string versions of these
96
+ merge behaviors.
97
+ * `{'strategy' => 'deep', <DEEP OPTION> => <VALUE>, ...}` --- Same as `'deep'`,
98
+ but can adjust the merge with additional options. The available options are:
99
+ * `'knockout_prefix'` (string or undef) --- A string prefix to indicate a
100
+ value should be _removed_ from the final result. Defaults to `undef`, which
101
+ disables this feature.
102
+ * `'sort_merged_arrays'` (boolean) --- Whether to sort all arrays that are
103
+ merged together. Defaults to `false`.
104
+ * `'unpack_arrays'` (string or undef) --- A delimiter string; Puppet will
105
+ join merged arrays with this delimiter, then split them again. Defaults to
106
+ `undef`, which disables this feature.
107
+ * `'merge_hash_arrays'` (boolean) --- Whether to merge hashes within arrays.
108
+ Defaults to `false`.
109
+
110
+ #### Examples
111
+
112
+ Look up a key and return the first value found:
113
+
114
+ lookup('ntp::service_name')
115
+
116
+ Do a unique merge lookup of class names, then add all of those classes to the
117
+ catalog (like `hiera_include`):
118
+
119
+ lookup('classes', Array[String], 'unique').include
120
+
121
+ Do a deep hash merge lookup of user data, but let higher priority sources
122
+ remove values by prefixing them with `--`:
123
+
124
+ lookup( { 'name' => 'users',
125
+ 'merge' => {
126
+ 'strategy' => 'deep',
127
+ 'knockout_prefix' => '--',
128
+ },
129
+ })
106
130
 
107
- The produced value is subject to type validation using the `value_type` (if given) and an error is raised unless
108
- the resulting value is of correct type.
109
-
110
- *Examples*
111
-
112
- When called with one argument; **the name**, it
113
- returns the bound value with the given name after having asserted it has the default datatype `Data`:
114
-
115
- lookup('the_name')
116
-
117
- When called with two arguments; **the name**, and **the expected type**, it
118
- returns the bound value with the given name after having asserted it has the given data
119
- type ('String' in the example):
120
-
121
- lookup('the_name', String)
122
-
123
- When called with four arguments, **the name**, the **expected type**, the **merge** strategy, and a
124
- **default value**, it returns the bound value with the given name, or the default after having asserted the value
125
- has the given data type:
126
-
127
- lookup('the_name', String, undef, 'Fred')
128
- lookup('the_name', Array[String], 'unique', [Fred])
129
-
130
- Using a lambda to provide a default value by calling a function:
131
-
132
- lookup('the_size', Integer[1,100]) |$name| {
133
- obtain_size_default()
134
- }
135
-
136
- There are two ways to make lookup return undef when no matching key was found instead of raising an error.
137
- Either call it with four arguments (the `merge` argument must be present even when using the default strategy
138
- to ensure that the four argument variant is used):
139
-
140
- $are_you_there = lookup('peekaboo', Optional[String], undef, undef)
141
-
142
- or call it using an options hash:
143
-
144
- $are_you_there = lookup('peekaboo', { 'default_value' => undef })
145
- $are_you_there = lookup({ 'name' => 'peekaboo', 'default_value' => undef })
146
-
147
- or with a block that produces an undef value:
148
-
149
- $are_you_there = lookup('peekaboo', Optional[String]) |$name| { undef }
150
-
151
- - Since 4.0.0
152
131
  ENDHEREDOC
153
132
  function_fail(["lookup() has been converted to 4x API"])
154
133
  end
@@ -34,6 +34,7 @@ $matches = "abc123".match(/([a-z]+)([1-9]+)/)
34
34
  ~~~ ruby
35
35
  $matches = ["abc123","def456"].match(/([a-z]+)([1-9]+)/)
36
36
  # $matches contains [[abc123, abc, 123], [def456, def, 456]]
37
+ ~~~
37
38
 
38
39
  - Since 4.0.0
39
40
  DOC
@@ -98,6 +98,7 @@ module Puppet::Plugins::DataProviders
98
98
  end
99
99
 
100
100
  class ModuleDataProvider
101
+ LOOKUP_OPTIONS = Puppet::Pops::Lookup::LOOKUP_OPTIONS
101
102
  include DataProvider
102
103
 
103
104
  # Retrieve the first segment of the qualified name _key_. This method will throw
@@ -106,7 +107,7 @@ module Puppet::Plugins::DataProviders
106
107
  # @param key [String] The key
107
108
  # @return [String] The first segment of the given key
108
109
  def data_key(key, lookup_invocation)
109
- return lookup_invocation.module_name if key == 'lookup_options'
110
+ return lookup_invocation.module_name if key == LOOKUP_OPTIONS
110
111
  qual_index = key.index('::')
111
112
  throw :no_such_key if qual_index.nil?
112
113
  key[0..qual_index-1]
@@ -121,7 +122,7 @@ module Puppet::Plugins::DataProviders
121
122
  def validate_data(data, module_name)
122
123
  module_prefix = "#{module_name}::"
123
124
  data.each_key do |k|
124
- unless k.is_a?(String) && (k == 'lookup_options' || k.start_with?(module_prefix))
125
+ unless k.is_a?(String) && (k == LOOKUP_OPTIONS || k.start_with?(module_prefix))
125
126
  raise Puppet::DataBinding::LookupError, "Module data for module '#{module_name}' must use keys qualified with the name of the module"
126
127
  end
127
128
  end