puppet 4.8.2 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

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 -2593
  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,82 @@
1
+ require_relative 'data_adapter'
2
+ require_relative 'context'
3
+ require_relative 'data_provider'
4
+
5
+ module Puppet::Pops
6
+ module Lookup
7
+ # @api private
8
+ class FunctionProvider
9
+ include DataProvider
10
+
11
+ attr_reader :parent_data_provider, :function_name, :locations
12
+
13
+ def initialize(name, parent_data_provider, function_name, options, locations)
14
+ @name = name
15
+ @parent_data_provider = parent_data_provider
16
+ @function_name = function_name
17
+ @options = options
18
+ @locations = locations || [nil]
19
+ @contexts = {}
20
+ end
21
+
22
+ # @return [FunctionContext] the function context associated with this provider
23
+ def function_context(lookup_invocation, location)
24
+ scope = lookup_invocation.scope
25
+ compiler = scope.compiler
26
+ @contexts[location] ||= FunctionContext.new(compiler.environment.name, module_name, function(scope))
27
+ end
28
+
29
+ def module_name
30
+ @parent_data_provider.module_name
31
+ end
32
+
33
+ def name
34
+ "Hierarchy entry \"#{@name}\""
35
+ end
36
+
37
+ def to_s
38
+ name
39
+ end
40
+
41
+ # Obtains the options to send to the function, optionally merged with a 'path' or 'uri' option
42
+ #
43
+ # @param [Pathname,URI] location The location to add to the options
44
+ # @return [Hash{String => Object}] The options hash
45
+ def options(location = nil)
46
+ case location
47
+ when nil
48
+ @options
49
+ when Pathname
50
+ @options.merge(HieraConfig::KEY_PATH => location.to_s)
51
+ when URI
52
+ @options.merge(HieraConfig::KEY_URI => location.to_s)
53
+ else
54
+ @options
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def function(scope)
61
+ @function ||= load_function(scope)
62
+ end
63
+
64
+ def load_function(scope)
65
+ loaders = scope.compiler.loaders
66
+ typed_name = Loader::TypedName.new(:function, @function_name)
67
+ loader = if typed_name.qualified?
68
+ qualifier = typed_name.name_parts[0]
69
+ qualifier == 'environment' ? loaders.private_environment_loader : loaders.private_loader_for_module(qualifier)
70
+ else
71
+ loaders.private_environment_loader
72
+ end
73
+ te = loader.load_typed(typed_name)
74
+ if te.nil? || te.value.nil?
75
+ raise Puppet::DataBinding::LookupError,
76
+ "#{@options[HieraConfig::KEY_NAME]}: Unable to find '#{self.class::TAG}' function named '#{function_name}'"
77
+ end
78
+ te.value
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ require 'hiera/scope'
2
+ require_relative 'configured_data_provider'
3
+
4
+ module Puppet::Pops
5
+ module Lookup
6
+ # @api private
7
+ class GlobalDataProvider < ConfiguredDataProvider
8
+ def place
9
+ 'Global'
10
+ end
11
+
12
+ def unchecked_key_lookup(key, lookup_invocation, merge)
13
+ config = config(lookup_invocation)
14
+ if(config.version == 3)
15
+ # Hiera version 3 needs access to special scope variables
16
+ scope = lookup_invocation.scope
17
+ unless scope.is_a?(Hiera::Scope)
18
+ lookup_invocation = Invocation.new(
19
+ Hiera::Scope.new(scope),
20
+ lookup_invocation.override_values,
21
+ lookup_invocation.default_values,
22
+ lookup_invocation.explainer)
23
+ end
24
+ merge = config.merge_strategy if merge.is_a?(DefaultMergeStrategy)
25
+ end
26
+ super(key, lookup_invocation, merge)
27
+ end
28
+
29
+ protected
30
+
31
+ def assert_config_version(config)
32
+ raise Puppet::DataBinding::LookupError, "#{config.name} cannot be used in the global layer" if config.version == 4
33
+ config
34
+ end
35
+
36
+ # Return the root of the environment
37
+ #
38
+ # @param lookup_invocation [Invocation] The current lookup invocation
39
+ # @return [Pathname] Path to the parent of the hiera configuration file
40
+ def provider_root(lookup_invocation)
41
+ configuration_path(lookup_invocation).parent
42
+ end
43
+
44
+ def configuration_path(lookup_invocation)
45
+ lookup_invocation.global_hiera_config_path
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,601 @@
1
+ require_relative 'data_dig_function_provider'
2
+ require_relative 'data_hash_function_provider'
3
+ require_relative 'lookup_key_function_provider'
4
+ require_relative 'location_resolver'
5
+
6
+ module Puppet::Pops
7
+ module Lookup
8
+
9
+ # @api private
10
+ class ScopeLookupCollectingInvocation < Invocation
11
+ attr_reader :scope_interpolations
12
+
13
+ def initialize(scope)
14
+ super(scope)
15
+ @scope_interpolations = {}
16
+ end
17
+
18
+ def remember_scope_lookup(key, value)
19
+ @scope_interpolations[key] = value
20
+ end
21
+ end
22
+
23
+ # @api private
24
+ class HieraConfig
25
+ include LocationResolver
26
+ include LabelProvider
27
+
28
+ CONFIG_FILE_NAME = 'hiera.yaml'
29
+
30
+ KEY_NAME = 'name'.freeze
31
+ KEY_VERSION = 'version'.freeze
32
+ KEY_DATADIR = 'datadir'.freeze
33
+ KEY_HIERARCHY = 'hierarchy'.freeze
34
+ KEY_LOGGER = 'logger'.freeze
35
+ KEY_OPTIONS = 'options'.freeze
36
+ KEY_PATH = 'path'.freeze
37
+ KEY_PATHS = 'paths'.freeze
38
+ KEY_GLOB = 'glob'.freeze
39
+ KEY_GLOBS = 'globs'.freeze
40
+ KEY_URI = 'uri'.freeze
41
+ KEY_URIS = 'uris'.freeze
42
+ KEY_DEFAULTS = 'defaults'.freeze
43
+ KEY_DATA_HASH = DataHashFunctionProvider::TAG
44
+ KEY_LOOKUP_KEY = LookupKeyFunctionProvider::TAG
45
+ KEY_DATA_DIG = DataDigFunctionProvider::TAG
46
+ KEY_V3_DATA_HASH = V3DataHashFunctionProvider::TAG
47
+ KEY_V3_BACKEND = V3BackendFunctionProvider::TAG
48
+ KEY_V4_DATA_HASH = V4DataHashFunctionProvider::TAG
49
+ KEY_BACKEND = 'backend'.freeze
50
+
51
+ FUNCTION_KEYS = [KEY_DATA_HASH, KEY_LOOKUP_KEY, KEY_DATA_DIG, KEY_V3_BACKEND]
52
+ ALL_FUNCTION_KEYS = FUNCTION_KEYS + [KEY_V4_DATA_HASH]
53
+ LOCATION_KEYS = [KEY_PATH, KEY_PATHS, KEY_GLOB, KEY_GLOBS, KEY_URI, KEY_URIS]
54
+ FUNCTION_PROVIDERS = {
55
+ KEY_DATA_HASH => DataHashFunctionProvider,
56
+ KEY_DATA_DIG => DataDigFunctionProvider,
57
+ KEY_LOOKUP_KEY => LookupKeyFunctionProvider,
58
+ KEY_V3_DATA_HASH => V3DataHashFunctionProvider,
59
+ KEY_V3_BACKEND => V3BackendFunctionProvider,
60
+ KEY_V4_DATA_HASH => V4DataHashFunctionProvider
61
+ }
62
+
63
+ def self.v4_function_config(config_root, function_name)
64
+ unless Puppet[:strict] == :off
65
+ Puppet.warn_once(:deprecation, 'legacy_provider_function',
66
+ "Using of legacy data provider function '#{function_name}'. Please convert to a 'data_hash' function")
67
+ end
68
+ HieraConfigV5.new(config_root, nil,
69
+ {
70
+ KEY_VERSION => 5,
71
+ KEY_HIERARCHY => [
72
+ {
73
+ KEY_NAME => "Legacy function '#{function_name}'",
74
+ KEY_V4_DATA_HASH => function_name
75
+ }
76
+ ]
77
+ }.freeze
78
+ )
79
+ end
80
+
81
+ def self.config_exist?(config_root)
82
+ config_path = config_root + CONFIG_FILE_NAME
83
+ config_path.exist?
84
+ end
85
+
86
+ def self.symkeys_to_string(struct)
87
+ case(struct)
88
+ when Hash
89
+ Hash[struct.map { |k,v| [k.to_s, symkeys_to_string(v)] }]
90
+ when Array
91
+ struct.map { |v| symkeys_to_string(v) }
92
+ else
93
+ struct
94
+ end
95
+ end
96
+
97
+ # Creates a new HieraConfig from the given _config_root_. This is where the 'hiera.yaml' is expected to be found
98
+ # and is also the base location used when resolving relative paths.
99
+ #
100
+ # @param config_path [Pathname] Absolute path to the configuration file
101
+ # @return [LookupConfiguration] the configuration
102
+ def self.create(config_path)
103
+ if config_path.is_a?(Hash)
104
+ config_path = nil
105
+ loaded_config = config_path
106
+ else
107
+ config_root = config_path.parent
108
+ if config_path.exist?
109
+ loaded_config = YAML.load_file(config_path)
110
+
111
+ # For backward compatibility, we must treat an empty file, or a yaml that doesn't
112
+ # produce a Hash as Hiera version 3 default.
113
+ unless loaded_config.is_a?(Hash)
114
+ Puppet.warning("#{config_path}: File exists but does not contain a valid YAML hash. Falling back to Hiera version 3 default config")
115
+ loaded_config = HieraConfigV3::DEFAULT_CONFIG_HASH
116
+ end
117
+ else
118
+ config_path = nil
119
+ loaded_config = HieraConfigV5::DEFAULT_CONFIG_HASH
120
+ end
121
+ end
122
+
123
+ version = loaded_config[KEY_VERSION] || loaded_config[:version]
124
+ version = version.nil? ? 3 : version.to_i
125
+ case version
126
+ when 5
127
+ HieraConfigV5.new(config_root, config_path, loaded_config)
128
+ when 4
129
+ HieraConfigV4.new(config_root, config_path, loaded_config)
130
+ when 3
131
+ HieraConfigV3.new(config_root, config_path, loaded_config)
132
+ else
133
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: This runtime does not support #{CONFIG_FILE_NAME} version '#{version}'"
134
+ end
135
+ end
136
+
137
+ attr_reader :config_path, :version
138
+
139
+ # Creates a new HieraConfig from the given _config_root_. This is where the 'lookup.yaml' is expected to be found
140
+ # and is also the base location used when resolving relative paths.
141
+ #
142
+ # @param config_path [Pathname] Absolute path to the configuration
143
+ # @param loaded_config [Hash] the loaded configuration
144
+ def initialize(config_root, config_path, loaded_config)
145
+ @config_root = config_root
146
+ @config_path = config_path
147
+ @loaded_config = loaded_config
148
+ @config = validate_config(self.class.symkeys_to_string(@loaded_config))
149
+ @data_providers = nil
150
+ end
151
+
152
+ # Returns the data providers for this config
153
+ #
154
+ # @param lookup_invocation [Invocation] Invocation data containing scope, overrides, and defaults
155
+ # @param parent_data_provider [DataProvider] The data provider that loaded this configuration
156
+ # @return [Array<DataProvider>] the data providers
157
+ def configured_data_providers(lookup_invocation, parent_data_provider)
158
+ scope = lookup_invocation.scope
159
+ unless @data_providers && scope_interpolations_stable?(scope)
160
+ if @data_providers
161
+ lookup_invocation.report_text { 'Hiera configuration recreated due to change of scope variables used in interpolation expressions' }
162
+ end
163
+ slc_invocation = ScopeLookupCollectingInvocation.new(scope)
164
+ @data_providers = create_configured_data_providers(slc_invocation, parent_data_provider)
165
+ @scope_interpolations = slc_invocation.scope_interpolations
166
+ end
167
+ @data_providers
168
+ end
169
+
170
+ def scope_interpolations_stable?(scope)
171
+ @scope_interpolations.all? { |key, value| scope[key].eql?(value) }
172
+ end
173
+
174
+ # @api private
175
+ def create_configured_data_providers(lookup_invocation, parent_data_provider)
176
+ self.class.not_implemented(self, 'create_configured_data_providers')
177
+ end
178
+
179
+ def validate_config(config)
180
+ self.class.not_implemented(self, 'validate_config')
181
+ end
182
+
183
+ def version
184
+ self.class.not_implemented(self, 'version')
185
+ end
186
+
187
+ def name
188
+ "hiera configuration version #{version}"
189
+ end
190
+
191
+ def create_hiera3_backend_provider(name, backend, parent_data_provider, datadir, paths, hiera3_config)
192
+ # Custom backend. Hiera v3 must be installed, it's logger configured, and it must be made aware of the loaded config
193
+ require 'hiera'
194
+ if Hiera::Config.instance_variable_defined?(:@config) && (current_config = Hiera::Config.instance_variable_get(:@config)).is_a?(Hash)
195
+ current_config.each_pair do |key, val|
196
+ case key
197
+ when :hierarchy, :backends
198
+ hiera3_config[key] = ([val] + [hiera3_config[key]]).flatten.uniq
199
+ else
200
+ hiera3_config[key] = val
201
+ end
202
+ end
203
+ else
204
+ if hiera3_config.include?(KEY_LOGGER)
205
+ Hiera.logger = hiera3_config[KEY_LOGGER].to_s
206
+ else
207
+ Hiera.logger = 'puppet'
208
+ end
209
+ end
210
+ Hiera::Config.instance_variable_set(:@config, hiera3_config)
211
+
212
+ # Use a special lookup_key that delegates to the backend
213
+ paths = nil if !paths.nil? && paths.empty?
214
+ create_data_provider(name, parent_data_provider, KEY_V3_BACKEND, 'hiera_v3_data', { KEY_DATADIR => datadir, KEY_BACKEND => backend }, paths)
215
+ end
216
+
217
+ private
218
+
219
+ def create_data_provider(name, parent_data_provider, function_kind, function_name, options, locations)
220
+ FUNCTION_PROVIDERS[function_kind].new(name, parent_data_provider, function_name, options, locations)
221
+ end
222
+
223
+ def self.not_implemented(impl, method_name)
224
+ raise NotImplementedError, "The class #{impl.class.name} should have implemented the method #{method_name}()"
225
+ end
226
+ end
227
+
228
+ # @api private
229
+ class HieraConfigV3 < HieraConfig
230
+ KEY_BACKENDS = 'backends'.freeze
231
+ KEY_MERGE_BEHAVIOR = 'merge_behavior'.freeze
232
+ KEY_DEEP_MERGE_OPTIONS = 'deep_merge_options'.freeze
233
+
234
+ def self.config_type
235
+ return @@CONFIG_TYPE if class_variable_defined?(:@@CONFIG_TYPE)
236
+ tf = Types::TypeFactory
237
+ nes_t = Types::PStringType::NON_EMPTY
238
+
239
+ # This is a hash, not a type. Contained backends are added prior to validation
240
+ @@CONFIG_TYPE = {
241
+ tf.optional(KEY_VERSION) => tf.range(3,3),
242
+ tf.optional(KEY_BACKENDS) => tf.variant(nes_t, tf.array_of(nes_t)),
243
+ tf.optional(KEY_LOGGER) => nes_t,
244
+ tf.optional(KEY_MERGE_BEHAVIOR) => tf.enum('deep', 'deeper', 'native'),
245
+ tf.optional(KEY_DEEP_MERGE_OPTIONS) => tf.hash_kv(nes_t, tf.variant(tf.string, tf.boolean)),
246
+ tf.optional(KEY_HIERARCHY) => tf.variant(nes_t, tf.array_of(nes_t))
247
+ }
248
+ end
249
+
250
+ def create_configured_data_providers(lookup_invocation, parent_data_provider)
251
+ scope = lookup_invocation.scope
252
+ unless scope.is_a?(Hiera::Scope)
253
+ lookup_invocation = Invocation.new(
254
+ Hiera::Scope.new(scope),
255
+ lookup_invocation.override_values,
256
+ lookup_invocation.default_values,
257
+ lookup_invocation.explainer)
258
+ end
259
+
260
+ default_datadir = File.join(Puppet.settings[:codedir], 'environments', '%{::environment}', 'hieradata')
261
+ data_providers = {}
262
+
263
+ [@config[KEY_BACKENDS]].flatten.each do |backend|
264
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: Backend '#{backend}' defined more than once" if data_providers.include?(backend)
265
+ original_paths = @config[KEY_HIERARCHY]
266
+ backend_config = @config[backend] || EMPTY_HASH
267
+ datadir = Pathname(interpolate(backend_config[KEY_DATADIR] || default_datadir, lookup_invocation, false))
268
+ ext = backend == 'hocon' ? '.conf' : ".#{backend}"
269
+ paths = resolve_paths(datadir, original_paths, lookup_invocation, @config_path.nil?, ext)
270
+ data_providers[backend] = case
271
+ when backend == 'json', backend == 'yaml'
272
+ create_data_provider(backend, parent_data_provider, KEY_V3_DATA_HASH, "#{backend}_data", { KEY_DATADIR => datadir }, paths)
273
+ when backend == 'hocon' && Puppet.features.hocon?
274
+ create_data_provider(backend, parent_data_provider, KEY_V3_DATA_HASH, 'hocon_data', { KEY_DATADIR => datadir }, paths)
275
+ else
276
+ create_hiera3_backend_provider(backend, backend, parent_data_provider, datadir, paths, @loaded_config)
277
+ end
278
+ end
279
+ data_providers.values
280
+ end
281
+
282
+ DEFAULT_CONFIG_HASH = {
283
+ KEY_BACKENDS => %w(yaml),
284
+ KEY_HIERARCHY => %w(nodes/%{::trusted.certname} common),
285
+ KEY_MERGE_BEHAVIOR => 'native'
286
+ }
287
+
288
+ def validate_config(config)
289
+ unless Puppet[:strict] == :off
290
+ Puppet.warn_once(:deprecation, 'hiera.yaml',
291
+ "#{@config_path}: Use of 'hiera.yaml' version 3 is deprecated. It should be converted to version 5", config_path.to_s)
292
+ end
293
+ config[KEY_VERSION] ||= 3
294
+ config[KEY_BACKENDS] ||= DEFAULT_CONFIG_HASH[KEY_BACKENDS]
295
+ config[KEY_HIERARCHY] ||= DEFAULT_CONFIG_HASH[KEY_HIERARCHY]
296
+ config[KEY_MERGE_BEHAVIOR] ||= DEFAULT_CONFIG_HASH[KEY_MERGE_BEHAVIOR]
297
+ config[KEY_DEEP_MERGE_OPTIONS] ||= {}
298
+
299
+ backends = [ config[KEY_BACKENDS] ].flatten
300
+
301
+ # Create the final struct used for validation (backends are included as keys to arbitrary configs in the form of a hash)
302
+ tf = Types::TypeFactory
303
+ backend_elements = {}
304
+ backends.each { |backend| backend_elements[tf.optional(backend)] = tf.hash_kv(Types::PStringType::NON_EMPTY, tf.any) }
305
+ v3_struct = tf.struct(self.class.config_type.merge(backend_elements))
306
+
307
+ Types::TypeAsserter.assert_instance_of(["The Lookup Configuration at '%s'", @config_path], v3_struct, config)
308
+ end
309
+
310
+ def merge_strategy
311
+ @merge_strategy ||= create_merge_strategy
312
+ end
313
+
314
+ def version
315
+ 3
316
+ end
317
+
318
+ private
319
+
320
+ def create_merge_strategy
321
+ key = @config[KEY_MERGE_BEHAVIOR]
322
+ case key
323
+ when nil
324
+ MergeStrategy.strategy(nil)
325
+ when 'native'
326
+ MergeStrategy.strategy(:first)
327
+ when 'array'
328
+ MergeStrategy.strategy(:unique)
329
+ when 'deep', 'deeper'
330
+ merge = { 'strategy' => key == 'deep' ? 'reverse_deep' : 'unconstrained_deep' }
331
+ dm_options = @config[KEY_DEEP_MERGE_OPTIONS]
332
+ merge.merge!(dm_options) if dm_options
333
+ MergeStrategy.strategy(merge)
334
+ end
335
+ end
336
+ end
337
+
338
+ # @api private
339
+ class HieraConfigV4 < HieraConfig
340
+ require 'puppet/plugins/data_providers'
341
+
342
+ include Puppet::Plugins::DataProviders
343
+
344
+ def self.config_type
345
+ return @@CONFIG_TYPE if class_variable_defined?(:@@CONFIG_TYPE)
346
+ tf = Types::TypeFactory
347
+ nes_t = Types::PStringType::NON_EMPTY
348
+
349
+ @@CONFIG_TYPE = tf.struct({
350
+ KEY_VERSION => tf.range(4, 4),
351
+ tf.optional(KEY_DATADIR) => nes_t,
352
+ tf.optional(KEY_HIERARCHY) => tf.array_of(tf.struct(
353
+ KEY_BACKEND => nes_t,
354
+ KEY_NAME => nes_t,
355
+ tf.optional(KEY_DATADIR) => nes_t,
356
+ tf.optional(KEY_PATH) => nes_t,
357
+ tf.optional(KEY_PATHS) => tf.array_of(nes_t)
358
+ ))
359
+ })
360
+ end
361
+
362
+ def factory_create_data_provider(lookup_invocation, name, parent_data_provider, provider_name, datadir, original_paths)
363
+ service_type = Registry.hash_of_path_based_data_provider_factories
364
+ provider_factory = Puppet.lookup(:injector).lookup(nil, service_type, PATH_BASED_DATA_PROVIDER_FACTORIES_KEY)[provider_name]
365
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: No data provider is registered for backend '#{provider_name}' " unless provider_factory
366
+
367
+ paths = original_paths.map { |path| interpolate(path, lookup_invocation, false) }
368
+ paths = provider_factory.resolve_paths(datadir, original_paths, paths, lookup_invocation)
369
+
370
+ provider_factory_version = provider_factory.respond_to?(:version) ? provider_factory.version : 1
371
+ if provider_factory_version == 1
372
+ # Version 1 is not aware of the parent provider
373
+ provider_factory.create(name, paths)
374
+ else
375
+ provider_factory.create(name, paths, parent_data_provider)
376
+ end
377
+ end
378
+
379
+ def create_configured_data_providers(lookup_invocation, parent_data_provider)
380
+ default_datadir = @config[KEY_DATADIR]
381
+ data_providers = {}
382
+
383
+ @config[KEY_HIERARCHY].each do |he|
384
+ name = he[KEY_NAME]
385
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: Name '#{name}' defined more than once" if data_providers.include?(name)
386
+ original_paths = he[KEY_PATHS] || [he[KEY_PATH] || name]
387
+ datadir = @config_root + (he[KEY_DATADIR] || default_datadir)
388
+ provider_name = he[KEY_BACKEND]
389
+ data_providers[name] = case
390
+ when provider_name == 'json', provider_name == 'yaml'
391
+ create_data_provider(name, parent_data_provider, KEY_DATA_HASH, "#{provider_name}_data", {},
392
+ resolve_paths(datadir, original_paths, lookup_invocation, @config_path.nil?, ".#{provider_name}"))
393
+ when provider_name == 'hocon' && Puppet.features.hocon?
394
+ create_data_provider(name, parent_data_provider, KEY_DATA_HASH, 'hocon_data', {},
395
+ resolve_paths(datadir, original_paths, lookup_invocation, @config_path.nil?, '.conf'))
396
+ else
397
+ factory_create_data_provider(lookup_invocation, name, parent_data_provider, provider_name, datadir, original_paths)
398
+ end
399
+ end
400
+ data_providers.values
401
+ end
402
+
403
+ def validate_config(config)
404
+ unless Puppet[:strict] == :off
405
+ Puppet.warn_once(:deprecation, 'hiera.yaml',
406
+ "#{@config_path}: Use of 'hiera.yaml' version 4 is deprecated. It should be converted to version 5", config_path.to_s)
407
+ end
408
+ config[KEY_DATADIR] ||= 'data'
409
+ config[KEY_HIERARCHY] ||= [{ KEY_NAME => 'common', KEY_BACKEND => 'yaml' }]
410
+ Types::TypeAsserter.assert_instance_of(["The Lookup Configuration at '%s'", @config_path], self.class.config_type, config)
411
+ end
412
+
413
+ def version
414
+ 4
415
+ end
416
+ end
417
+
418
+ # @api private
419
+ class HieraConfigV5 < HieraConfig
420
+ def self.config_type
421
+ return @@CONFIG_TYPE if class_variable_defined?(:@@CONFIG_TYPE_V5)
422
+ tf = Types::TypeFactory
423
+ nes_t = Types::PStringType::NON_EMPTY
424
+
425
+ # Need alias here to avoid ridiculously long regexp burp in case of validation errors.
426
+ uri_t = Pcore::TYPE_URI_ALIAS
427
+
428
+ # The option name must start with a letter and end with a letter or digit. May contain underscore and dash.
429
+ option_name_t = tf.pattern(/\A[A-Za-z](:?[0-9A-Za-z_-]*[0-9A-Za-z])?\z/)
430
+
431
+ @@CONFIG_TYPE = tf.struct({
432
+ KEY_VERSION => tf.range(5, 5),
433
+ tf.optional(KEY_DEFAULTS) => tf.struct(
434
+ {
435
+ tf.optional(KEY_DATA_HASH) => nes_t,
436
+ tf.optional(KEY_LOOKUP_KEY) => nes_t,
437
+ tf.optional(KEY_DATA_DIG) => nes_t,
438
+ tf.optional(KEY_DATADIR) => nes_t
439
+ }),
440
+ tf.optional(KEY_HIERARCHY) => tf.array_of(tf.struct(
441
+ {
442
+ KEY_NAME => nes_t,
443
+ tf.optional(KEY_OPTIONS) => tf.hash_kv(option_name_t, tf.data),
444
+ tf.optional(KEY_DATA_HASH) => nes_t,
445
+ tf.optional(KEY_LOOKUP_KEY) => nes_t,
446
+ tf.optional(KEY_V3_BACKEND) => nes_t,
447
+ tf.optional(KEY_V4_DATA_HASH) => nes_t,
448
+ tf.optional(KEY_DATA_DIG) => nes_t,
449
+ tf.optional(KEY_PATH) => nes_t,
450
+ tf.optional(KEY_PATHS) => tf.array_of(nes_t, tf.range(1, :default)),
451
+ tf.optional(KEY_GLOB) => nes_t,
452
+ tf.optional(KEY_GLOBS) => tf.array_of(nes_t, tf.range(1, :default)),
453
+ tf.optional(KEY_URI) => uri_t,
454
+ tf.optional(KEY_URIS) => tf.array_of(uri_t, tf.range(1, :default)),
455
+ tf.optional(KEY_DATADIR) => nes_t
456
+ }))
457
+ })
458
+ end
459
+
460
+ def create_configured_data_providers(lookup_invocation, parent_data_provider)
461
+ defaults = @config[KEY_DEFAULTS] || EMPTY_HASH
462
+ datadir = defaults[KEY_DATADIR] || 'data'
463
+
464
+ # Hashes enumerate their values in the order that the corresponding keys were inserted so it's safe to use
465
+ # a hash for the data_providers.
466
+ data_providers = {}
467
+ @config[KEY_HIERARCHY].each do |he|
468
+ name = he[KEY_NAME]
469
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: Name '#{name}' defined more than once" if data_providers.include?(name)
470
+ function_kind = ALL_FUNCTION_KEYS.find { |key| he.include?(key) }
471
+ if function_kind.nil?
472
+ function_kind = FUNCTION_KEYS.find { |key| defaults.include?(key) }
473
+ function_name = defaults[function_kind]
474
+ else
475
+ function_name = he[function_kind]
476
+ end
477
+
478
+ entry_datadir = @config_root + (he[KEY_DATADIR] || datadir)
479
+ location_key = LOCATION_KEYS.find { |key| he.include?(key) }
480
+ locations = case location_key
481
+ when KEY_PATHS
482
+ resolve_paths(entry_datadir, he[location_key], lookup_invocation, @config_path.nil?)
483
+ when KEY_PATH
484
+ resolve_paths(entry_datadir, [he[location_key]], lookup_invocation, @config_path.nil?)
485
+ when KEY_GLOBS
486
+ expand_globs(entry_datadir, he[location_key], lookup_invocation)
487
+ when KEY_GLOB
488
+ expand_globs(entry_datadir, [he[location_key]], lookup_invocation)
489
+ when KEY_URIS
490
+ expand_uris(he[location_key], lookup_invocation)
491
+ when KEY_URI
492
+ expand_uris([he[location_key]], lookup_invocation)
493
+ else
494
+ nil
495
+ end
496
+ next if @config_path.nil? && !locations.nil? && locations.empty? # Default config and no existing paths found
497
+ options = he[KEY_OPTIONS]
498
+ options = options.nil? ? EMPTY_HASH : interpolate(options, lookup_invocation, false)
499
+ if(function_kind == KEY_V3_BACKEND)
500
+ unless parent_data_provider.is_a?(GlobalDataProvider)
501
+ # hiera3_backend is not allowed in environments and modules
502
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: '#{KEY_V3_BACKEND}' is only allowed in the global layer"
503
+ end
504
+
505
+ if function_name == 'json' || function_name == 'yaml' || function_name == 'hocon' && Puppet.features.hocon?
506
+ # Disallow use of backends that have corresponding "data_hash" functions in version 5
507
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: Use \"#{KEY_DATA_HASH}: #{function_name}_data\" instead of \"#{KEY_V3_BACKEND}: #{function_name}\""
508
+ end
509
+ v3options = { :datadir => entry_datadir.to_s }
510
+ options.each_pair { |k, v| v3options[k.to_sym] = v }
511
+ data_providers[name] = create_hiera3_backend_provider(name, function_name, parent_data_provider, entry_datadir, locations, {
512
+ :hierarchy =>
513
+ locations.nil? ? [] : locations.map do |loc|
514
+ path = loc.original_location
515
+ path.end_with?(".#{function_name}") ? path[0..-(function_name.length + 2)] : path
516
+ end,
517
+ function_name.to_sym => v3options,
518
+ :backends => [ function_name ],
519
+ :logger => 'puppet'
520
+ })
521
+ else
522
+ data_providers[name] = create_data_provider(name, parent_data_provider, function_kind, function_name, options, locations)
523
+ end
524
+ end
525
+ data_providers.values
526
+ end
527
+
528
+ RESERVED_OPTION_KEYS = ['path', 'uri'].freeze
529
+
530
+ DEFAULT_CONFIG_HASH = {
531
+ KEY_VERSION => 5,
532
+ KEY_DEFAULTS => {
533
+ KEY_DATADIR => 'data',
534
+ KEY_DATA_HASH => 'yaml_data'
535
+ },
536
+ KEY_HIERARCHY => [
537
+ {
538
+ KEY_NAME => 'Common',
539
+ KEY_PATH => 'common.yaml',
540
+ }
541
+ ]
542
+ }.freeze
543
+
544
+ def validate_config(config)
545
+ config[KEY_DEFAULTS] ||= DEFAULT_CONFIG_HASH[KEY_DEFAULTS]
546
+ config[KEY_HIERARCHY] ||= DEFAULT_CONFIG_HASH[KEY_HIERARCHY]
547
+
548
+ Types::TypeAsserter.assert_instance_of(["The Lookup Configuration at '%s'", @config_path], self.class.config_type, config)
549
+ defaults = config[KEY_DEFAULTS]
550
+ validate_defaults(defaults) unless defaults.nil?
551
+ config[KEY_HIERARCHY].each do |he|
552
+ name = he[KEY_NAME]
553
+ case ALL_FUNCTION_KEYS.count { |key| he.include?(key) }
554
+ when 0
555
+ if defaults.nil? || FUNCTION_KEYS.count { |key| defaults.include?(key) } == 0
556
+ raise Puppet::DataBinding::LookupError,
557
+ "#{@config_path}: One of #{combine_strings(FUNCTION_KEYS)} must defined in hierarchy '#{name}'"
558
+ end
559
+ when 1
560
+ # OK
561
+ when 0
562
+ raise Puppet::DataBinding::LookupError,
563
+ "#{@config_path}: One of #{combine_strings(FUNCTION_KEYS)} must defined in hierarchy '#{name}'"
564
+ else
565
+ raise Puppet::DataBinding::LookupError,
566
+ "#{@config_path}: Only one of #{combine_strings(FUNCTION_KEYS)} can be defined in hierarchy '#{name}'"
567
+ end
568
+
569
+ if LOCATION_KEYS.count { |key| he.include?(key) } > 1
570
+ raise Puppet::DataBinding::LookupError,
571
+ "#{@config_path}: Only one of #{combine_strings(LOCATION_KEYS)} can be defined in hierarchy '#{name}'"
572
+ end
573
+
574
+ options = he[KEY_OPTIONS]
575
+ unless options.nil?
576
+ RESERVED_OPTION_KEYS.each do |key|
577
+ if options.include?(key)
578
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: Option key '#{key}' used in hierarchy '#{name}' is reserved by Puppet"
579
+ end
580
+ end
581
+ end
582
+ end
583
+ config
584
+ end
585
+
586
+ def validate_defaults(defaults)
587
+ case FUNCTION_KEYS.count { |key| defaults.include?(key) }
588
+ when 0, 1
589
+ # OK
590
+ else
591
+ raise Puppet::DataBinding::LookupError,
592
+ "#{@config_path}: Only one of #{combine_strings(FUNCTION_KEYS)} can be defined in defaults"
593
+ end
594
+ end
595
+
596
+ def version
597
+ 5
598
+ end
599
+ end
600
+ end
601
+ end