puppet 4.8.2-x64-mingw32 → 4.9.0-x64-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
@@ -28,7 +28,7 @@ describe 'the binary_file function' do
28
28
  with_file_content('one') do |one|
29
29
  compile_to_catalog("notify { binary_file('#{one}/nope'):}")
30
30
  end
31
- end.to raise_error(/The given file '.*' does not exist/)
31
+ end.to raise_error(/The given file '.+\/nope' does not exist/)
32
32
  end
33
33
 
34
34
  it 'reads an existing file in a module' do
@@ -1,125 +1,335 @@
1
1
  require 'spec_helper'
2
- require 'puppet_spec/scope'
2
+ require 'puppet_spec/compiler'
3
3
  require 'puppet/pops'
4
- require 'puppet/loaders'
5
4
 
6
5
  describe 'when calling' do
7
- include PuppetSpec::Scope
6
+ include PuppetSpec::Compiler
7
+ include PuppetSpec::Files
8
8
 
9
- let(:scope) { create_test_scope_for_node('foo') }
10
- let(:loaders) { Puppet::Pops::Loaders.new(Puppet::Node::Environment.create(:testing, [])) }
11
- let(:loader) { loaders.puppet_system_loader }
9
+ let(:global_dir) { tmpdir('global') }
10
+ let(:env_config) { {} }
11
+ let(:global_files) do
12
+ {
13
+ 'hiera.yaml' => <<-YAML.unindent,
14
+ ---
15
+ :backends:
16
+ - yaml
17
+ - custom
18
+ :yaml:
19
+ :datadir: #{global_dir}/hieradata
20
+ :hierarchy:
21
+ - first
22
+ - second
23
+ YAML
24
+ 'ruby_stuff' => {
25
+ 'hiera' => {
26
+ 'backend' => {
27
+ 'custom_backend.rb' => <<-RUBY.unindent
28
+ class Hiera::Backend::Custom_backend
29
+ def initialize(cache = nil)
30
+ Hiera.debug('Custom_backend starting')
31
+ end
32
+
33
+ def lookup(key, scope, order_override, resolution_type, context)
34
+ case key
35
+ when 'datasources'
36
+ Hiera::Backend.datasources(scope, order_override) { |source| source }
37
+ else
38
+ throw :no_such_key
39
+ end
40
+ end
41
+ end
42
+ RUBY
43
+ }
44
+ }
45
+ },
46
+ 'hieradata' => {
47
+ 'first.yaml' => <<-YAML.unindent,
48
+ ---
49
+ a: first a
50
+ class_name: "-- %{calling_class} --"
51
+ class_path: "-- %{calling_class_path} --"
52
+ module: "-- %{calling_module} --"
53
+ mod_name: "-- %{module_name} --"
54
+ database_user:
55
+ name: postgres
56
+ uid: 500
57
+ gid: 500
58
+ b:
59
+ b1: first b1
60
+ b2: first b2
61
+ fbb:
62
+ - mod::foo
63
+ - mod::bar
64
+ - mod::baz
65
+ empty_array: []
66
+ YAML
67
+ 'second.yaml' => <<-YAML.unindent,
68
+ ---
69
+ a: second a
70
+ b:
71
+ b1: second b1
72
+ b3: second b3
73
+ YAML
74
+ 'the_override.yaml' => <<-YAML.unindent
75
+ ---
76
+ key: foo_result
77
+ YAML
78
+ },
79
+ 'environments' => {
80
+ 'test' => {
81
+ 'modules' => {
82
+ 'mod' => {
83
+ 'manifests' => {
84
+ 'foo.pp' => <<-PUPPET.unindent,
85
+ class mod::foo {
86
+ notice(hiera('class_name'))
87
+ notice(hiera('class_path'))
88
+ notice(hiera('module'))
89
+ notice(hiera('mod_name'))
90
+ }
91
+ PUPPET
92
+ 'bar.pp' => <<-PUPPET.unindent,
93
+ class mod::bar {}
94
+ PUPPET
95
+ 'baz.pp' => <<-PUPPET.unindent
96
+ class mod::baz {}
97
+ PUPPET
98
+ },
99
+ 'hiera.yaml' => <<-YAML.unindent,
100
+ ---
101
+ version: 5
102
+ YAML
103
+ 'data' => {
104
+ 'common.yaml' => <<-YAML.unindent
105
+ mod::c: mod::c (from module)
106
+ YAML
107
+ }
108
+ }
109
+ }
110
+ }
111
+ }
112
+ }
113
+ end
12
114
 
13
- context 'hiera' do
14
- let(:hiera) { loader.load(:function, 'hiera') }
115
+ let(:logs) { [] }
116
+ let(:warnings) { logs.select { |log| log.level == :warning }.map { |log| log.message } }
117
+ let(:env_dir) { File.join(global_dir, 'environments') }
118
+ let(:env) { Puppet::Node::Environment.create(:test, [File.join(env_dir, 'test', 'modules')]) }
119
+ let(:environments) { Puppet::Environments::Directories.new(env_dir, []) }
120
+ let(:node) { Puppet::Node.new('test_hiera', :environment => env) }
121
+ let(:compiler) { Puppet::Parser::Compiler.new(node) }
122
+ let(:the_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'hiera') }
123
+
124
+ before(:each) do
125
+ Puppet.settings[:codedir] = global_dir
126
+ Puppet.settings[:hiera_config] = File.join(global_dir, 'hiera.yaml')
127
+ end
128
+
129
+ around(:each) do |example|
130
+ # Faking the load path to enable 'require' to load from 'ruby_stuff'. It removes the need for a static fixture
131
+ # for the custom backend
132
+ dir_contained_in(global_dir, DeepMerge.deep_merge!(global_files, { 'environments' => { 'test' => env_config } } ))
133
+ $LOAD_PATH.unshift(File.join(global_dir, 'ruby_stuff'))
134
+ begin
135
+ Puppet.override(:environments => environments, :current_environment => env) do
136
+ example.run
137
+ end
138
+ ensure
139
+ Hiera::Backend.send(:remove_const, :Custom_backend) if Hiera::Backend.const_defined?(:Custom_backend)
140
+ $LOAD_PATH.shift
141
+ end
142
+ end
143
+
144
+ def with_scope(code = 'undef')
145
+ result = nil
146
+ Puppet[:code] = 'undef'
147
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
148
+ compiler.topscope['environment'] = 'test'
149
+ compiler.compile do |catalog|
150
+ result = yield(compiler.topscope)
151
+ catalog
152
+ end
153
+ end
154
+ result
155
+ end
15
156
 
157
+ def func(*args, &block)
158
+ with_scope { |scope| the_func.call(scope, *args, &block) }
159
+ end
160
+
161
+ context 'hiera' do
16
162
  it 'should require a key argument' do
17
- expect { hiera.call(scope, []) }.to raise_error(ArgumentError)
163
+ expect { func([]) }.to raise_error(ArgumentError)
18
164
  end
19
165
 
20
166
  it 'should raise a useful error when nil is returned' do
21
- expect { hiera.call(scope, 'badkey') }.to raise_error(Puppet::ParseError, /Could not find data item badkey/)
167
+ expect { func('badkey') }.to raise_error(Puppet::DataBinding::LookupError, /did not find a value for the name 'badkey'/)
168
+ end
169
+
170
+ it 'should use the "first" merge strategy' do
171
+ expect(func('a')).to eql('first a')
22
172
  end
23
173
 
24
- it 'should use the priority resolution_type' do
25
- Hiera.any_instance.expects(:lookup).with { |*args| expect(args[4]).to be(:priority) }.returns('foo_result')
26
- expect(hiera.call(scope, 'key')).to eql('foo_result')
174
+ it 'should not find data in module' do
175
+ expect(func('mod::c', 'default mod::c')).to eql('default mod::c')
27
176
  end
28
177
 
29
178
  it 'should propagate optional override' do
30
179
  ovr = 'the_override'
31
- Hiera.any_instance.expects(:lookup).with { |*args| expect(args[3]).to be(ovr) }.returns('foo_result')
32
- expect(hiera.call(scope, 'key', nil, ovr)).to eql('foo_result')
180
+ expect(func('key', nil, ovr)).to eql('foo_result')
181
+ end
182
+
183
+ it 'backend data sources, including optional overrides, are propagated to custom backend' do
184
+ expect(func('datasources', nil, 'the_override')).to eql(['the_override', 'first', 'second'])
185
+ end
186
+
187
+ it 'a hiera v3 scope is used' do
188
+ expect(eval_and_collect_notices(<<-PUPPET, node)).to eql(['-- testing --', '-- mod::foo --', '-- mod/foo --', '-- mod --', '-- mod --'])
189
+ class testing () {
190
+ notice(hiera('class_name'))
191
+ }
192
+ include testing
193
+ include mod::foo
194
+ PUPPET
33
195
  end
34
196
 
35
197
  it 'should return default value nil when key is not found' do
36
- expect(hiera.call(scope, 'foo', nil)).to be_nil
198
+ expect(func('foo', nil)).to be_nil
37
199
  end
38
200
 
39
201
  it "should return default value '' when key is not found" do
40
- expect(hiera.call(scope, 'foo', '')).to eq('')
202
+ expect(func('foo', '')).to eq('')
41
203
  end
42
204
 
43
205
  it 'should use default block' do
44
- #expect(hiera.call(scope, 'foo', lambda_1(scope, loader) { |k| "default for key '#{k}'" })).to eql("default for key 'foo'")
45
- expect(hiera.call(scope, 'foo') { |k| "default for key '#{k}'" }).to eql("default for key 'foo'")
206
+ expect(func('foo') { |k| "default for key '#{k}'" }).to eql("default for key 'foo'")
46
207
  end
47
208
 
48
209
  it 'should propagate optional override when combined with default block' do
49
- ovr = {}
50
- Hiera::Backend::Yaml_backend.any_instance.expects(:lookup).with { |*args| expect(args[2]).to be(ovr) }.returns(nil)
51
- expect(hiera.call(scope, 'foo.bar', ovr) { |k| "default for key '#{k}'" }).to eql("default for key 'foo.bar'")
210
+ ovr = 'the_override'
211
+ with_scope do |scope|
212
+ expect(the_func.call(scope, 'key', ovr) { |k| "default for key '#{k}'" }).to eql('foo_result')
213
+ expect(the_func.call(scope, 'foo.bar', ovr) { |k| "default for key '#{k}'" }).to eql("default for key 'foo.bar'")
214
+ end
215
+ end
216
+
217
+ it 'should log deprecation errors' do
218
+ func('a')
219
+ expect(warnings).to include(/The function 'hiera' is deprecated in favor of using 'lookup'. See https:/)
220
+ end
221
+
222
+ context 'with environment with configured data provider' do
223
+ let(:env_config) {
224
+ {
225
+ 'hiera.yaml' => <<-YAML.unindent,
226
+ ---
227
+ version: 5
228
+ YAML
229
+ 'data' => {
230
+ 'common.yaml' => <<-YAML.unindent
231
+ ---
232
+ a: a (from environment)
233
+ e: e (from environment)
234
+ YAML
235
+ }
236
+ }
237
+ }
238
+
239
+ it 'should find data globally' do
240
+ expect(func('a')).to eql('first a')
241
+ end
242
+
243
+ it 'should find data in the environment' do
244
+ expect(func('e')).to eql('e (from environment)')
245
+ end
246
+
247
+ it 'should find data in module' do
248
+ expect(func('mod::c')).to eql('mod::c (from module)')
249
+ end
52
250
  end
53
251
  end
54
252
 
55
253
  context 'hiera_array' do
56
- # noinspection RubyResolve
57
- let(:hiera_array) { loader.load(:function, 'hiera_array') }
254
+ let(:the_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'hiera_array') }
58
255
 
59
256
  it 'should require a key argument' do
60
- expect { hiera_array.call(scope, []) }.to raise_error(ArgumentError)
257
+ expect { func([]) }.to raise_error(ArgumentError)
61
258
  end
62
259
 
63
260
  it 'should raise a useful error when nil is returned' do
64
- expect { hiera_array.call(scope, 'badkey') }.to raise_error(Puppet::ParseError, /Could not find data item badkey/)
261
+ expect { func('badkey') }.to raise_error(Puppet::DataBinding::LookupError, /did not find a value for the name 'badkey'/)
262
+ end
263
+
264
+ it 'should log deprecation errors' do
265
+ func('fbb')
266
+ expect(warnings).to include(/The function 'hiera_array' is deprecated in favor of using 'lookup'/)
65
267
  end
66
268
 
67
269
  it 'should use the array resolution_type' do
68
- Hiera.any_instance.expects(:lookup).with { |*args| expect(args[4]).to be(:array) }.returns(%w[foo bar baz])
69
- expect(hiera_array.call(scope, 'key', {'key' => 'foo_result'})).to eql(%w[foo bar baz])
270
+ expect(func('fbb', {'fbb' => 'foo_result'})).to eql(%w[mod::foo mod::bar mod::baz])
70
271
  end
71
272
 
72
273
  it 'should use default block' do
73
- expect(hiera_array.call(scope, 'foo') { |k| ['key', k] }).to eql(%w[key foo])
274
+ expect(func('foo') { |k| ['key', k] }).to eql(%w[key foo])
74
275
  end
75
276
  end
76
277
 
77
278
  context 'hiera_hash' do
78
- let(:hiera_hash) { loader.load(:function, 'hiera_hash') }
279
+ let(:the_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'hiera_hash') }
79
280
 
80
281
  it 'should require a key argument' do
81
- expect { hiera_hash.call(scope, []) }.to raise_error(ArgumentError)
282
+ expect { func([]) }.to raise_error(ArgumentError)
82
283
  end
83
284
 
84
285
  it 'should raise a useful error when nil is returned' do
85
- expect { hiera_hash.call(scope, 'badkey') }.to raise_error(Puppet::ParseError, /Could not find data item badkey/)
286
+ expect { func('badkey') }.to raise_error(Puppet::DataBinding::LookupError, /did not find a value for the name 'badkey'/)
86
287
  end
87
288
 
88
289
  it 'should use the hash resolution_type' do
89
- Hiera.any_instance.expects(:lookup).with { |*args| expect(args[4]).to be(:hash) }.returns({'foo' => 'result'})
90
- expect(hiera_hash.call(scope, 'key', {'key' => 'foo_result'})).to eql({'foo' => 'result'})
290
+ expect(func('b', {'b' => 'foo_result'})).to eql({ 'b1' => 'first b1', 'b2' => 'first b2', 'b3' => 'second b3'})
291
+ end
292
+
293
+ it 'should lookup and return a hash' do
294
+ expect(func('database_user')).to eql({ 'name' => 'postgres', 'uid' => 500, 'gid' => 500})
295
+ end
296
+
297
+ it 'should log deprecation errors' do
298
+ func('b')
299
+ expect(warnings).to include(/The function 'hiera_hash' is deprecated in favor of using 'lookup'. See https:/)
91
300
  end
92
301
 
93
302
  it 'should use default block' do
94
- expect(hiera_hash.call(scope, 'foo') { |k| {'key' => k} }).to eql({'key' => 'foo'})
303
+ expect(func('foo') { |k| {'key' => k} }).to eql({'key' => 'foo'})
95
304
  end
96
305
  end
97
306
 
98
307
  context 'hiera_include' do
99
- let(:hiera_include) { loader.load(:function, 'hiera_include') }
308
+ let(:the_func) { Puppet.lookup(:loaders).puppet_system_loader.load(:function, 'hiera_include') }
100
309
 
101
310
  it 'should require a key argument' do
102
- expect { hiera_include.call(scope, []) }.to raise_error(ArgumentError)
311
+ expect { func([]) }.to raise_error(ArgumentError)
103
312
  end
104
313
 
105
314
  it 'should raise a useful error when nil is returned' do
106
- expect { hiera_include.call(scope, 'badkey') }.to raise_error(Puppet::ParseError, /Could not find data item badkey/)
315
+ expect { func('badkey') }.to raise_error(Puppet::DataBinding::LookupError, /did not find a value for the name 'badkey'/)
107
316
  end
108
317
 
109
- it 'should use the array resolution_type' do
110
- Hiera.any_instance.expects(:lookup).with { |*args| expect(args[4]).to be(:array) }.returns(%w[foo bar baz])
111
- hiera_include.expects(:call_function_with_scope).with(scope, 'include', %w[foo bar baz])
112
- hiera_include.call(scope, 'key', {'key' => 'foo_result'})
318
+ it 'should use the array resolution_type to include classes' do
319
+ expect(func('fbb').map { |c| c.class_name }).to eql(%w[mod::foo mod::bar mod::baz])
320
+ end
321
+
322
+ it 'should log deprecation errors' do
323
+ func('fbb')
324
+ expect(warnings).to include(/The function 'hiera_include' is deprecated in favor of using 'lookup'. See https:/)
113
325
  end
114
326
 
115
327
  it 'should not raise an error if the resulting hiera lookup returns an empty array' do
116
- Hiera.any_instance.expects(:lookup).returns []
117
- expect { hiera_include.call(scope, 'key') }.to_not raise_error
328
+ expect { func('empty_array') }.to_not raise_error
118
329
  end
119
330
 
120
- it 'should use default block' do
121
- hiera_include.expects(:call_function_with_scope).with(scope,'include', %w[key foo])
122
- hiera_include.call(scope, 'foo') { |k| ['key', k] }
331
+ it 'should use default block array to include classes' do
332
+ expect(func('foo') { |k| ['mod::bar', "mod::#{k}"] }.map { |c| c.class_name }).to eql(%w[mod::bar mod::foo])
123
333
  end
124
334
  end
125
335
  end
@@ -0,0 +1,693 @@
1
+ #! /usr/bin/env ruby
2
+ require 'spec_helper'
3
+ require 'puppet_spec/compiler'
4
+ require 'puppet_spec/files'
5
+ require 'puppet/pops'
6
+ require 'deep_merge/core'
7
+
8
+ # Tests the lookup function using fixtures
9
+ describe 'The lookup function' do
10
+ include PuppetSpec::Compiler
11
+
12
+ # Assembles code that includes the *abc* class and compiles it into a catalog. This class will use the global
13
+ # variable $args to perform a lookup and assign the result to $abc::result. Unless the $block is set to
14
+ # the string 'no_block_present', it will be passed as a lambda to the lookup. The assembled code will declare
15
+ # a notify resource with a name that is formed by interpolating the result into a format string.
16
+ #
17
+ # The method performs the folloging steps.
18
+ #
19
+ # - Build the code that:
20
+ # - sets the $args variable from _lookup_args_
21
+ # - sets the $block parameter to the given block or the string 'no_block_present'
22
+ # - includes the abc class
23
+ # - assigns the $abc::result to $r
24
+ # - interpolates a string using _fmt_ (which is assumed to use $r)
25
+ # - declares a notify resource from the interpolated string
26
+ # - Compile the code into a catalog
27
+ # - Return the name of all Notify resources in that catalog
28
+ #
29
+ # @param fmt [String] The puppet interpolated string used when creating the notify title
30
+ # @param *args [String] splat of args that will be concatenated to form the puppet args sent to lookup
31
+ # @return [Array<String>] List of names of Notify resources in the resulting catalog
32
+ #
33
+ def assemble_and_compile(fmt, *lookup_args, &block)
34
+ assemble_and_compile_with_block(fmt, "'no_block_present'", *lookup_args, &block)
35
+ end
36
+
37
+ def assemble_and_compile_with_block(fmt, block, *lookup_args, &cblock)
38
+ compile_and_get_notifications(<<-END.unindent, &cblock)
39
+ $args = [#{lookup_args.join(',')}]
40
+ $block = #{block}
41
+ include abc
42
+ $r = if $abc::result == undef { 'no_value' } else { $abc::result }
43
+ notify { \"#{fmt}\": }
44
+ END
45
+ end
46
+
47
+ def compile_and_get_notifications(code)
48
+ Puppet[:code] = code
49
+ node.environment.check_for_reparse
50
+ catalog = block_given? ? compiler.compile { |catalog| yield(compiler.topscope); catalog } : compiler.compile
51
+ catalog.resources.map(&:ref).select { |r| r.start_with?('Notify[') }.map { |r| r[7..-2] }
52
+ end
53
+
54
+ # There is a fully configured 'production' environment in fixtures at this location
55
+ let(:environmentpath) { File.join(my_fixture_dir, 'environments') }
56
+ let(:node) { Puppet::Node.new("testnode", :facts => Puppet::Node::Facts.new("facts", {}), :environment => 'production') }
57
+ let(:compiler) { Puppet::Parser::Compiler.new(node) }
58
+
59
+ around(:each) do |example|
60
+ # Initialize settings to get a full compile as close as possible to a real
61
+ # environment load
62
+ Puppet.settings.initialize_global_settings
63
+
64
+ # Initialize loaders based on the environmentpath. It does not work to
65
+ # just set the setting environmentpath for some reason - this achieves the same:
66
+ # - first a loader is created, loading directory environments from the fixture (there is
67
+ # one environment, 'sample', which will be loaded since the node references this
68
+ # environment by name).
69
+ # - secondly, the created env loader is set as 'environments' in the puppet context.
70
+ #
71
+ environments = Puppet::Environments::Directories.new(environmentpath, [])
72
+ Puppet.override(:environments => environments) do
73
+ example.run
74
+ end
75
+ end
76
+
77
+ context 'using valid parameters' do
78
+ it 'can lookup value provided by the environment' do
79
+ resources = assemble_and_compile('${r}', "'abc::a'")
80
+ expect(resources).to include('env_a')
81
+ end
82
+
83
+ it 'can lookup value provided by the module' do
84
+ resources = assemble_and_compile('${r}', "'abc::b'")
85
+ expect(resources).to include('module_b')
86
+ end
87
+
88
+ it "can lookup value provided by the module that has 'function' data_provider entry in metadata.json" do
89
+ resources = compile_and_get_notifications("$args = ['meta::b']\ninclude meta\nnotify { $meta::result: }\n")
90
+ expect(resources).to include('module_b')
91
+ end
92
+
93
+ it "can lookup value provided by the module that has 'sample' data_provider entry in metadata.json" do
94
+ resources = compile_and_get_notifications("$args = ['metawcp::b']\ninclude metawcp\nnotify { $metawcp::result: }\n")
95
+ expect(resources).to include('module_b')
96
+ end
97
+
98
+ it 'can lookup value provided in global scope' do
99
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
100
+ resources = assemble_and_compile('${r}', "'abc::a'")
101
+ expect(resources).to include('global_a')
102
+ end
103
+
104
+ it 'will stop at first found name when several names are provided' do
105
+ resources = assemble_and_compile('${r}', "['abc::b', 'abc::a']")
106
+ expect(resources).to include('module_b')
107
+ end
108
+
109
+ it 'can lookup value provided by the module that is overriden by environment' do
110
+ resources = assemble_and_compile('${r}', "'abc::c'")
111
+ expect(resources).to include('env_c')
112
+ end
113
+
114
+ it "can 'unique' merge values provided by both the module and the environment" do
115
+ resources = assemble_and_compile('${r[0]}_${r[1]}', "'abc::c'", 'Array[String]', "'unique'")
116
+ expect(resources).to include('env_c_module_c')
117
+ end
118
+
119
+ it "can 'hash' merge values provided by the environment only" do
120
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::d'", 'Hash[String,String]', "'hash'")
121
+ expect(resources).to include('env_d1_env_d2_env_d3')
122
+ end
123
+
124
+ it "can 'hash' merge values provided by both the environment and the module" do
125
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "'hash'")
126
+ expect(resources).to include('env_e1_module_e2_env_e3')
127
+ end
128
+
129
+ it "can 'hash' merge values provided by global, environment, and module" do
130
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
131
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "'hash'")
132
+ expect(resources).to include('global_e1_module_e2_env_e3')
133
+ end
134
+
135
+ it "can pass merge parameter in the form of a hash with a 'strategy=>unique'" do
136
+ resources = assemble_and_compile('${r[0]}_${r[1]}', "'abc::c'", 'Array[String]', "{strategy => 'unique'}")
137
+ expect(resources).to include('env_c_module_c')
138
+ end
139
+
140
+ it "can pass merge parameter in the form of a hash with 'strategy=>hash'" do
141
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "{strategy => 'hash'}")
142
+ expect(resources).to include('env_e1_module_e2_env_e3')
143
+ end
144
+
145
+ it "can pass merge parameter in the form of a hash with a 'strategy=>deep'" do
146
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "{strategy => 'deep'}")
147
+ expect(resources).to include('env_e1_module_e2_env_e3')
148
+ end
149
+
150
+ it "will fail unless merge in the form of a hash contains a 'strategy'" do
151
+ expect do
152
+ assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "{merge_key => 'hash'}")
153
+ end.to raise_error(Puppet::ParseError, /hash given as 'merge' must contain the name of a strategy/)
154
+ end
155
+
156
+ it 'will raise an exception when value is not found for single key and no default is provided' do
157
+ expect do
158
+ assemble_and_compile('${r}', "'abc::x'")
159
+ end.to raise_error(Puppet::ParseError, /did not find a value for the name 'abc::x'/)
160
+ end
161
+
162
+ it 'can lookup an undef value' do
163
+ resources = assemble_and_compile('${r}', "'abc::n'")
164
+ expect(resources).to include('no_value')
165
+ end
166
+
167
+ it 'will not replace an undef value with a given default' do
168
+ resources = assemble_and_compile('${r}', "'abc::n'", 'undef', 'undef', '"default_n"')
169
+ expect(resources).to include('no_value')
170
+ end
171
+
172
+ it 'will not accept a succesful lookup of an undef value when the type rejects it' do
173
+ expect do
174
+ assemble_and_compile('${r}', "'abc::n'", 'String')
175
+ end.to raise_error(Puppet::ParseError, /Found value has wrong type, expects a String value, got Undef/)
176
+ end
177
+
178
+ it 'will raise an exception when value is not found for array key and no default is provided' do
179
+ expect do
180
+ assemble_and_compile('${r}', "['abc::x', 'abc::y']")
181
+ end.to raise_error(Puppet::ParseError, /did not find a value for any of the names \['abc::x', 'abc::y'\]/)
182
+ end
183
+
184
+ it 'can lookup and deep merge shallow values provided by the environment only' do
185
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::d'", 'Hash[String,String]', "'deep'")
186
+ expect(resources).to include('env_d1_env_d2_env_d3')
187
+ end
188
+
189
+ it 'can lookup and deep merge shallow values provided by both the module and the environment' do
190
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "'deep'")
191
+ expect(resources).to include('env_e1_module_e2_env_e3')
192
+ end
193
+
194
+ it 'can lookup and deep merge deep values provided by global, environment, and module' do
195
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
196
+ resources = assemble_and_compile('${r[k1][s1]}_${r[k1][s2]}_${r[k1][s3]}_${r[k2][s1]}_${r[k2][s2]}_${r[k2][s3]}', "'abc::f'", 'Hash[String,Hash[String,String]]', "'deep'")
197
+ expect(resources).to include('global_f11_env_f12_module_f13_env_f21_module_f22_global_f23')
198
+ end
199
+
200
+ it 'will propagate resolution_type :array to Hiera when merge == \'unique\'' do
201
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
202
+ resources = assemble_and_compile('${r[0]}_${r[1]}_${r[2]}', "'abc::c'", 'Array[String]', "'unique'")
203
+ expect(resources).to include('global_c_env_c_module_c')
204
+ end
205
+
206
+ it 'will propagate a Hash resolution_type with :behavior => :native to Hiera when merge == \'hash\'' do
207
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
208
+ resources = assemble_and_compile('${r[k1]}_${r[k2]}_${r[k3]}', "'abc::e'", 'Hash[String,String]', "{strategy => 'hash'}")
209
+ expect(resources).to include('global_e1_module_e2_env_e3')
210
+ end
211
+
212
+ it 'will propagate a Hash resolution_type with :behavior => :deeper to Hiera when merge == \'deep\'' do
213
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
214
+ resources = assemble_and_compile('${r[k1][s1]}_${r[k1][s2]}_${r[k1][s3]}_${r[k2][s1]}_${r[k2][s2]}_${r[k2][s3]}', "'abc::f'", 'Hash[String,Hash[String,String]]', "'deep'")
215
+ expect(resources).to include('global_f11_env_f12_module_f13_env_f21_module_f22_global_f23')
216
+ end
217
+
218
+ it 'will propagate a Hash resolution_type with symbolic deep merge options to Hiera' do
219
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
220
+ resources = assemble_and_compile('${r[k1][s1]}_${r[k1][s2]}_${r[k1][s3]}_${r[k2][s1]}_${r[k2][s2]}_${r[k2][s3]}', "'abc::f'", 'Hash[String,Hash[String,String]]', "{ 'strategy' => 'deep', 'knockout_prefix' => '--' }")
221
+ expect(resources).to include('global_f11_env_f12_module_f13_env_f21_module_f22_global_f23')
222
+ end
223
+
224
+ context 'with provided default' do
225
+ it 'will return default when lookup fails' do
226
+ resources = assemble_and_compile('${r}', "'abc::x'", 'String', 'undef', "'dflt_x'")
227
+ expect(resources).to include('dflt_x')
228
+ end
229
+
230
+ it 'can precede default parameter with undef as the value_type and undef as the merge type' do
231
+ resources = assemble_and_compile('${r}', "'abc::x'", 'undef', 'undef', "'dflt_x'")
232
+ expect(resources).to include('dflt_x')
233
+ end
234
+
235
+ it 'can use array' do
236
+ resources = assemble_and_compile('${r[0]}_${r[1]}', "'abc::x'", 'Array[String]', 'undef', "['dflt_x', 'dflt_y']")
237
+ expect(resources).to include('dflt_x_dflt_y')
238
+ end
239
+
240
+ it 'can use hash' do
241
+ resources = assemble_and_compile('${r[a]}_${r[b]}', "'abc::x'", 'Hash[String,String]', 'undef', "{'a' => 'dflt_x', 'b' => 'dflt_y'}")
242
+ expect(resources).to include('dflt_x_dflt_y')
243
+ end
244
+
245
+ it 'fails unless default is an instance of value_type' do
246
+ expect do
247
+ assemble_and_compile('${r[a]}_${r[b]}', "'abc::x'", 'Hash[String,String]', 'undef', "{'a' => 'dflt_x', 'b' => 32}")
248
+ end.to raise_error(Puppet::ParseError,
249
+ /Default value has wrong type, entry 'b' expects a String value, got Integer/)
250
+ end
251
+ end
252
+
253
+ context 'with a default block' do
254
+ it 'will be called when lookup fails' do
255
+ resources = assemble_and_compile_with_block('${r}', "'dflt_x'", "'abc::x'")
256
+ expect(resources).to include('dflt_x')
257
+ end
258
+
259
+ it 'will not called when lookup succeeds but the found value is nil' do
260
+ resources = assemble_and_compile_with_block('${r}', "'dflt_x'", "'abc::n'")
261
+ expect(resources).to include('no_value')
262
+ end
263
+
264
+ it 'can use array' do
265
+ resources = assemble_and_compile_with_block('${r[0]}_${r[1]}', "['dflt_x', 'dflt_y']", "'abc::x'")
266
+ expect(resources).to include('dflt_x_dflt_y')
267
+ end
268
+
269
+ it 'can use hash' do
270
+ resources = assemble_and_compile_with_block('${r[a]}_${r[b]}', "{'a' => 'dflt_x', 'b' => 'dflt_y'}", "'abc::x'")
271
+ expect(resources).to include('dflt_x_dflt_y')
272
+ end
273
+
274
+ it 'can return undef from block' do
275
+ resources = assemble_and_compile_with_block('${r}', 'undef', "'abc::x'")
276
+ expect(resources).to include('no_value')
277
+ end
278
+
279
+ it 'fails unless block returns an instance of value_type' do
280
+ expect do
281
+ assemble_and_compile_with_block('${r[a]}_${r[b]}', "{'a' => 'dflt_x', 'b' => 32}", "'abc::x'", 'Hash[String,String]')
282
+ end.to raise_error(Puppet::ParseError,
283
+ /Value returned from default block has wrong type, entry 'b' expects a String value, got Integer/)
284
+ end
285
+
286
+ it 'receives a single name parameter' do
287
+ resources = assemble_and_compile_with_block('${r}', 'true', "'name_x'")
288
+ expect(resources).to include('name_x')
289
+ end
290
+
291
+ it 'receives an array name parameter' do
292
+ resources = assemble_and_compile_with_block('${r[0]}_${r[1]}', 'true', "['name_x', 'name_y']")
293
+ expect(resources).to include('name_x_name_y')
294
+ end
295
+ end
296
+ end
297
+
298
+ context 'and using dotted keys' do
299
+ it 'can access values in data using dot notation' do
300
+ source = <<-PUPPET
301
+ function environment::data() {
302
+ { a => { b => { c => 'the data' }}}
303
+ }
304
+ notice(lookup('a.b.c'))
305
+ PUPPET
306
+ expect(eval_and_collect_notices(source)).to include('the data')
307
+ end
308
+
309
+ it 'can find data using quoted dot notation' do
310
+ source = <<-PUPPET
311
+ function environment::data() {
312
+ { 'a.b.c' => 'the data' }
313
+ }
314
+ notice(lookup('"a.b.c"'))
315
+ PUPPET
316
+ expect(eval_and_collect_notices(source)).to include('the data')
317
+ end
318
+
319
+ it 'can access values in data using a mix of dot notation and quoted dot notation' do
320
+ source = <<-PUPPET
321
+ function environment::data() {
322
+ { 'a' => { 'b.c' => 'the data' }}
323
+ }
324
+ notice(lookup('a."b.c"'))
325
+ PUPPET
326
+ expect(eval_and_collect_notices(source)).to include('the data')
327
+ end
328
+ end
329
+
330
+ context 'passing a hash as the only parameter' do
331
+ it 'can pass a single name correctly' do
332
+ resources = assemble_and_compile('${r}', "{name => 'abc::a'}")
333
+ expect(resources).to include('env_a')
334
+ end
335
+
336
+ it 'can pass a an array of names correctly' do
337
+ resources = assemble_and_compile('${r}', "{name => ['abc::b', 'abc::a']}")
338
+ expect(resources).to include('module_b')
339
+ end
340
+
341
+ it 'can pass an override map and find values there even though they would be found' do
342
+ resources = assemble_and_compile('${r}', "{name => 'abc::a', override => { abc::a => 'override_a'}}")
343
+ expect(resources).to include('override_a')
344
+ end
345
+
346
+ it 'can pass an default_values_hash and find values there correctly' do
347
+ resources = assemble_and_compile('${r}', "{name => 'abc::x', default_values_hash => { abc::x => 'extra_x'}}")
348
+ expect(resources).to include('extra_x')
349
+ end
350
+
351
+ it 'can pass an default_values_hash but not use it when value is found elsewhere' do
352
+ resources = assemble_and_compile('${r}', "{name => 'abc::a', default_values_hash => { abc::a => 'extra_a'}}")
353
+ expect(resources).to include('env_a')
354
+ end
355
+
356
+ it 'can pass an default_values_hash but not use it when value is found elsewhere even when found value is undef' do
357
+ resources = assemble_and_compile('${r}', "{name => 'abc::n', default_values_hash => { abc::n => 'extra_n'}}")
358
+ expect(resources).to include('no_value')
359
+ end
360
+
361
+ it 'can pass an override and an default_values_hash and find the override value' do
362
+ resources = assemble_and_compile('${r}', "{name => 'abc::x', override => { abc::x => 'override_x'}, default_values_hash => { abc::x => 'extra_x'}}")
363
+ expect(resources).to include('override_x')
364
+ end
365
+
366
+ it 'will raise an exception when value is not found for single key and no default is provided' do
367
+ expect do
368
+ assemble_and_compile('${r}', "{name => 'abc::x'}")
369
+ end.to raise_error(Puppet::ParseError, /did not find a value for the name 'abc::x'/)
370
+ end
371
+
372
+ it 'will not raise an exception when value is not found default value is nil' do
373
+ resources = assemble_and_compile('${r}', "{name => 'abc::x', default_value => undef}")
374
+ expect(resources).to include('no_value')
375
+ end
376
+ end
377
+
378
+ context 'accessing from outside a module' do
379
+ it 'will both log a warning and raise an exception when key in the function provided module data is not prefixed' do
380
+ logs = []
381
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
382
+ Puppet[:code] = "include bad_data\nlookup('bad_data::b')"
383
+ expect { compiler.compile }.to raise_error(Puppet::ParseError, /did not find a value for the name 'bad_data::b'/)
384
+ end
385
+ warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
386
+ expect(warnings).to include("Module 'bad_data': deprecated API function \"bad_data::data\" must use keys qualified with the name of the module")
387
+ end
388
+
389
+ it 'will succeed finding prefixed keys even when a key in the function provided module data is not prefixed' do
390
+ logs = []
391
+ resources = nil
392
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
393
+ resources = compile_and_get_notifications(<<-PUPPET.unindent)
394
+ include bad_data
395
+ notify { lookup('bad_data::c'): }
396
+ PUPPET
397
+ expect(resources).to include('module_c')
398
+ end
399
+ warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
400
+ expect(warnings).to include("Module 'bad_data': deprecated API function \"bad_data::data\" must use keys qualified with the name of the module")
401
+ end
402
+
403
+ it 'will resolve global, environment, and module correctly' do
404
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
405
+ resources = compile_and_get_notifications(<<-PUPPET.unindent)
406
+ include bca
407
+ $r = lookup(bca::e, Hash[String,String], hash)
408
+ notify { "${r[k1]}_${r[k2]}_${r[k3]}": }
409
+ PUPPET
410
+ expect(resources).to include('global_e1_module_bca_e2_env_bca_e3')
411
+ end
412
+
413
+ it 'will resolve global and environment correctly when module has no provider' do
414
+ Puppet.settings[:hiera_config] = File.join(my_fixture_dir, 'hiera.yaml')
415
+ resources = compile_and_get_notifications(<<-PUPPET.unindent)
416
+ include no_provider
417
+ $r = lookup(no_provider::e, Hash[String,String], hash)
418
+ notify { "${r[k1]}_${r[k2]}_${r[k3]}": }
419
+ PUPPET
420
+ expect(resources).to include('global_e1__env_no_provider_e3') # k2 is missing
421
+ end
422
+ end
423
+
424
+ context 'accessing bad data' do
425
+ it 'a warning will be logged when key in the function provided module data is not prefixed' do
426
+ Puppet[:code] = "include bad_data\nlookup('bad_data::c')"
427
+ logs = []
428
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
429
+ compiler.compile
430
+ end
431
+ warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
432
+ expect(warnings).to include("Module 'bad_data': deprecated API function \"bad_data::data\" must use keys qualified with the name of the module")
433
+ end
434
+
435
+ it 'a warning will be logged when key in the hiera provided module data is not prefixed' do
436
+ Puppet[:code] = "include hieraprovider\nlookup('hieraprovider::test::param_a')"
437
+ logs = []
438
+ Puppet::Util::Log.with_destination(Puppet::Test::LogCollector.new(logs)) do
439
+ compiler.compile
440
+ end
441
+ warnings = logs.select { |log| log.level == :warning }.map { |log| log.message }
442
+ expect(warnings).to include("Module 'hieraprovider': Hierarchy entry \"two paths\" must use keys qualified with the name of the module")
443
+ end
444
+ end
445
+
446
+ context 'accessing empty files' do
447
+ # An empty YAML file is OK and should be treated as a file that contains no keys
448
+ it "will fail normally with a 'did not find a value' error when a yaml file is empty" do
449
+ Puppet[:code] = "include empty_yaml\nlookup('empty_yaml::a')"
450
+ expect { compiler.compile }.to raise_error(Puppet::ParseError, /did not find a value for the name 'empty_yaml::a'/)
451
+ end
452
+
453
+ # An empty JSON file is not OK. Should yield a parse error
454
+ it "will fail with a LookupError indicating a parser failure when a json file is empty" do
455
+ Puppet[:code] = "include empty_json\nlookup('empty_json::a')"
456
+ expect { compiler.compile }.to raise_error(Puppet::DataBinding::LookupError, /Unable to parse/)
457
+ end
458
+ end
459
+
460
+ context 'accessing nil values' do
461
+ it 'will find a key with undef value in a yaml file' do
462
+ Puppet[:code] = 'include empty_key_yaml'
463
+ compiler.compile do |catalog|
464
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true)
465
+ begin
466
+ Puppet::Pops::Lookup.lookup('empty_key_yaml::has_undef_value', nil, nil, false, nil, lookup_invocation)
467
+ rescue Puppet::Error
468
+ end
469
+ expect(lookup_invocation.explainer.explain).to include(<<-EOS.unindent(' '))
470
+ Path "#{environmentpath}/production/modules/empty_key_yaml/data/empty_key.yaml"
471
+ Original path: "empty_key"
472
+ Found key: "empty_key_yaml::has_undef_value" value: nil
473
+ EOS
474
+ end
475
+ end
476
+
477
+ it 'will find a key with undef value in a json file' do
478
+ Puppet[:code] = 'include empty_key_json'
479
+ compiler.compile do |catalog|
480
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true)
481
+ begin
482
+ Puppet::Pops::Lookup.lookup('empty_key_json::has_undef_value', nil, nil, false, nil, lookup_invocation)
483
+ rescue Puppet::Error
484
+ end
485
+ expect(lookup_invocation.explainer.explain).to include(<<-EOS.unindent(' '))
486
+ Path "#{environmentpath}/production/modules/empty_key_json/data/empty_key.json"
487
+ Original path: "empty_key"
488
+ Found key: "empty_key_json::has_undef_value" value: nil
489
+ EOS
490
+ end
491
+ end
492
+ end
493
+
494
+ context 'using explain' do
495
+ it 'will explain that module is not found' do
496
+ Puppet[:code] = 'undef'
497
+ compiler.compile do |catalog|
498
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true)
499
+ begin
500
+ Puppet::Pops::Lookup.lookup('ppx::e', nil, nil, false, nil, lookup_invocation)
501
+ rescue Puppet::Error
502
+ end
503
+ expect(lookup_invocation.explainer.explain).to include('Module "ppx" not found')
504
+ end
505
+ end
506
+
507
+ it 'will explain that module does not find a key' do
508
+ Puppet[:code] = 'undef'
509
+ compiler.compile do |catalog|
510
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(compiler.topscope, {}, {}, true)
511
+ begin
512
+ Puppet::Pops::Lookup.lookup('abc::x', nil, nil, false, nil, lookup_invocation)
513
+ rescue Puppet::Error
514
+ end
515
+ expect(lookup_invocation.explainer.explain).to include(<<-EOS.unindent(' '))
516
+ Module "abc" Data Provider (hiera configuration version 5)
517
+ deprecated API function "abc::data"
518
+ No such key: "abc::x"
519
+ EOS
520
+ end
521
+ end
522
+
523
+ it 'will explain deep merge results without options' do
524
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
525
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
526
+ Puppet::Pops::Lookup.lookup('abc::e', Puppet::Pops::Types::TypeParser.singleton.parse('Hash[String,String]'), nil, false, 'deep', lookup_invocation)
527
+ expect(lookup_invocation.explainer.explain).to eq(<<-EOS.unindent)
528
+ Searching for "abc::e"
529
+ Merge strategy deep
530
+ Global Data Provider (hiera configuration version 5)
531
+ No such key: "abc::e"
532
+ Environment Data Provider (hiera configuration version 5)
533
+ deprecated API function "environment::data"
534
+ Found key: "abc::e" value: {
535
+ "k1" => "env_e1",
536
+ "k3" => "env_e3"
537
+ }
538
+ Module "abc" Data Provider (hiera configuration version 5)
539
+ deprecated API function "abc::data"
540
+ Found key: "abc::e" value: {
541
+ "k1" => "module_e1",
542
+ "k2" => "module_e2"
543
+ }
544
+ Merged result: {
545
+ "k1" => "env_e1",
546
+ "k2" => "module_e2",
547
+ "k3" => "env_e3"
548
+ }
549
+ EOS
550
+ end
551
+ end
552
+
553
+ it 'will explain deep merge results with options' do
554
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
555
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
556
+ Puppet::Pops::Lookup.lookup('abc::e', Puppet::Pops::Types::TypeParser.singleton.parse('Hash[String,String]'), nil, false, { 'strategy' => 'deep', 'merge_hash_arrays' => true }, lookup_invocation)
557
+ expect(lookup_invocation.explainer.explain).to include(<<-EOS.unindent(' '))
558
+ Merge strategy deep
559
+ Options: {
560
+ "merge_hash_arrays" => true
561
+ }
562
+ EOS
563
+ end
564
+ end
565
+
566
+ it 'will handle merge when no entries are not found' do
567
+ assemble_and_compile('${r}', "'hieraprovider::test::param_a'") do |scope|
568
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
569
+ begin
570
+ Puppet::Pops::Lookup.lookup('hieraprovider::test::not_found', nil, nil, false, 'deep', lookup_invocation)
571
+ rescue Puppet::DataBinding::LookupError
572
+ end
573
+ expect(lookup_invocation.explainer.explain).to eq(<<-EOS.unindent)
574
+ Searching for "hieraprovider::test::not_found"
575
+ Merge strategy deep
576
+ Global Data Provider (hiera configuration version 5)
577
+ No such key: "hieraprovider::test::not_found"
578
+ Environment Data Provider (hiera configuration version 5)
579
+ deprecated API function "environment::data"
580
+ No such key: "hieraprovider::test::not_found"
581
+ Module "hieraprovider" Data Provider (hiera configuration version 4)
582
+ Using configuration "#{environmentpath}/production/modules/hieraprovider/hiera.yaml"
583
+ Hierarchy entry "two paths"
584
+ Merge strategy deep
585
+ Path "#{environmentpath}/production/modules/hieraprovider/data/first.json"
586
+ Original path: "first"
587
+ No such key: "hieraprovider::test::not_found"
588
+ Path "#{environmentpath}/production/modules/hieraprovider/data/second_not_present.json"
589
+ Original path: "second_not_present"
590
+ Path not found
591
+ EOS
592
+ end
593
+ end
594
+
595
+ it 'will explain value access caused by dot notation in key' do
596
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
597
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
598
+ Puppet::Pops::Lookup.lookup('abc::f.k1.s1', Puppet::Pops::Types::TypeParser.singleton.parse('String'), nil, false, nil, lookup_invocation)
599
+ expect(lookup_invocation.explainer.explain).to include(<<-EOS.unindent(' '))
600
+ Sub key: "k1.s1"
601
+ Found key: "k1" value: {
602
+ "s1" => "env_f11",
603
+ "s2" => "env_f12"
604
+ }
605
+ Found key: "s1" value: "env_f11"
606
+ EOS
607
+ end
608
+ end
609
+
610
+
611
+ it 'will provide a hash containing all explanation elements' do
612
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
613
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
614
+ Puppet::Pops::Lookup.lookup('abc::e', Puppet::Pops::Types::TypeParser.singleton.parse('Hash[String,String]'), nil, false, { 'strategy' => 'deep', 'merge_hash_arrays' => true }, lookup_invocation)
615
+ expect(lookup_invocation.explainer.to_hash).to eq(
616
+ {
617
+ :type => :root,
618
+ :key => 'abc::e',
619
+ :branches => [
620
+ {
621
+ :value => { 'k1' => 'env_e1', 'k2' => 'module_e2', 'k3' => 'env_e3' },
622
+ :event => :result,
623
+ :merge => :deep,
624
+ :options => { 'merge_hash_arrays' => true },
625
+ :type => :merge,
626
+ :branches => [
627
+ {
628
+ :key => 'abc::e',
629
+ :event => :not_found,
630
+ :type => :data_provider,
631
+ :name => 'Global Data Provider (hiera configuration version 5)'
632
+ },
633
+ {
634
+ :type => :data_provider,
635
+ :name => 'Environment Data Provider (hiera configuration version 5)',
636
+ :branches => [
637
+ {
638
+ :type => :data_provider,
639
+ :name => 'deprecated API function "environment::data"',
640
+ :key => 'abc::e',
641
+ :value => { 'k1' => 'env_e1', 'k3' => 'env_e3' },
642
+ :event => :found
643
+ }
644
+ ]
645
+ },
646
+ {
647
+ :type => :data_provider,
648
+ :name => 'Module "abc" Data Provider (hiera configuration version 5)',
649
+ :module => 'abc',
650
+ :branches => [
651
+ {
652
+ :type => :data_provider,
653
+ :name => 'deprecated API function "abc::data"',
654
+ :key => 'abc::e',
655
+ :event => :found,
656
+ :value => {
657
+ 'k1' => 'module_e1',
658
+ 'k2' => 'module_e2'
659
+ }
660
+ }
661
+ ]
662
+ }
663
+ ]
664
+ }
665
+ ]
666
+ }
667
+ )
668
+ end
669
+ end
670
+
671
+ it 'will explain that "lookup_options" is an invalid key' do
672
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
673
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
674
+ begin
675
+ Puppet::Pops::Lookup.lookup('lookup_options', nil, nil, false, nil, lookup_invocation)
676
+ rescue Puppet::Error
677
+ end
678
+ expect(lookup_invocation.explainer.explain.chomp).to eq('Invalid key "lookup_options"')
679
+ end
680
+ end
681
+
682
+ it 'will explain that "lookup_options" is an invalid key for any key starting with "lookup_options."' do
683
+ assemble_and_compile('${r}', "'abc::a'") do |scope|
684
+ lookup_invocation = Puppet::Pops::Lookup::Invocation.new(scope, {}, {}, true)
685
+ begin
686
+ Puppet::Pops::Lookup.lookup('lookup_options.subkey', nil, nil, false, nil, lookup_invocation)
687
+ rescue Puppet::Error
688
+ end
689
+ expect(lookup_invocation.explainer.explain.chomp).to eq('Invalid key "lookup_options"')
690
+ end
691
+ end
692
+ end
693
+ end