puppet 4.8.2-x86-mingw32 → 4.9.0-x86-mingw32

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 (348) hide show
  1. checksums.yaml +15 -0
  2. data/CONTRIBUTING.md +25 -1
  3. data/Gemfile +6 -0
  4. data/Rakefile +1 -0
  5. data/ext/project_data.yaml +5 -1
  6. data/ext/windows/service/daemon.rb +2 -1
  7. data/install.rb +43 -6
  8. data/lib/hiera/puppet_function.rb +15 -17
  9. data/lib/hiera/scope.rb +12 -14
  10. data/lib/puppet.rb +52 -0
  11. data/lib/puppet/application/face_base.rb +4 -0
  12. data/lib/puppet/application/lookup.rb +4 -2
  13. data/lib/puppet/application/resource.rb +1 -1
  14. data/lib/puppet/data_providers.rb +6 -3
  15. data/lib/puppet/data_providers/data_adapter.rb +6 -0
  16. data/lib/puppet/data_providers/data_function_support.rb +7 -0
  17. data/lib/puppet/data_providers/function_env_data_provider.rb +7 -0
  18. data/lib/puppet/data_providers/function_module_data_provider.rb +6 -0
  19. data/lib/puppet/data_providers/hiera_config.rb +31 -10
  20. data/lib/puppet/data_providers/hiera_env_data_provider.rb +6 -0
  21. data/lib/puppet/data_providers/hiera_interpolate.rb +2 -1
  22. data/lib/puppet/data_providers/hiera_module_data_provider.rb +6 -0
  23. data/lib/puppet/data_providers/hiera_support.rb +6 -0
  24. data/lib/puppet/data_providers/json_data_provider_factory.rb +12 -0
  25. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +12 -0
  26. data/lib/puppet/defaults.rb +25 -4
  27. data/lib/puppet/face/ca.rb +2 -0
  28. data/lib/puppet/face/certificate_request.rb +2 -0
  29. data/lib/puppet/face/certificate_revocation_list.rb +2 -0
  30. data/lib/puppet/face/file.rb +3 -0
  31. data/lib/puppet/face/help.rb +19 -17
  32. data/lib/puppet/face/help/face.erb +3 -0
  33. data/lib/puppet/face/key.rb +1 -0
  34. data/lib/puppet/face/man.rb +4 -2
  35. data/lib/puppet/face/module/generate.rb +1 -1
  36. data/lib/puppet/face/status.rb +2 -0
  37. data/lib/puppet/feature/base.rb +9 -2
  38. data/lib/puppet/feature/hocon.rb +3 -0
  39. data/lib/puppet/file_system.rb +15 -3
  40. data/lib/puppet/file_system/windows.rb +8 -0
  41. data/lib/puppet/forge.rb +6 -6
  42. data/lib/puppet/forge/repository.rb +1 -2
  43. data/lib/puppet/functions/binary_file.rb +4 -10
  44. data/lib/puppet/functions/hiera_array.rb +1 -1
  45. data/lib/puppet/functions/hiera_include.rb +1 -1
  46. data/lib/puppet/functions/hocon_data.rb +24 -0
  47. data/lib/puppet/functions/json_data.rb +18 -0
  48. data/lib/puppet/functions/yaml_data.rb +21 -0
  49. data/lib/puppet/generate/type.rb +1 -1
  50. data/lib/puppet/graph/simple_graph.rb +4 -2
  51. data/lib/puppet/indirector/file_bucket_file/file.rb +10 -2
  52. data/lib/puppet/indirector/request.rb +5 -1
  53. data/lib/puppet/interface.rb +14 -2
  54. data/lib/puppet/interface/face_collection.rb +1 -1
  55. data/lib/puppet/module.rb +14 -2
  56. data/lib/puppet/module_tool.rb +4 -4
  57. data/lib/puppet/module_tool/applications/builder.rb +3 -2
  58. data/lib/puppet/module_tool/applications/installer.rb +14 -14
  59. data/lib/puppet/module_tool/applications/upgrader.rb +13 -13
  60. data/lib/puppet/module_tool/installed_modules.rb +7 -7
  61. data/lib/puppet/module_tool/local_tarball.rb +3 -3
  62. data/lib/puppet/module_tool/metadata.rb +1 -1
  63. data/lib/puppet/network/http/connection.rb +2 -0
  64. data/lib/puppet/network/http/webrick.rb +2 -1
  65. data/lib/puppet/parser/functions/hiera.rb +14 -0
  66. data/lib/puppet/parser/functions/hiera_array.rb +14 -0
  67. data/lib/puppet/parser/functions/hiera_hash.rb +14 -0
  68. data/lib/puppet/parser/functions/hiera_include.rb +14 -0
  69. data/lib/puppet/parser/scope.rb +14 -20
  70. data/lib/puppet/plugins/data_providers.rb +2 -0
  71. data/lib/puppet/plugins/data_providers/data_provider.rb +108 -17
  72. data/lib/puppet/plugins/data_providers/registry.rb +2 -36
  73. data/lib/puppet/pops.rb +6 -9
  74. data/lib/puppet/pops/adaptable.rb +0 -3
  75. data/lib/puppet/pops/binder/producers.rb +3 -3
  76. data/lib/puppet/pops/evaluator/access_operator.rb +4 -4
  77. data/lib/puppet/pops/evaluator/closure.rb +1 -1
  78. data/lib/puppet/pops/evaluator/compare_operator.rb +4 -4
  79. data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
  80. data/lib/puppet/pops/issues.rb +4 -0
  81. data/lib/puppet/pops/label_provider.rb +14 -0
  82. data/lib/puppet/pops/loader/loader_paths.rb +3 -1
  83. data/lib/puppet/pops/loader/module_loaders.rb +21 -7
  84. data/lib/puppet/pops/loader/typed_name.rb +0 -2
  85. data/lib/puppet/pops/loaders.rb +31 -12
  86. data/lib/puppet/pops/lookup.rb +4 -3
  87. data/lib/puppet/pops/lookup/configured_data_provider.rb +87 -0
  88. data/lib/puppet/pops/lookup/context.rb +121 -71
  89. data/lib/puppet/pops/lookup/data_adapter.rb +27 -0
  90. data/lib/puppet/pops/lookup/data_dig_function_provider.rb +55 -0
  91. data/lib/puppet/pops/lookup/data_hash_function_provider.rb +111 -0
  92. data/lib/puppet/pops/lookup/data_provider.rb +102 -0
  93. data/lib/puppet/pops/lookup/environment_data_provider.rb +27 -0
  94. data/lib/puppet/pops/lookup/explainer.rb +122 -82
  95. data/lib/puppet/pops/lookup/function_provider.rb +82 -0
  96. data/lib/puppet/pops/lookup/global_data_provider.rb +49 -0
  97. data/lib/puppet/pops/lookup/hiera_config.rb +601 -0
  98. data/lib/puppet/pops/lookup/interpolation.rb +56 -35
  99. data/lib/puppet/pops/lookup/invocation.rb +179 -101
  100. data/lib/puppet/pops/lookup/location_resolver.rb +72 -0
  101. data/lib/puppet/pops/lookup/lookup_adapter.rb +451 -0
  102. data/lib/puppet/pops/lookup/lookup_key.rb +99 -0
  103. data/lib/puppet/pops/lookup/lookup_key_function_provider.rb +119 -0
  104. data/lib/puppet/pops/lookup/module_data_provider.rb +58 -0
  105. data/lib/puppet/pops/lookup/sub_lookup.rb +8 -4
  106. data/lib/puppet/pops/merge_strategy.rb +120 -39
  107. data/lib/puppet/pops/parser/egrammar.ra +2 -0
  108. data/lib/puppet/pops/parser/eparser.rb +816 -808
  109. data/lib/puppet/pops/parser/locator.rb +3 -3
  110. data/lib/puppet/pops/parser/slurp_support.rb +4 -3
  111. data/lib/puppet/pops/pcore.rb +21 -12
  112. data/lib/puppet/pops/serialization/abstract_reader.rb +17 -7
  113. data/lib/puppet/pops/serialization/abstract_writer.rb +27 -12
  114. data/lib/puppet/pops/serialization/deserializer.rb +17 -4
  115. data/lib/puppet/pops/serialization/extension.rb +37 -8
  116. data/lib/puppet/pops/serialization/object.rb +14 -6
  117. data/lib/puppet/pops/serialization/rgen.rb +2 -1
  118. data/lib/puppet/pops/serialization/serializer.rb +30 -7
  119. data/lib/puppet/pops/types/implementation_registry.rb +1 -1
  120. data/lib/puppet/pops/types/p_object_type.rb +55 -12
  121. data/lib/puppet/pops/types/p_sem_ver_range_type.rb +27 -27
  122. data/lib/puppet/pops/types/p_sem_ver_type.rb +12 -12
  123. data/lib/puppet/pops/types/p_timespan_type.rb +6 -6
  124. data/lib/puppet/pops/types/p_timestamp_type.rb +2 -2
  125. data/lib/puppet/pops/types/p_type_set_type.rb +7 -16
  126. data/lib/puppet/pops/types/recursion_guard.rb +64 -20
  127. data/lib/puppet/pops/types/ruby_generator.rb +10 -0
  128. data/lib/puppet/pops/types/type_calculator.rb +23 -13
  129. data/lib/puppet/pops/types/type_factory.rb +20 -9
  130. data/lib/puppet/pops/types/type_formatter.rb +37 -17
  131. data/lib/puppet/pops/types/type_mismatch_describer.rb +7 -6
  132. data/lib/puppet/pops/types/type_parser.rb +6 -0
  133. data/lib/puppet/pops/types/types.rb +225 -132
  134. data/lib/puppet/pops/validation.rb +1 -1
  135. data/lib/puppet/pops/validation/checker4_0.rb +12 -2
  136. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  137. data/lib/puppet/pops/visitor.rb +4 -3
  138. data/lib/puppet/provider/mcx/mcxcontent.rb +2 -1
  139. data/lib/puppet/provider/nameservice.rb +15 -0
  140. data/lib/puppet/provider/package/appdmg.rb +1 -1
  141. data/lib/puppet/provider/package/dnf.rb +1 -1
  142. data/lib/puppet/provider/package/pkg.rb +1 -1
  143. data/lib/puppet/provider/package/pkgdmg.rb +1 -1
  144. data/lib/puppet/provider/package/pkgng.rb +1 -1
  145. data/lib/puppet/provider/package/rpm.rb +2 -2
  146. data/lib/puppet/provider/service/smf.rb +3 -3
  147. data/lib/puppet/provider/service/systemd.rb +5 -1
  148. data/lib/puppet/provider/user/directoryservice.rb +1 -0
  149. data/lib/puppet/provider/user/user_role_add.rb +15 -0
  150. data/lib/puppet/provider/yumrepo/inifile.rb +2 -2
  151. data/lib/puppet/provider/zone/solaris.rb +4 -1
  152. data/lib/puppet/reference/indirection.rb +1 -1
  153. data/lib/puppet/resource.rb +2 -3
  154. data/lib/puppet/resource/catalog.rb +12 -4
  155. data/lib/puppet/resource/type.rb +3 -3
  156. data/lib/puppet/settings.rb +1 -1
  157. data/lib/puppet/settings/config_file.rb +2 -1
  158. data/lib/puppet/settings/directory_setting.rb +6 -0
  159. data/lib/puppet/settings/environment_conf.rb +6 -2
  160. data/lib/puppet/settings/file_or_directory_setting.rb +6 -0
  161. data/lib/puppet/settings/file_setting.rb +10 -0
  162. data/lib/puppet/ssl/certificate_authority.rb +13 -2
  163. data/lib/puppet/ssl/host.rb +23 -1
  164. data/lib/puppet/transaction/additional_resource_generator.rb +7 -0
  165. data/lib/puppet/type/user.rb +16 -3
  166. data/lib/puppet/util.rb +1 -0
  167. data/lib/puppet/util/execution.rb +3 -3
  168. data/lib/puppet/util/filetype.rb +11 -5
  169. data/lib/puppet/util/logging.rb +2 -1
  170. data/lib/puppet/util/network_device/config.rb +1 -1
  171. data/lib/puppet/util/plist.rb +6 -0
  172. data/lib/puppet/util/profiler/aggregate.rb +1 -1
  173. data/lib/puppet/util/rdoc/generators/puppet_generator.rb +2 -2
  174. data/lib/puppet/util/rdoc/parser/puppet_parser_core.rb +2 -1
  175. data/lib/puppet/util/windows/adsi.rb +15 -12
  176. data/lib/puppet/vendor/load_semantic_puppet.rb +1 -0
  177. data/lib/puppet/vendor/pathspec/lib/pathspec.rb +2 -1
  178. data/lib/puppet/vendor/require_vendored.rb +0 -1
  179. data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet.rb +17 -0
  180. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency.rb +7 -7
  181. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/graph.rb +2 -2
  182. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/graph_node.rb +2 -2
  183. data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/dependency/module_release.rb +58 -0
  184. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/source.rb +2 -2
  185. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/dependency/unsatisfiable_graph.rb +2 -2
  186. data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/gem_version.rb +3 -0
  187. data/lib/puppet/vendor/semantic_puppet/lib/semantic_puppet/locales/config.yaml +21 -0
  188. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/version.rb +48 -21
  189. data/lib/puppet/vendor/{semantic/lib/semantic → semantic_puppet/lib/semantic_puppet}/version_range.rb +15 -17
  190. data/lib/puppet/version.rb +1 -1
  191. data/lib/semver.rb +19 -12
  192. data/locales/config.yaml +29 -0
  193. data/locales/puppet.pot +79 -0
  194. data/man/man5/puppet.conf.5 +1 -1
  195. data/spec/fixtures/unit/application/environments/puppet_func_provider/functions/{data.pp → environment/data.pp} +0 -0
  196. data/spec/fixtures/unit/data_providers/environments/hiera_misc/data/common.yaml +2 -0
  197. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/data/common.yaml +1 -1
  198. data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/hiera.yaml +5 -0
  199. data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/lib/puppet/bindings/backend/default.rb +9 -0
  200. data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/lib/puppet_x/backend/special_data_provider_factory.rb +23 -0
  201. data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/manifests/init.pp +5 -0
  202. data/spec/fixtures/unit/data_providers/environments/sample/modules/backend/metadata.json +9 -0
  203. data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_env_data.rb +1 -0
  204. data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/manifests/init.pp +1 -1
  205. data/spec/fixtures/unit/functions/lookup/data/common.yaml +19 -0
  206. data/spec/fixtures/unit/functions/lookup_fixture/data/common.yaml +19 -0
  207. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/environment.conf +0 -0
  208. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/lib/puppet/functions/environment/data.rb +0 -0
  209. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/abc/lib/puppet/bindings/abc/default.rb +0 -0
  210. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/abc/lib/puppet/functions/abc/data.rb +0 -0
  211. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/abc/manifests/init.pp +0 -0
  212. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bad_data/lib/puppet/bindings/bad_data/default.rb +0 -0
  213. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bad_data/lib/puppet/functions/bad_data/data.rb +0 -0
  214. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bad_data/manifests/init.pp +0 -0
  215. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bca/lib/puppet/bindings/bca/default.rb +0 -0
  216. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bca/lib/puppet/functions/bca/data.rb +0 -0
  217. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/bca/manifests/init.pp +0 -0
  218. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/data/empty.json +0 -0
  219. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/hiera.yaml +0 -0
  220. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/manifests/init.pp +0 -0
  221. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_json/metadata.json +0 -0
  222. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/data/empty_key.json +0 -0
  223. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/hiera.yaml +0 -0
  224. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/manifests/init.pp +0 -0
  225. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_json/metadata.json +0 -0
  226. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/data/empty_key.yaml +0 -0
  227. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/hiera.yaml +0 -0
  228. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/manifests/init.pp +0 -0
  229. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_key_yaml/metadata.json +0 -0
  230. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/data/empty.yaml +0 -0
  231. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/hiera.yaml +0 -0
  232. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/manifests/init.pp +0 -0
  233. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/empty_yaml/metadata.json +0 -0
  234. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/data/first.json +0 -0
  235. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/hiera.yaml +0 -0
  236. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/manifests/init.pp +0 -0
  237. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/hieraprovider/metadata.json +0 -0
  238. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/meta/lib/puppet/functions/meta/data.rb +0 -0
  239. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/meta/manifests/init.pp +0 -0
  240. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/meta/metadata.json +0 -0
  241. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/lib/puppet/bindings/metawcp/default.rb +0 -0
  242. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/lib/puppet_x/thallgren/sample_module_data.rb +0 -0
  243. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/manifests/init.pp +0 -0
  244. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/metawcp/metadata.json +0 -0
  245. data/spec/fixtures/unit/functions/{lookup → lookup_fixture}/environments/production/modules/no_provider/manifests/init.pp +0 -0
  246. data/spec/integration/application/apply_spec.rb +88 -2
  247. data/spec/integration/application/lookup_spec.rb +155 -0
  248. data/spec/integration/data_binding_spec.rb +5 -5
  249. data/spec/integration/defaults_spec.rb +13 -0
  250. data/spec/integration/environments/default_manifest_spec.rb +16 -16
  251. data/spec/integration/environments/setting_hooks_spec.rb +1 -1
  252. data/spec/integration/test/test_helper_spec.rb +6 -2
  253. data/spec/integration/transaction_spec.rb +74 -0
  254. data/spec/integration/util/execution_spec.rb +8 -0
  255. data/spec/lib/puppet_spec/module_tool/shared_functions.rb +2 -2
  256. data/spec/lib/puppet_spec/module_tool/stub_source.rb +1 -1
  257. data/spec/lib/puppet_spec/unindent.rb +2 -2
  258. data/spec/unit/application/face_base_spec.rb +16 -0
  259. data/spec/unit/application/lookup_spec.rb +262 -227
  260. data/spec/unit/data_providers/{sample_data_provider_spec.rb → custom_data_provider_spec.rb} +14 -16
  261. data/spec/unit/data_providers/function_data_provider_spec.rb +2 -2
  262. data/spec/unit/data_providers/hiera_data_provider_spec.rb +60 -97
  263. data/spec/unit/defaults_spec.rb +1 -1
  264. data/spec/unit/face/ca_spec.rb +10 -0
  265. data/spec/unit/face/certificate_request_spec.rb +10 -0
  266. data/spec/unit/face/certificate_revocation_list_spec.rb +10 -0
  267. data/spec/unit/face/file_spec.rb +4 -0
  268. data/spec/unit/face/help_spec.rb +17 -0
  269. data/spec/unit/face/key_spec.rb +10 -0
  270. data/spec/unit/face/status_spec.rb +10 -0
  271. data/spec/unit/file_system_spec.rb +143 -6
  272. data/spec/unit/functions/binary_file_spec.rb +1 -1
  273. data/spec/unit/functions/hiera_spec.rb +257 -47
  274. data/spec/unit/functions/lookup_fixture_spec.rb +693 -0
  275. data/spec/unit/functions/lookup_spec.rb +1319 -608
  276. data/spec/unit/functions/new_spec.rb +3 -3
  277. data/spec/unit/graph/rb_tree_map_spec.rb +1 -1
  278. data/spec/unit/graph/simple_graph_spec.rb +1 -1
  279. data/spec/unit/hiera/scope_spec.rb +4 -4
  280. data/spec/unit/indirector/request_spec.rb +9 -0
  281. data/spec/unit/interface_spec.rb +27 -0
  282. data/spec/unit/man_spec.rb +1 -1
  283. data/spec/unit/module_spec.rb +1 -1
  284. data/spec/unit/module_tool/applications/builder_spec.rb +16 -1
  285. data/spec/unit/module_tool/applications/installer_spec.rb +1 -1
  286. data/spec/unit/module_tool/applications/upgrader_spec.rb +1 -1
  287. data/spec/unit/module_tool/installed_modules_spec.rb +6 -6
  288. data/spec/unit/module_tool_spec.rb +3 -3
  289. data/spec/unit/network/http/connection_spec.rb +10 -0
  290. data/spec/unit/network/http/webrick_spec.rb +1 -1
  291. data/spec/unit/pops/evaluator/access_ops_spec.rb +2 -2
  292. data/spec/unit/pops/evaluator/runtime3_converter_spec.rb +9 -9
  293. data/spec/unit/pops/loaders/environment_loader_spec.rb +172 -0
  294. data/spec/unit/pops/lookup/context_spec.rb +45 -16
  295. data/spec/unit/pops/lookup/interpolation_spec.rb +28 -20
  296. data/spec/unit/pops/lookup/lookup_spec.rb +197 -0
  297. data/spec/unit/pops/merge_strategy_spec.rb +18 -0
  298. data/spec/unit/pops/parser/lexer2_spec.rb +16 -1
  299. data/spec/unit/pops/parser/parse_site_spec.rb +4 -0
  300. data/spec/unit/pops/serialization/packer_spec.rb +4 -23
  301. data/spec/unit/pops/serialization/serialization_spec.rb +32 -8
  302. data/spec/unit/pops/types/p_object_type_spec.rb +68 -3
  303. data/spec/unit/pops/types/p_sem_ver_type_spec.rb +4 -4
  304. data/spec/unit/pops/types/p_type_set_type_spec.rb +31 -2
  305. data/spec/unit/pops/types/type_acceptor_spec.rb +18 -17
  306. data/spec/unit/pops/types/type_calculator_spec.rb +39 -40
  307. data/spec/unit/pops/types/type_factory_spec.rb +3 -3
  308. data/spec/unit/pops/types/type_formatter_spec.rb +7 -3
  309. data/spec/unit/pops/types/type_mismatch_describer_spec.rb +13 -2
  310. data/spec/unit/pops/types/types_spec.rb +25 -2
  311. data/spec/unit/pops/validator/validator_spec.rb +60 -4
  312. data/spec/unit/provider/nameservice_spec.rb +42 -0
  313. data/spec/unit/provider/package/aptrpm_spec.rb +1 -1
  314. data/spec/unit/provider/package/pkg_spec.rb +22 -0
  315. data/spec/unit/provider/package/pkgng_spec.rb +12 -0
  316. data/spec/unit/provider/package/rpm_spec.rb +8 -8
  317. data/spec/unit/provider/service/smf_spec.rb +13 -11
  318. data/spec/unit/provider/service/systemd_spec.rb +8 -1
  319. data/spec/unit/provider/user/useradd_spec.rb +1 -0
  320. data/spec/unit/puppet_spec.rb +14 -0
  321. data/spec/unit/resource/catalog_spec.rb +15 -9
  322. data/spec/unit/resource_spec.rb +20 -17
  323. data/spec/unit/semver_spec.rb +14 -0
  324. data/spec/unit/ssl/certificate_authority_spec.rb +12 -1
  325. data/spec/unit/transaction/additional_resource_generator_spec.rb +11 -0
  326. data/spec/unit/type/user_spec.rb +32 -6
  327. data/spec/unit/util/filetype_spec.rb +3 -3
  328. data/spec/unit/util/yaml_spec.rb +1 -1
  329. data/spec/unit/util_spec.rb +10 -2
  330. data/tasks/i18n.rake +20 -0
  331. metadata +2661 -2607
  332. data/lib/puppet/data_providers/lookup_adapter.rb +0 -254
  333. data/lib/puppet/vendor/load_semantic.rb +0 -1
  334. data/lib/puppet/vendor/semantic/Gemfile +0 -20
  335. data/lib/puppet/vendor/semantic/PUPPET_README.md +0 -6
  336. data/lib/puppet/vendor/semantic/Rakefile +0 -69
  337. data/lib/puppet/vendor/semantic/lib/semantic.rb +0 -7
  338. data/lib/puppet/vendor/semantic/lib/semantic/dependency/module_release.rb +0 -60
  339. data/lib/puppet/vendor/semantic/spec/spec_helper.rb +0 -24
  340. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb +0 -141
  341. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_spec.rb +0 -162
  342. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb +0 -143
  343. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/source_spec.rb +0 -5
  344. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/unsatisfiable_graph_spec.rb +0 -44
  345. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb +0 -383
  346. data/lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb +0 -307
  347. data/lib/puppet/vendor/semantic/spec/unit/semantic/version_spec.rb +0 -608
  348. data/spec/fixtures/unit/data_providers/environments/sample/manifests/site.pp +0 -6
@@ -0,0 +1,99 @@
1
+ require_relative 'sub_lookup'
2
+
3
+ module Puppet::Pops
4
+ module Lookup
5
+ # @api private
6
+ class LookupKey
7
+ include SubLookup
8
+
9
+ attr_reader :module_name, :root_key, :segments
10
+
11
+ def initialize(key)
12
+ segments = split_key(key) { |problem| Puppet::DataBinding::LookupError.new("#{problem} in key: '#{key}'") }
13
+ root_key = segments.shift.freeze
14
+ qual_index = root_key.index(DOUBLE_COLON)
15
+
16
+ @key = key
17
+ @module_name = qual_index.nil? ? nil : root_key[0..qual_index-1].freeze
18
+ @root_key = root_key
19
+ @segments = segments.empty? ? nil : segments.map { |segment| segment =~ /^[0-9]+$/ ? segment.to_i : segment }.freeze
20
+ end
21
+
22
+ def dig(lookup_invocation, value)
23
+ @segments.nil? ? value : sub_lookup(@key, lookup_invocation, @segments, value)
24
+ end
25
+
26
+ # Prunes a found root value with respect to subkeys in this key. The given _value_ is returned untouched
27
+ # if this key has no subkeys. Otherwise an attempt is made to create a Hash or Array that contains only the
28
+ # path to the appointed value and that value.
29
+ #
30
+ # If subkeys exists and no value is found, then this method will return `nil`, an empty `Array` or an empty `Hash`
31
+ # to enable further merges to be applied. The returned type depends on the given _value_.
32
+ #
33
+ # @param value [Object] the value to prune
34
+ # @return the possibly pruned value
35
+ def prune(value)
36
+ if @segments.nil?
37
+ value
38
+ else
39
+ pruned = @segments.reduce(value) do |memo, segment|
40
+ memo.is_a?(Hash) || memo.is_a?(Array) && segment.is_a?(Integer) ? memo[segment] : nil
41
+ end
42
+ if pruned.nil?
43
+ case value
44
+ when Hash
45
+ EMPTY_HASH
46
+ when Array
47
+ EMPTY_ARRAY
48
+ else
49
+ nil
50
+ end
51
+ else
52
+ undig(pruned)
53
+ end
54
+ end
55
+ end
56
+
57
+ # Create a structure that can be dug into using the subkeys of this key in order to find the
58
+ # given _value_. If this key has no subkeys, the _value_ is returned.
59
+ #
60
+ # @param value [Object] the value to wrap in a structure in case this value has subkeys
61
+ # @return [Object] the possibly wrapped value
62
+ def undig(value)
63
+ @segments.nil? ? value : segments.reverse.reduce(value) do |memo, segment|
64
+ if segment.is_a?(Integer)
65
+ x = []
66
+ x[segment] = memo
67
+ else
68
+ x = { segment => memo }
69
+ end
70
+ x
71
+ end
72
+ end
73
+
74
+ def to_a
75
+ unless instance_variable_defined?(:@all_segments)
76
+ a = [@root_key]
77
+ a += @segments unless @segments.nil?
78
+ @all_segments = a.freeze
79
+ end
80
+ @all_segments
81
+ end
82
+
83
+ def eql?(v)
84
+ v.is_a?(LookupKey) && @key == v.to_s
85
+ end
86
+ alias == eql?
87
+
88
+ def hash
89
+ @key.hash
90
+ end
91
+
92
+ def to_s
93
+ @key
94
+ end
95
+
96
+ LOOKUP_OPTIONS = LookupKey.new('lookup_options')
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,119 @@
1
+ require_relative 'function_provider'
2
+
3
+ module Puppet::Pops
4
+ module Lookup
5
+ # @api private
6
+ class LookupKeyFunctionProvider < FunctionProvider
7
+ TAG = 'lookup_key'.freeze
8
+
9
+ # Performs a lookup with the assumption that a recursive check has been made.
10
+ #
11
+ # @param key [LookupKey] The key to lookup
12
+ # @param lookup_invocation [Invocation] The current lookup invocation
13
+ # @param merge [MergeStrategy,String,Hash{String => Object},nil] Merge strategy, merge strategy name, strategy and options hash, or nil (implies "first found")
14
+ # @return [Object] the found object
15
+ # @throw :no_such_key when the object is not found
16
+ def unchecked_key_lookup(key, lookup_invocation, merge)
17
+ lookup_invocation.with(:data_provider, self) do
18
+ MergeStrategy.strategy(merge).lookup(locations, lookup_invocation) do |location|
19
+ if location.nil?
20
+ value = lookup_key(key.root_key, lookup_invocation, nil, merge)
21
+ lookup_invocation.report_found(key.root_key, validate_data_value(self, value))
22
+ else
23
+ lookup_invocation.with(:location, location) do
24
+ value = lookup_key(key.root_key, lookup_invocation, location.location, merge)
25
+ lookup_invocation.report_found(key.root_key, validate_data_value(self, value))
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def label
33
+ 'Lookup Key'
34
+ end
35
+
36
+ private
37
+
38
+ def lookup_key(key, lookup_invocation, location, merge)
39
+ unless location.nil? || location.exist?
40
+ lookup_invocation.report_location_not_found
41
+ throw :no_such_key
42
+ end
43
+ ctx = function_context(lookup_invocation, location)
44
+ ctx.data_hash ||= {}
45
+ catch(:no_such_key) do
46
+ hash = ctx.data_hash
47
+ hash[key] = ctx.function.call(lookup_invocation.scope, key, options(location), Context.new(ctx, lookup_invocation)) unless hash.include?(key)
48
+ return hash[key]
49
+ end
50
+ lookup_invocation.report_not_found(key)
51
+ throw :no_such_key
52
+ end
53
+ end
54
+
55
+ class V3BackendFunctionProvider < LookupKeyFunctionProvider
56
+ TAG = 'hiera3_backend'.freeze
57
+
58
+ def lookup_key(key, lookup_invocation, location, merge)
59
+ @backend ||= instantiate_backend(lookup_invocation)
60
+ @backend.lookup(key, lookup_invocation.scope, lookup_invocation.hiera_v3_location_overrides, convert_merge(merge), context = {:recurse_guard => nil})
61
+ end
62
+
63
+ private
64
+
65
+ def instantiate_backend(lookup_invocation)
66
+ backend_name = options[HieraConfig::KEY_BACKEND]
67
+ begin
68
+ require 'hiera/backend'
69
+ require "hiera/backend/#{backend_name.downcase}_backend"
70
+ backend = Hiera::Backend.const_get("#{backend_name.capitalize}_backend").new
71
+ return backend.method(:lookup).arity == 4 ? Hiera::Backend::Backend1xWrapper.new(backend) : backend
72
+ rescue LoadError => e
73
+ lookup_invocation.report_text { "Unable to load backend '#{backend_name}': #{e.message}" }
74
+ throw :no_such_key
75
+ rescue NameError => e
76
+ lookup_invocation.report_text { "Unable to instantiate backend '#{backend_name}': #{e.message}" }
77
+ throw :no_such_key
78
+ end
79
+ end
80
+
81
+ # Converts a lookup 'merge' parameter argument into a Hiera 'resolution_type' argument.
82
+ #
83
+ # @param merge [String,Hash,nil] The lookup 'merge' argument
84
+ # @return [Symbol,Hash,nil] The Hiera 'resolution_type'
85
+ def convert_merge(merge)
86
+ case merge
87
+ when nil
88
+ when 'first', 'default'
89
+ # Nil is OK. Defaults to Hiera :priority
90
+ nil
91
+ when Puppet::Pops::MergeStrategy
92
+ convert_merge(merge.configuration)
93
+ when 'unique'
94
+ # Equivalent to Hiera :array
95
+ :array
96
+ when 'hash'
97
+ # Equivalent to Hiera :hash with default :native merge behavior. A Hash must be passed here
98
+ # to override possible Hiera deep merge config settings.
99
+ { :behavior => :native }
100
+ when 'deep'
101
+ # Equivalent to Hiera :hash with :deeper merge behavior.
102
+ { :behavior => :deeper }
103
+ when Hash
104
+ strategy = merge['strategy']
105
+ if strategy == 'deep'
106
+ result = { :behavior => :deeper }
107
+ # Remaining entries must have symbolic keys
108
+ merge.each_pair { |k,v| result[k.to_sym] = v unless k == 'strategy' }
109
+ result
110
+ else
111
+ convert_merge(strategy)
112
+ end
113
+ else
114
+ raise Puppet::DataBinding::LookupError, "Unrecognized value for request 'merge' parameter: '#{merge}'"
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'configured_data_provider'
2
+
3
+ module Puppet::Pops
4
+ module Lookup
5
+ # @api private
6
+ class ModuleDataProvider < ConfiguredDataProvider
7
+
8
+ attr_reader :module_name
9
+
10
+ def initialize(module_name, config = nil)
11
+ super(config)
12
+ @module_name = module_name
13
+ end
14
+
15
+ def place
16
+ 'Module'
17
+ end
18
+
19
+ # Asserts that all keys in the given _data_hash_ are prefixed with the configured _module_name_. Removes entries
20
+ # that does not follow the convention and logs a warning.
21
+ #
22
+ # @param data_hash [Hash] The data hash
23
+ # @return [Hash] The possibly pruned hash
24
+ def validate_data_hash(data_provider, data_hash)
25
+ super
26
+ module_prefix = "#{module_name}::"
27
+ data_hash.each_key.reduce(data_hash) do |memo, k|
28
+ next memo if k == LOOKUP_OPTIONS || k.start_with?(module_prefix)
29
+ msg = 'must use keys qualified with the name of the module'
30
+ memo = memo.clone if memo.equal?(data_hash)
31
+ memo.delete(k)
32
+ Puppet.warning("Module '#{module_name}': #{data_provider.name} #{msg}")
33
+ memo
34
+ end
35
+ end
36
+
37
+ protected
38
+
39
+ def assert_config_version(config)
40
+ raise Puppet::DataBinding::LookupError, "#{config.name} cannot be used in a module" unless config.version > 3
41
+ config
42
+ end
43
+
44
+ # Return the root of the module with the name equal to the configured module name
45
+ #
46
+ # @param lookup_invocation [Invocation] The current lookup invocation
47
+ # @return [Pathname] Path to root of the module
48
+ # @raise [Puppet::DataBinding::LookupError] if the module can not be found
49
+ #
50
+ def provider_root(lookup_invocation)
51
+ env = lookup_invocation.scope.environment
52
+ mod = env.module(module_name)
53
+ raise Puppet::DataBinding::LookupError, "Environment '#{env.name}', cannot find module '#{module_name}'" unless mod
54
+ Pathname.new(mod.path)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,6 +1,8 @@
1
1
  module Puppet::Pops
2
2
  module Lookup
3
3
  module SubLookup
4
+ SPECIAL = /['"\.]/
5
+
4
6
  # Split key into segments. A segment may be a quoted string (both single and double quotes can
5
7
  # be used) and the segment separator is the '.' character. Whitespace will be trimmed off on
6
8
  # both sides of each segment. Whitespace within quotes are not trimmed.
@@ -15,10 +17,11 @@ module SubLookup
15
17
  #
16
18
  # @api public
17
19
  def split_key(key)
20
+ return [key] if key.match(SPECIAL).nil?
18
21
  segments = key.split(/(\s*"[^"]+"\s*|\s*'[^']+'\s*|[^'".]+)/)
19
22
  if segments.empty?
20
23
  # Only happens if the original key was an empty string
21
- ''
24
+ raise yield('Syntax error')
22
25
  elsif segments.shift == ''
23
26
  count = segments.size
24
27
  raise yield('Syntax error') unless count > 0
@@ -40,13 +43,14 @@ module SubLookup
40
43
  # implements the '#[]' method.
41
44
  #
42
45
  # @param key [String] the original key (only used for error messages)
43
- # @param lookup_invocation [Invocation] The current lookup invocation
46
+ # @param context [Context] The current lookup context
44
47
  # @param segments [Array<String>] the segments to use for lookup
45
48
  # @param value [Object] the value to access using the segments
46
49
  # @return [Object] the value obtained when accessing the value
47
50
  #
48
51
  # @api public
49
- def sub_lookup(key, lookup_invocation, segments, value)
52
+ def sub_lookup(key, context, segments, value)
53
+ lookup_invocation = context.is_a?(Invocation) ? context : context.invocation
50
54
  lookup_invocation.with(:sub_lookup, segments) do
51
55
  segments.each do |segment|
52
56
  lookup_invocation.with(:segment, segment) do
@@ -54,7 +58,7 @@ module SubLookup
54
58
  lookup_invocation.report_not_found(segment)
55
59
  throw :no_such_key
56
60
  end
57
- if segment =~ /^[0-9]+$/
61
+ if segment.is_a?(Integer) || segment =~ /^[0-9]+$/
58
62
  segment = segment.to_i
59
63
  unless value.instance_of?(Array)
60
64
  raise Puppet::DataBinding::LookupError,
@@ -6,12 +6,6 @@ module Puppet::Pops
6
6
  class MergeStrategy
7
7
  NOT_FOUND = Object.new.freeze
8
8
 
9
- # The type used for validation of the _merge_ argument
10
- def self.merge_t
11
- @@merge_t ||= Types::TypeParser.singleton.parse("Variant[String[1],Runtime[ruby,'Symbol'],Hash[Variant[String[1],Runtime[ruby,'Symbol']],Scalar,1]]")
12
- end
13
- private_class_method :merge_t
14
-
15
9
  def self.strategies
16
10
  @@strategies ||= {}
17
11
  end
@@ -24,22 +18,23 @@ module Puppet::Pops
24
18
  # @return [MergeStrategy] The matching merge strategy
25
19
  #
26
20
  def self.strategy(merge)
21
+ return DefaultMergeStrategy::INSTANCE unless merge
27
22
  return merge if merge.is_a?(MergeStrategy)
28
- merge = :first if merge.nil?
29
- Types::TypeAsserter.assert_instance_of("MergeStrategy 'merge' parameter", merge_t, merge)
23
+
30
24
  if merge.is_a?(Hash)
31
25
  merge_strategy = merge['strategy']
32
26
  if merge_strategy.nil?
33
27
  raise ArgumentError, "The hash given as 'merge' must contain the name of a strategy in string form for the key 'strategy'"
34
28
  end
35
- merge_options = merge
29
+ merge_options = merge.size == 1 ? EMPTY_HASH : merge
36
30
  else
37
31
  merge_strategy = merge
38
- merge_options = {}
32
+ merge_options = EMPTY_HASH
39
33
  end
40
- strategy = strategies[merge_strategy.to_sym]
41
- raise ArgumentError, "Unknown merge strategy: '#{merge_strategy}'" if strategy.nil?
42
- strategy.new(merge_options)
34
+ merge_strategy = merge_strategy.to_sym if merge_strategy.is_a?(String)
35
+ strategy_class = strategies[merge_strategy]
36
+ raise ArgumentError, "Unknown merge strategy: '#{merge_strategy}'" if strategy_class.nil?
37
+ merge_options == EMPTY_HASH ? strategy_class::INSTANCE : strategy_class.new(merge_options)
43
38
  end
44
39
 
45
40
  # Returns the list of merge strategy keys known to this class
@@ -47,7 +42,7 @@ module Puppet::Pops
47
42
  # @return [Array<Symbol>] List of strategy keys
48
43
  #
49
44
  def self.strategy_keys
50
- strategies.keys
45
+ strategies.keys - [:default, :unconstrained_deep, :reverse_deep]
51
46
  end
52
47
 
53
48
  # Adds a new merge strategy to the map of strategies known to this class
@@ -79,7 +74,7 @@ module Puppet::Pops
79
74
  # Create a new instance of this strategy configured with the given _options_
80
75
  # @param merge_options [Hash<String,Object>] Merge options
81
76
  def initialize(options)
82
- assert_type('The merge options', options_t, options)
77
+ assert_type('The merge options', self.class.options_t, options) unless options.empty?
83
78
  @options = options
84
79
  end
85
80
 
@@ -96,6 +91,12 @@ module Puppet::Pops
96
91
  assert_type('The second element of the merge', value_t, e2))
97
92
  end
98
93
 
94
+ # TODO: API 5.0 Remove this method
95
+ # @deprecated
96
+ def merge_lookup(lookup_variants)
97
+ lookup(lookup_variants, Lookup::Invocation.current)
98
+ end
99
+
99
100
  # Merges the result of yielding the given _lookup_variants_ to a given block.
100
101
  #
101
102
  # @param lookup_variants [Array] The variants to pass as second argument to the given block
@@ -105,22 +106,40 @@ module Puppet::Pops
105
106
  # @yieldreturn [Object] the value to merge with other values
106
107
  # @throws :no_such_key if the lookup was unsuccessful
107
108
  #
108
- def merge_lookup(lookup_variants)
109
- result = lookup_variants.reduce(NOT_FOUND) do |memo, lookup_variant|
110
- not_found = true
111
- value = catch(:no_such_key) do
112
- v = yield(lookup_variant)
113
- not_found = false
114
- v
115
- end
116
- if not_found
117
- memo
118
- else
119
- memo.equal?(NOT_FOUND) ? convert_value(value) : merge(memo, value)
109
+ # Merges the result of yielding the given _lookup_variants_ to a given block.
110
+ #
111
+ # @param lookup_variants [Array] The variants to pass as second argument to the given block
112
+ # @return [Object] the merged value.
113
+ # @yield [} ]
114
+ # @yieldparam variant [Object] each variant given in the _lookup_variants_ array.
115
+ # @yieldreturn [Object] the value to merge with other values
116
+ # @throws :no_such_key if the lookup was unsuccessful
117
+ #
118
+ def lookup(lookup_variants, lookup_invocation)
119
+ case lookup_variants.size
120
+ when 0
121
+ throw :no_such_key
122
+ when 1
123
+ yield(lookup_variants[0])
124
+ else
125
+ lookup_invocation.with(:merge, self) do
126
+ result = lookup_variants.reduce(NOT_FOUND) do |memo, lookup_variant|
127
+ not_found = true
128
+ value = catch(:no_such_key) do
129
+ v = yield(lookup_variant)
130
+ not_found = false
131
+ v
132
+ end
133
+ if not_found
134
+ memo
135
+ else
136
+ memo.equal?(NOT_FOUND) ? convert_value(value) : merge(memo, value)
137
+ end
138
+ end
139
+ throw :no_such_key if result == NOT_FOUND
140
+ lookup_invocation.report_result(result)
120
141
  end
121
142
  end
122
- throw :no_such_key if result == NOT_FOUND
123
- result
124
143
  end
125
144
 
126
145
  # Converts a single value to the type expected when merging two elements
@@ -148,8 +167,8 @@ module Puppet::Pops
148
167
  #
149
168
  # @return [Types::PStructType] the puppet type
150
169
  #
151
- def options_t
152
- @options_t ||=Types::TypeParser.singleton.parse("Struct[{strategy=>Optional[Pattern[#{self.class.key}]]}]")
170
+ def self.options_t
171
+ @options_t ||=Types::TypeParser.singleton.parse("Struct[{strategy=>Optional[Pattern[/#{key}/]]}]")
153
172
  end
154
173
 
155
174
  # Returns the type used to validate the options hash
@@ -172,6 +191,8 @@ module Puppet::Pops
172
191
  # Simple strategy that returns the first value found. It never merges any values.
173
192
  #
174
193
  class FirstFoundStrategy < MergeStrategy
194
+ INSTANCE = self.new(EMPTY_HASH)
195
+
175
196
  def self.key
176
197
  :first
177
198
  end
@@ -182,10 +203,10 @@ module Puppet::Pops
182
203
  # @return [Object] the merged value
183
204
  # @throws :no_such_key unless the lookup was successful
184
205
  #
185
- def merge_lookup(lookup_variants)
186
- lookup_variants.each do |lookup_variant|
187
- catch(:no_such_key) { return yield(lookup_variant) }
188
- end
206
+ def lookup(lookup_variants, _)
207
+ # First found does not continue when a root key was found and a subkey wasn't since that would
208
+ # simulate a hash merge
209
+ lookup_variants.each { |lookup_variant| catch(:no_such_key) { return yield(lookup_variant) } }
189
210
  throw :no_such_key
190
211
  end
191
212
 
@@ -198,10 +219,23 @@ module Puppet::Pops
198
219
  MergeStrategy.add_strategy(self)
199
220
  end
200
221
 
222
+ # Same as {FirstFoundStrategy} but used when no strategy has been explicitly given
223
+ class DefaultMergeStrategy < FirstFoundStrategy
224
+ INSTANCE = self.new(EMPTY_HASH)
225
+
226
+ def self.key
227
+ :default
228
+ end
229
+
230
+ MergeStrategy.add_strategy(self)
231
+ end
232
+
201
233
  # Produces a new hash by merging hash e1 with hash e2 in such a way that the values of duplicate keys
202
234
  # will be those of e1
203
235
  #
204
236
  class HashMergeStrategy < MergeStrategy
237
+ INSTANCE = self.new(EMPTY_HASH)
238
+
205
239
  def self.key
206
240
  :hash
207
241
  end
@@ -230,6 +264,8 @@ module Puppet::Pops
230
264
  # first contributor of elements and e2 the second.
231
265
  #
232
266
  class UniqueMergeStrategy < MergeStrategy
267
+ INSTANCE = self.new(EMPTY_HASH)
268
+
233
269
  def self.key
234
270
  :unique
235
271
  end
@@ -302,6 +338,8 @@ module Puppet::Pops
302
338
  # Results: {:x => [{:y => 1, :z => 2}]}
303
339
  #
304
340
  class DeepMergeStrategy < MergeStrategy
341
+ INSTANCE = self.new(EMPTY_HASH)
342
+
305
343
  def self.key
306
344
  :deep
307
345
  end
@@ -309,8 +347,20 @@ module Puppet::Pops
309
347
  def checked_merge(e1, e2)
310
348
  dm_options = { :preserve_unmergeables => false }
311
349
  options.each_pair { |k,v| dm_options[k.to_sym] = v unless k == 'strategy' }
312
- # e2 (the destination) is dup'ed to avoid that the passed in object mutates
313
- DeepMerge.deep_merge!(e1, e2.dup, dm_options)
350
+ # e2 (the destination) is deep cloned to avoid that the passed in object mutates
351
+ DeepMerge.deep_merge!(e1, deep_clone(e2), dm_options)
352
+ end
353
+
354
+ def deep_clone(value)
355
+ if value.is_a?(Hash)
356
+ result = value.clone
357
+ value.each{ |k, v| result[k] = deep_clone(v) }
358
+ result
359
+ elsif value.is_a?(Array)
360
+ value.map{ |v| deep_clone(v) }
361
+ else
362
+ value
363
+ end
314
364
  end
315
365
 
316
366
  protected
@@ -319,9 +369,9 @@ module Puppet::Pops
319
369
  # the setting of that option to false
320
370
  #
321
371
  # @return [Types::PAnyType] the puppet type used when validating the options hash
322
- def options_t
372
+ def self.options_t
323
373
  @options_t ||= Types::TypeParser.singleton.parse('Struct[{'\
324
- "strategy=>Optional[Pattern[#{self.class.key}]],"\
374
+ "strategy=>Optional[Pattern[#{key}]],"\
325
375
  'knockout_prefix=>Optional[String],'\
326
376
  'merge_debug=>Optional[Boolean],'\
327
377
  'merge_hash_arrays=>Optional[Boolean],'\
@@ -335,4 +385,35 @@ module Puppet::Pops
335
385
 
336
386
  MergeStrategy.add_strategy(self)
337
387
  end
388
+
389
+ # Same as {DeepMergeStrategy} but without constraint on valid merge options
390
+ # (needed for backward compatibility with Hiera v3)
391
+ class UnconstrainedDeepMergeStrategy < DeepMergeStrategy
392
+ def self.key
393
+ :unconstrained_deep
394
+ end
395
+
396
+ # @return [Types::PAnyType] the puppet type used when validating the options hash
397
+ def self.options_t
398
+ @options_t ||= Types::TypeParser.singleton.parse('Hash[String[1],Any]')
399
+ end
400
+
401
+ MergeStrategy.add_strategy(self)
402
+ end
403
+
404
+ # Same as {UnconstrainedDeepMergeStrategy} but with reverse priority of merged elements.
405
+ # (needed for backward compatibility with Hiera v3)
406
+ class ReverseDeepMergeStrategy < UnconstrainedDeepMergeStrategy
407
+ INSTANCE = self.new(EMPTY_HASH)
408
+
409
+ def self.key
410
+ :reverse_deep
411
+ end
412
+
413
+ def checked_merge(e1, e2)
414
+ super(e2, e1)
415
+ end
416
+
417
+ MergeStrategy.add_strategy(self)
418
+ end
338
419
  end