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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bbb3d1b7ae680827054a63fb3fe802e44769a0b2
4
- data.tar.gz: c63a7977ba8f1c7440fee55996b907b87b9b01a7
3
+ metadata.gz: 60bac673f74c2536d8b6cabef95b12f681870b0b
4
+ data.tar.gz: c2ec8ac4a44a646e7107c77c8c2a3369bb539069
5
5
  SHA512:
6
- metadata.gz: bb2e66fdd215d9fa2494211c9332e20fb1447be490a92c1093b280688f5e37c5b674751ee506089583c7446376af9ce20665df1e6010b67686c3b4c845746b8c
7
- data.tar.gz: 14e69b0c2ccfa644196413e815c77ccf9c09c15628c821b9a73eb8ee2a9d315814acedd606ebf1ed94d2fa4276d5404514e0dad191f8b1384cf25886080c3b9e
6
+ metadata.gz: 56de86472279f036aa8909f2ff792bb5f9dff0ad77067d096a497d3fe48949386a60cebd02bf8b5d71757083ca1263203f590610f6e296742f7779e7fbeadd7f
7
+ data.tar.gz: 456955eeee0d45ee397618a4e5934f7c77bf37f278d4346b2a6bfcf9d8a3e4a941c3402bc605f252faf0212e3008953d55686dd091c33b0dbb61994ca0447a44
@@ -14,7 +14,7 @@ build_dmg: FALSE
14
14
  sign_tar: FALSE
15
15
  yum_host: 'yum.puppetlabs.com'
16
16
  yum_repo_path: '/opt/repository/yum/'
17
- apt_host: 'apt.puppetlabs.com'
17
+ apt_signing_server: 'apt.puppetlabs.com'
18
18
  apt_repo_url: 'http://apt.puppetlabs.com'
19
19
  apt_repo_path: '/opt/repository/incoming'
20
20
  tar_host: 'downloads.puppetlabs.com'
@@ -33,7 +33,7 @@ class Hiera
33
33
  if [CALLING_CLASS, CALLING_CLASS_PATH, CALLING_MODULE].include? key
34
34
  true
35
35
  else
36
- @real.lookupvar(key) != ""
36
+ @real.exist?(key)
37
37
  end
38
38
  end
39
39
 
@@ -12,11 +12,7 @@ class Puppet::Application::Lookup < Puppet::Application
12
12
 
13
13
  # Options for lookup
14
14
  option('--merge TYPE') do |arg|
15
- if %w{unique hash deep}.include?(arg)
16
- options[:merge] = arg
17
- else
18
- raise "The --merge option only accepts 'unique', 'hash', or 'deep'.\n#{RUN_HELP}"
19
- end
15
+ options[:merge] = arg
20
16
  end
21
17
 
22
18
  option('--debug', '-d')
@@ -31,6 +27,8 @@ class Puppet::Application::Lookup < Puppet::Application
31
27
  options[:type] = arg
32
28
  end
33
29
 
30
+ option('--compile', '-c')
31
+
34
32
  option('--knock-out-prefix PREFIX_STRING') do |arg|
35
33
  options[:prefix] = arg
36
34
  end
@@ -45,6 +43,8 @@ class Puppet::Application::Lookup < Puppet::Application
45
43
 
46
44
  option('--explain')
47
45
 
46
+ option('--explain-options')
47
+
48
48
  option('--default VALUE') do |arg|
49
49
  options[:default_value] = arg
50
50
  end
@@ -96,31 +96,6 @@ class Puppet::Application::Lookup < Puppet::Application
96
96
  Puppet::FileBucket::File.indirection.terminus_class = :file
97
97
  end
98
98
 
99
- def setup_ssl
100
- # Configure all of the SSL stuff.
101
- if Puppet::SSL::CertificateAuthority.ca?
102
- Puppet::SSL::Host.ca_location = :local
103
- Puppet.settings.use :ca
104
- Puppet::SSL::CertificateAuthority.instance
105
- else
106
- Puppet::SSL::Host.ca_location = :none
107
- end
108
- # These lines are not on stable (seems like a copy was made from master)
109
- #
110
- # Puppet::SSL::Oids.register_puppet_oids
111
- # Puppet::SSL::Oids.load_custom_oid_file(Puppet[:trusted_oid_mapping_file])
112
- end
113
-
114
- # Sets up a special node cache "write only yaml" that collects and stores node data in yaml
115
- # but never finds or reads anything (this since a real cache causes stale data to be served
116
- # in circumstances when the cache can not be cleared).
117
- # @see puppet issue 16753
118
- # @see Puppet::Node::WriteOnlyYaml
119
- # @return [void]
120
- def setup_node_cache
121
- Puppet::Node.indirection.cache_class = Puppet[:node_cache_terminus]
122
- end
123
-
124
99
  def setup
125
100
  setup_logs
126
101
 
@@ -129,11 +104,6 @@ class Puppet::Application::Lookup < Puppet::Application
129
104
  Puppet.settings.use :main, :master, :ssl, :metrics
130
105
 
131
106
  setup_terminuses
132
-
133
- # TODO: Do we need this in lookup? It sets up a write only cache
134
- setup_node_cache
135
-
136
- setup_ssl
137
107
  end
138
108
 
139
109
  def help
@@ -156,6 +126,7 @@ puppet lookup [--help] [--type <TYPESTRING>] [--merge unique|hash|deep]
156
126
  [--knock-out-prefix <PREFIX-STRING>] [--sort-merged-arrays]
157
127
  [--unpack-arrays <STRING-VALUE>] [--merge-hash-arrays] [--explain]
158
128
  [--default <VALUE>] [--node <NODE-NAME>] [--facts <FILE>]
129
+ [--compile]
159
130
  [--render-as s|json|yaml|binary|msgpack] <keys>
160
131
 
161
132
  DESCRIPTION
@@ -214,6 +185,10 @@ the puppet lookup function linked to above.
214
185
  than the value returned for the key. The explaination will describe how
215
186
  the result was obtained or why lookup failed to obtain the result.
216
187
 
188
+ * --explain-options
189
+ Explain if a lookup_options hash will be used and how it was assembled
190
+ when performing a lookup.
191
+
217
192
  * --default <VALUE>
218
193
  A value produced if no value was found in the lookup.
219
194
 
@@ -227,6 +202,11 @@ the puppet lookup function linked to above.
227
202
  override the facts for the current node. Any facts not specified by the
228
203
  user will maintain their original value.
229
204
 
205
+ * --compile
206
+ Perform a full catalog compilation prior to the lookup. This is meaningful when
207
+ the catalog changes global variables that are referenced in interpolated values.
208
+ No catalog compilation takes place unless this flag is given.
209
+
230
210
  * --render-as s|json|yaml|binary|msgpack
231
211
  Determines how the results will be rendered to the standard output where
232
212
  s means plain text. The default when lookup is producing a value is yaml
@@ -266,7 +246,6 @@ Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
266
246
 
267
247
  def main
268
248
  keys = command_line.args
269
- raise 'No keys were given to lookup.' if keys.empty?
270
249
 
271
250
  #unless options[:node]
272
251
  # raise "No node was given via the '--node' flag for the scope of the lookup.\n#{RUN_HELP}"
@@ -279,8 +258,15 @@ Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
279
258
  use_default_value = !options[:default_value].nil?
280
259
  merge_options = nil
281
260
 
282
- if options[:merge]
283
- if options[:merge] == 'deep'
261
+ merge = options[:merge]
262
+ unless merge.nil?
263
+ strategies = Puppet::Pops::MergeStrategy.strategy_keys
264
+ unless strategies.include?(merge.to_sym)
265
+ strategies = strategies.map {|k| "'#{k}'"}
266
+ raise "The --merge option only accepts #{strategies[0...-1].join(', ')}, or #{strategies.last}\n#{RUN_HELP}"
267
+ end
268
+
269
+ if merge == 'deep'
284
270
  merge_options = {'strategy' => 'deep',
285
271
  'sort_merge_arrays' => !options[:sort_merge_arrays].nil?,
286
272
  'merge_hash_arrays' => !options[:merge_hash_arrays].nil?}
@@ -294,11 +280,22 @@ Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
294
280
  end
295
281
 
296
282
  else
297
- merge_options = {'strategy' => options[:merge]}
283
+ merge_options = {'strategy' => merge}
298
284
  end
299
285
  end
300
286
 
301
- explain = !!options[:explain]
287
+ explain_data = !!options[:explain]
288
+ explain_options = !!options[:explain_options]
289
+ only_explain_options = explain_options && !explain_data
290
+ if keys.empty?
291
+ if only_explain_options
292
+ # Explain lookup_options for lookup of an unqualified value.
293
+ keys = Puppet::Pops::Lookup::GLOBAL
294
+ else
295
+ raise 'No keys were given to lookup.'
296
+ end
297
+ end
298
+ explain = explain_data || explain_options
302
299
 
303
300
  # Format defaults to text (:s) when producing an explanation and :yaml when producing the value
304
301
  format = options[:render_as] || (explain ? :s : :yaml)
@@ -308,7 +305,7 @@ Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
308
305
  type = options.include?(:type) ? Puppet::Pops::Types::TypeParser.new.parse(options[:type]) : nil
309
306
 
310
307
  generate_scope do |scope|
311
- lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, explain)
308
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, explain ? Puppet::Pops::Lookup::Explainer.new(explain_options, only_explain_options) : nil)
312
309
  begin
313
310
  result = Puppet::Pops::Lookup.lookup(keys, type, options[:default_value], use_default_value, merge_options, lookup_invocation)
314
311
  puts renderer.render(result) unless explain
@@ -336,7 +333,7 @@ Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
336
333
  fact_file = options[:fact_file]
337
334
 
338
335
  if fact_file
339
- original_facts = node.facts.values
336
+ original_facts = node.parameters
340
337
  if fact_file.end_with?("json")
341
338
  given_facts = JSON.parse(File.read(fact_file))
342
339
  else
@@ -347,9 +344,10 @@ Copyright (c) 2015 Puppet Labs, LLC Licensed under the Apache 2.0 License
347
344
  raise "Incorrect formatted data in #{fact_file} given via the --facts flag"
348
345
  end
349
346
 
350
- node.facts.values = original_facts.merge(given_facts)
347
+ node.parameters = original_facts.merge(given_facts)
351
348
  end
352
349
 
350
+ Puppet[:code] = 'undef' unless options[:compile]
353
351
  compiler = Puppet::Parser::Compiler.new(node)
354
352
  compiler.compile { |catalog| yield(compiler.topscope); catalog }
355
353
  end
@@ -3,7 +3,9 @@
3
3
  #
4
4
  class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
5
5
 
6
- LOOKUP_OPTIONS = 'lookup_options'.freeze
6
+ LOOKUP_OPTIONS = Puppet::Pops::Lookup::LOOKUP_OPTIONS
7
+ LOOKUP_OPTIONS_PREFIX = LOOKUP_OPTIONS + '.'
8
+ LOOKUP_OPTIONS_PREFIX.freeze
7
9
  HASH = 'hash'.freeze
8
10
  MERGE = 'merge'.freeze
9
11
 
@@ -29,12 +31,43 @@ class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
29
31
  # @throws :no_such_key if the given key is not found
30
32
  #
31
33
  def lookup(key, lookup_invocation, merge)
32
- merge = lookup_merge_options(key, lookup_invocation) if merge.nil?
33
- merge_strategy = Puppet::Pops::MergeStrategy.strategy(merge)
34
- lookup_invocation.with(:merge, merge_strategy) do
35
- result = merge_strategy.merge_lookup([:lookup_global, :lookup_in_environment, :lookup_in_module]) { |m| send(m, key, lookup_invocation, merge_strategy) }
36
- lookup_invocation.report_result(result)
37
- result
34
+ # The 'lookup_options' key is reserved and not found as normal data
35
+ if key == LOOKUP_OPTIONS || key.start_with?(LOOKUP_OPTIONS_PREFIX)
36
+ lookup_invocation.with(:invalid_key, LOOKUP_OPTIONS) do
37
+ throw :no_such_key
38
+ end
39
+ end
40
+
41
+ lookup_invocation.top_key ||= key
42
+ merge_explained = false
43
+ if lookup_invocation.explain_options?
44
+ catch(:no_such_key) do
45
+ module_name = extract_module_name(key) unless key == Puppet::Pops::Lookup::GLOBAL
46
+ lookup_invocation.module_name = module_name
47
+ if lookup_invocation.only_explain_options?
48
+ do_lookup(LOOKUP_OPTIONS, lookup_invocation, HASH)
49
+ return nil
50
+ end
51
+
52
+ # Bypass cache and do a "normal" lookup of the lookup_options
53
+ lookup_invocation.with(:meta, LOOKUP_OPTIONS) do
54
+ key_options = do_lookup(LOOKUP_OPTIONS, lookup_invocation, HASH)[key]
55
+ merge = key_options[MERGE] unless key_options.nil?
56
+ merge_explained = true
57
+ end
58
+ end
59
+ elsif merge.nil?
60
+ # Used cached lookup_options
61
+ merge = lookup_merge_options(key, lookup_invocation)
62
+ lookup_invocation.report_merge_source('lookup_options') unless merge.nil?
63
+ end
64
+
65
+ if merge_explained
66
+ # Merge lookup is explained in detail so we need to explain the data in a section
67
+ # on the same level to avoid confusion
68
+ lookup_invocation.with(:data, key) { do_lookup(key, lookup_invocation, merge) }
69
+ else
70
+ do_lookup(key, lookup_invocation, merge)
38
71
  end
39
72
  end
40
73
 
@@ -44,13 +77,15 @@ class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
44
77
  lookup_invocation.with(:global, terminus) do
45
78
  catch(:no_such_key) do
46
79
  return lookup_invocation.report_found(name, Puppet::DataBinding.indirection.find(name,
47
- { :environment => @env.to_s, :variables => lookup_invocation.scope, :merge => merge_strategy }))
80
+ { :environment => @env, :variables => lookup_invocation.scope, :merge => merge_strategy }))
48
81
  end
49
82
  lookup_invocation.report_not_found(name)
50
83
  throw :no_such_key
51
84
  end
52
- rescue Puppet::DataBinding::LookupError => e
53
- raise Puppet::Error.new("Error from DataBinding '#{terminus}' while looking up '#{name}': #{e.message}", e)
85
+ rescue Puppet::DataBinding::LookupError => detail
86
+ error = Puppet::Error.new("Lookup of key '#{lookup_invocation.top_key}' failed: #{detail.message}")
87
+ error.set_backtrace(detail.backtrace)
88
+ raise error
54
89
  end
55
90
 
56
91
  # @api private
@@ -60,7 +95,7 @@ class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
60
95
 
61
96
  # @api private
62
97
  def lookup_in_module(name, lookup_invocation, merge_strategy)
63
- module_name = extract_module_name(name)
98
+ module_name = lookup_invocation.module_name || extract_module_name(name)
64
99
 
65
100
  # Do not attempt to do a lookup in a module unless the name is qualified.
66
101
  throw :no_such_key if module_name.nil?
@@ -95,41 +130,52 @@ class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
95
130
  module_name = extract_module_name(name)
96
131
 
97
132
  # Retrieve the options for the module. We use nil as a key in case we have none
98
- options = @lookup_options[module_name]
99
- if options.nil? && !@lookup_options.include?(module_name)
133
+ if !@lookup_options.include?(module_name)
100
134
  options = retrieve_lookup_options(module_name, lookup_invocation, Puppet::Pops::MergeStrategy.strategy(HASH))
101
135
  raise Puppet::DataBinding::LookupError.new("value of #{LOOKUP_OPTIONS} must be a hash") unless options.nil? || options.is_a?(Hash)
102
136
  @lookup_options[module_name] = options
137
+ else
138
+ options = @lookup_options[module_name]
103
139
  end
104
140
  options.nil? ? nil : options[name]
105
141
  end
106
142
 
107
143
  private
108
144
 
145
+ def do_lookup(key, lookup_invocation, merge)
146
+ merge_strategy = Puppet::Pops::MergeStrategy.strategy(merge)
147
+ lookup_invocation.with(:merge, merge_strategy) do
148
+ result = merge_strategy.merge_lookup([:lookup_global, :lookup_in_environment, :lookup_in_module]) { |m| send(m, key, lookup_invocation, merge_strategy) }
149
+ lookup_invocation.report_result(result)
150
+ result
151
+ end
152
+ end
153
+
109
154
  # Retrieve lookup options that applies when using a specific module (i.e. a merge of the pre-cached
110
155
  # `env_lookup_options` and the module specific data)
111
156
  def retrieve_lookup_options(module_name, lookup_invocation, merge_strategy)
112
- lookup_invocation.with(:meta, module_name) do
113
- env_opts = env_lookup_options(lookup_invocation, merge_strategy)
114
- options = nil
115
- unless module_name.nil?
116
- catch(:no_such_key) do
117
- options = module_provider(module_name).lookup(LOOKUP_OPTIONS, lookup_invocation, merge_strategy)
118
- options = merge_strategy.merge(env_opts, options) unless env_opts.nil?
119
- end
157
+ meta_invocation = Puppet::Pops::Lookup::Invocation.new(lookup_invocation.scope)
158
+ meta_invocation.top_key = lookup_invocation.top_key
159
+ env_opts = env_lookup_options(meta_invocation, merge_strategy)
160
+ unless module_name.nil? || @env.module(module_name).nil?
161
+ catch(:no_such_key) do
162
+ meta_invocation.module_name = module_name
163
+ options = module_provider(module_name).lookup(LOOKUP_OPTIONS, meta_invocation, merge_strategy)
164
+ options = merge_strategy.merge(env_opts, options) unless env_opts.nil?
165
+ return options
120
166
  end
121
- options.nil? ? env_opts : options
122
167
  end
168
+ env_opts
123
169
  end
124
170
 
125
171
  # Retrieve and cache lookup options specific to the environment that this adapter is attached to (i.e. a merge
126
172
  # of global and environment lookup options).
127
- def env_lookup_options(lookup_invocation, merge_strategy)
128
- unless instance_variable_defined?(:@env_lookup_options)
173
+ def env_lookup_options(meta_invocation, merge_strategy)
174
+ if !instance_variable_defined?(:@env_lookup_options)
129
175
  @env_lookup_options = nil
130
176
  catch(:no_such_key) do
131
177
  @env_lookup_options = merge_strategy.merge_lookup([:lookup_global, :lookup_in_environment]) do |m|
132
- send(m, LOOKUP_OPTIONS, lookup_invocation, merge_strategy)
178
+ send(m, LOOKUP_OPTIONS, meta_invocation, merge_strategy)
133
179
  end
134
180
  end
135
181
  end
@@ -170,7 +216,8 @@ class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
170
216
  unless provider
171
217
  raise Puppet::Error.new("Environment '#{@env.name}', cannot find module_data_provider '#{provider_name}'")
172
218
  end
173
- provider
219
+ # Provider is configured per module but cached using environment life cycle so it must be cloned
220
+ provider.clone
174
221
  end
175
222
 
176
223
  def initialize_env_provider
@@ -1,153 +1,129 @@
1
- # Looks up data defined using Data Binding, and Data Providers using different strategies. The lookup searches in
2
- # Data Bindings first (if configured; typically Hiera), then in the environments data provider (if any), and last in
3
- # the module's data provider (if any) of the module the call to lookup originates from. Thus, the global Data Binding
4
- # has higher priority than data provided in the environment, which has higher priority than data provided in a module,
5
- #
6
- # The lookup function can be called in one of these ways:
7
- #
8
- # lookup(name)
9
- # lookup(name, value_type)
10
- # lookup(name, value_type, merge)
11
- # lookup(name, value_type, merge, default_value)
12
- # lookup(options_hash)
13
- # lookup(name, options_hash)
14
- #
15
- # The function may optionally be called with a code block / lambda with the following signature:
16
- #
17
- # lookup(...) |$name| { ... }
18
- #
19
- # The block, if present, is mutually exclusive to the `default_value` and will be called with the `name` used in the
20
- # lookup when no value is found. The value produced by the block then becomes the value produced by the lookup.
21
- #
22
- # The meaning of the parameters or content of the options hash is:
23
- #
24
- # * `name` - The name or array of names to lookup (first found is returned)
25
- # * `value_type` - The type to assert. Defaults to 'Data' See 'Type Specification' below.
26
- # * `default_value` - The default value if there was no value found (must comply with the data type)
27
- # * `override` - a hash with map from names to values that are used instead of the underlying bindings. If the name
28
- # is found here it wins. Defaults to an empty hash.
29
- # * `default_values_hash` - a hash with map from names to values that are used as a last resort to obtain a value.
30
- # Defaults to an empty hash.
31
- # * `merge` - A string of type Enum[unique, hash, merge] or a hash with the key 'strategy' set to that string. See
32
- # 'Merge Strategies' below.
33
- #
34
- # It is not permitted to pass the `name` as both a parameter and in the options hash.
35
- #
36
- # The search will proceed as follows:
37
- # 1. For each name given in the `name` array (or once, if it's just one name):
38
- # - If a matching key is found in the `override` hash, it's value is immediately type checked and returned
39
- # - Search and optionally merge Data Binding, environment data providers, and module data providers
40
- # - Type check and return the value if a matching key is found
41
- # 2. For each name given in the `name` array (or once, if it's just one name):
42
- # - Type check and return the value if a matching key is found in the `default_values_hash`
43
- # 3. Type check and return either the given `default_value` or the result of calling the code block if either exist
44
- # 4. Raise an error indicating that no matching value was found
45
- #
46
- # *Merge Strategies*
47
- #
48
- # The default behavior of the lookup is to return the first value that is found for the given `name`. The optional
49
- # `merge` parameter will change this so that a lookup makes an attempt to find values in all three sources (the Data
50
- # Binder, the environment, and the module scope) and then merge these values according to the given strategy. This
51
- # does not apply to values found in the 'override' hash. Such values are returned immediately without merging.
52
- # Note that `merge` is passed on to allow the underlying provider to return a merged result
53
- #
54
- # The valid strategies are:
55
- # - 'hash' Performs a simple hash-merge by overwriting keys of lower lookup priority. Merged values must be of Hash type
56
- # - 'unique' Appends everything to an array containing no nested arrays and where all duplicates have been removed. Can
57
- # append values of Scalar or Array[Scalar] type
58
- # - 'deep' Performs a deep merge on values of Array and Hash type. See documentation for the DeepMerge gem's deep_merge
59
- # operation for details and options.
60
- #
61
- # The 'deep' strategy can use additional options to control its behavior. Options can be passed as top level
62
- # keys in the `merge` parameter when it is a given as a hash. Recognized options are:
63
- # - 'knockout_prefix' Set to string value to signify prefix which deletes elements from existing element. Defaults is _undef_
64
- # - 'sort_merged_arrays' Set to _true_ to sort all arrays that are merged together. Default is _false_
65
- # - 'unpack_arrays' Set to string value used as a deliminator to join all array values and then split them again. Default is _undef_
66
- # - 'merge_hash_arrays' Set to _true_ to merge hashes within arrays. Default is _false_
67
- #
68
- # *Type Specification*
69
- #
70
- # The type specification is a type in the Puppet Type System, e.g.:
71
- # * `Integer`, an integral value with optional range e.g.:
72
- # * `Integer[0, default]` - 0 or positive
73
- # * `Integer[default, -1]` - negative,
74
- # * `Integer[1,100]` - value between 1 and 100 inclusive
75
- # * `String`- any string
76
- # * `Float` - floating point number (same signature as for Integer for `Integer` ranges)
77
- # * `Boolean` - true of false (strict)
78
- # * `Array` - an array (of Data by default), or parameterized as `Array[<element_type>]`, where
79
- # `<element_type>` is the expected type of elements
80
- # * `Hash`, - a hash (of default `Literal` keys and `Data` values), or parameterized as
81
- # `Hash[<value_type>]`, `Hash[<key_type>, <value_type>]`, where `<key_type>`, and
82
- # `<value_type>` are the types of the keys and values respectively
83
- # (key is `Literal` by default).
84
- # * `Data` - abstract type representing any `Literal` (including _undef_), `Array[Data]`, or `Hash[Literal, Data]`
85
- # * `Pattern[<p1>, <p2>, ..., <pn>]` - an enumeration of valid patterns (one or more) where
86
- # a pattern is a regular expression string or regular expression,
87
- # e.g. `Pattern['.com$', '.net$']`, `Pattern[/[a-z]+[0-9]+/]`
88
- # * `Enum[<s1>, <s2>, ..., <sn>]`, - an enumeration of exact string values (one or more)
89
- # e.g. `Enum[blue, red, green]`.
90
- # * `Variant[<t1>, <t2>,...<tn>]` - matches one of the listed types (at least one must be given)
91
- # e.g. `Variant[Integer[8000,8999], Integer[20000, 99999]]` to accept a value in either range
92
- # * `Regexp`- a regular expression (i.e. the result is a regular expression, not a string
93
- # matching a regular expression).
94
- #
95
- # For more options and details about types, see the Puppet Language Reference
96
- #
97
- # *Handling of undef*
98
- #
99
- # When no match is found for the given `name` when searching all sources, (including the `override`and
100
- # `default_values_hash`), then the value used is either the `default_value` or the value produced by the given block.
101
- # If neither is provided, then the lookup will always raise an error. Note that this only applies when there's no
102
- # match for the given `name`. It does not happen when a value is found and that value happens to be _undef_.
103
- #
104
- # *Validation of returned value*
105
- #
106
- # The produced value is subject to type validation using the `value_type` (if given) and an error is raised unless
107
- # the resulting value is of correct type.
108
- #
109
- # *Examples*
110
- #
111
- # When called with one argument; **the name**, it
112
- # returns the bound value with the given name after having asserted it has the default datatype `Data`:
113
- #
114
- # lookup('the_name')
115
- #
116
- # When called with two arguments; **the name**, and **the expected type**, it
117
- # returns the bound value with the given name after having asserted it has the given data
118
- # type ('String' in the example):
119
- #
120
- # lookup('the_name', String)
121
- #
122
- # When called with four arguments, **the name**, the **expected type**, the **merge** strategy, and a
123
- # **default value**, it returns the bound value with the given name, or the default after having asserted the value
124
- # has the given data type:
125
- #
126
- # lookup('the_name', String, undef, 'Fred')
127
- # lookup('the_name', Array[String], 'unique', [Fred])
128
- #
129
- # Using a lambda to provide a default value by calling a function:
130
- #
131
- # lookup('the_size', Integer[1,100]) |$name| {
132
- # obtain_size_default()
133
- # }
134
- #
135
- # There are two ways to make lookup return undef when no matching key was found instead of raising an error.
136
- # Either call it with four arguments (the `merge` argument must be present even when using the default strategy
137
- # to ensure that the four argument variant is used):
138
- #
139
- # $are_you_there = lookup('peekaboo', Optional[String], undef, undef)
140
- #
141
- # or call it using an options hash:
142
- #
143
- # $are_you_there = lookup('peekaboo', { 'default_value' => undef })
144
- # $are_you_there = lookup({ 'name' => 'peekaboo', 'default_value' => undef })
145
- #
146
- # or with a block that produces an undef value:
147
- #
148
- # $are_you_there = lookup('peekaboo', Optional[String]) |$name| { undef }
149
- #
150
- # - Since 4.0.0
1
+ # Uses the Puppet lookup system to retrieve a value for a given key. By default,
2
+ # this returns the first value found (and fails compilation if no values are
3
+ # available), but you can configure it to merge multiple values into one, fail
4
+ # gracefully, and more.
5
+ #
6
+ # When looking up a key, Puppet will search up to three tiers of data, in the
7
+ # following order:
8
+ #
9
+ # 1. Hiera.
10
+ # 2. The current environment's data provider.
11
+ # 3. The indicated module's data provider, if the key is of the form
12
+ # `<MODULE NAME>::<SOMETHING>`.
13
+ #
14
+ # #### Arguments
15
+ #
16
+ # You must provide the name of a key to look up, and can optionally provide other
17
+ # arguments. You can combine these arguments in the following ways:
18
+ #
19
+ # * `lookup( <NAME>, [<VALUE TYPE>], [<MERGE BEHAVIOR>], [<DEFAULT VALUE>] )`
20
+ # * `lookup( [<NAME>], <OPTIONS HASH> )`
21
+ # * `lookup( as above ) |$key| { # lambda returns a default value }`
22
+ #
23
+ # Arguments in `[square brackets]` are optional.
24
+ #
25
+ # The arguments accepted by `lookup` are as follows:
26
+ #
27
+ # 1. `<NAME>` (string or array) --- The name of the key to look up.
28
+ # * This can also be an array of keys. If Puppet doesn't find anything for the
29
+ # first key, it will try again with the subsequent ones, only resorting to a
30
+ # default value if none of them succeed.
31
+ # 2. `<VALUE TYPE>` (data type) --- A
32
+ # [data type](https://docs.puppetlabs.com/puppet/latest/reference/lang_data_type.html)
33
+ # that must match the retrieved value; if not, the lookup (and catalog
34
+ # compilation) will fail. Defaults to `Data` (accepts any normal value).
35
+ # 3. `<MERGE BEHAVIOR>` (string or hash; see **"Merge Behaviors"** below) ---
36
+ # Whether (and how) to combine multiple values. If present, this overrides any
37
+ # merge behavior specified in the data sources. Defaults to no value; Puppet will
38
+ # use merge behavior from the data sources if present, and will otherwise do a
39
+ # first-found lookup.
40
+ # 4. `<DEFAULT VALUE>` (any normal value) --- If present, `lookup` returns this
41
+ # when it can't find a normal value. Default values are never merged with found
42
+ # values. Like a normal value, the default must match the value type. Defaults to
43
+ # no value; if Puppet can't find a normal value, the lookup (and compilation) will
44
+ # fail.
45
+ # 5. `<OPTIONS HASH>` (hash) --- Alternate way to set the arguments above, plus
46
+ # some less-common extra options. If you pass an options hash, you can't combine
47
+ # it with any regular arguments (except `<NAME>`). An options hash can have the
48
+ # following keys:
49
+ # * `'name'` --- Same as `<NAME>` (argument 1). You can pass this as an
50
+ # argument or in the hash, but not both.
51
+ # * `'value_type'` --- Same as `<VALUE TYPE>` (argument 2).
52
+ # * `'merge'` --- Same as `<MERGE BEHAVIOR>` (argument 3).
53
+ # * `'default_value'` --- Same as `<DEFAULT VALUE>` (argument 4).
54
+ # * `'default_values_hash'` (hash) --- A hash of lookup keys and default
55
+ # values. If Puppet can't find a normal value, it will check this hash for the
56
+ # requested key before giving up. You can combine this with `default_value` or
57
+ # a lambda, which will be used if the key isn't present in this hash. Defaults
58
+ # to an empty hash.
59
+ # * `'override'` (hash) --- A hash of lookup keys and override values. Puppet
60
+ # will check for the requested key in the overrides hash _first;_ if found, it
61
+ # returns that value as the _final_ value, ignoring merge behavior. Defaults
62
+ # to an empty hash.
63
+ #
64
+ # Finally, `lookup` can take a lambda, which must accept a single parameter.
65
+ # This is yet another way to set a default value for the lookup; if no results are
66
+ # found, Puppet will pass the requested key to the lambda and use its result as
67
+ # the default value.
68
+ #
69
+ # #### Merge Behaviors
70
+ #
71
+ # Puppet lookup uses a hierarchy of data sources, and a given key might have
72
+ # values in multiple sources. By default, Puppet returns the first value it finds,
73
+ # but it can also continue searching and merge all the values together.
74
+ #
75
+ # > **Note:** Data sources can use the special `lookup_options` metadata key to
76
+ # request a specific merge behavior for a key. The `lookup` function will use that
77
+ # requested behavior unless you explicitly specify one.
78
+ #
79
+ # The valid merge behaviors are:
80
+ #
81
+ # * `'first'` --- Returns the first value found, with no merging. Puppet lookup's
82
+ # default behavior.
83
+ # * `'unique'` (called "array merge" in classic Hiera) --- Combines any number of
84
+ # arrays and scalar values to return a merged, flattened array with all duplicate
85
+ # values removed. The lookup will fail if any hash values are found.
86
+ # * `'hash'` --- Combines the keys and values of any number of hashes to return a
87
+ # merged hash. If the same key exists in multiple source hashes, Puppet will use
88
+ # the value from the highest-priority data source; it won't recursively merge the
89
+ # values.
90
+ # * `'deep'` --- Combines the keys and values of any number of hashes to return a
91
+ # merged hash. If the same key exists in multiple source hashes, Puppet will
92
+ # recursively merge hash or array values (with duplicate values removed from
93
+ # arrays). For conflicting scalar values, the highest-priority value will win.
94
+ # * `{'strategy' => 'first|unique|hash'}` --- Same as the string versions of these
95
+ # merge behaviors.
96
+ # * `{'strategy' => 'deep', <DEEP OPTION> => <VALUE>, ...}` --- Same as `'deep'`,
97
+ # but can adjust the merge with additional options. The available options are:
98
+ # * `'knockout_prefix'` (string or undef) --- A string prefix to indicate a
99
+ # value should be _removed_ from the final result. Defaults to `undef`, which
100
+ # disables this feature.
101
+ # * `'sort_merged_arrays'` (boolean) --- Whether to sort all arrays that are
102
+ # merged together. Defaults to `false`.
103
+ # * `'unpack_arrays'` (string or undef) --- A delimiter string; Puppet will
104
+ # join merged arrays with this delimiter, then split them again. Defaults to
105
+ # `undef`, which disables this feature.
106
+ # * `'merge_hash_arrays'` (boolean) --- Whether to merge hashes within arrays.
107
+ # Defaults to `false`.
108
+ #
109
+ # @example Look up a key and return the first value found
110
+ #
111
+ # lookup('ntp::service_name')
112
+ #
113
+ # @example Do a unique merge lookup of class names, then add all of those classes to the catalog (like `hiera_include`)
114
+ #
115
+ # lookup('classes', Array[String], 'unique').include
116
+ #
117
+ # @example Do a deep hash merge lookup of user data, but let higher priority sources remove values by prefixing them with `--`
118
+ #
119
+ # lookup( { 'name' => 'users',
120
+ # 'merge' => {
121
+ # 'strategy' => 'deep',
122
+ # 'knockout_prefix' => '--',
123
+ # },
124
+ # })
125
+ #
126
+ # @since 4.0.0
151
127
  Puppet::Functions.create_function(:lookup, Puppet::Functions::InternalFunction) do
152
128
  name_t = 'Variant[String,Array[String]]'
153
129
  value_type_t = 'Type'