puppet 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (422) hide show
  1. data/CONTRIBUTING.md +1 -1
  2. data/Gemfile +5 -7
  3. data/README.md +1 -1
  4. data/Rakefile +20 -0
  5. data/ext/debian/puppet.init +0 -1
  6. data/ext/debian/puppet.logrotate +14 -5
  7. data/ext/osx/puppet.plist +2 -4
  8. data/ext/project_data.yaml +1 -1
  9. data/ext/redhat/client.init +65 -12
  10. data/ext/redhat/logrotate +15 -3
  11. data/ext/redhat/puppet.spec.erb +5 -1
  12. data/ext/redhat/server.init +1 -1
  13. data/ext/solaris/smf/puppet +44 -0
  14. data/ext/solaris/smf/puppet.xml +44 -0
  15. data/ext/suse/client.init +27 -27
  16. data/ext/suse/server.init +2 -2
  17. data/ext/systemd/puppet.service +1 -0
  18. data/install.rb +21 -39
  19. data/lib/hiera/puppet_function.rb +5 -5
  20. data/lib/puppet/agent/locker.rb +11 -2
  21. data/lib/puppet/agent.rb +4 -4
  22. data/lib/puppet/application/agent.rb +28 -14
  23. data/lib/puppet/application/apply.rb +17 -4
  24. data/lib/puppet/application/cert.rb +16 -0
  25. data/lib/puppet/application/filebucket.rb +78 -4
  26. data/lib/puppet/application/lookup.rb +356 -0
  27. data/lib/puppet/application/master.rb +5 -1
  28. data/lib/puppet/configurer.rb +9 -5
  29. data/lib/puppet/context/trusted_information.rb +21 -1
  30. data/lib/puppet/context.rb +16 -1
  31. data/lib/puppet/daemon.rb +17 -13
  32. data/lib/puppet/data_binding.rb +4 -2
  33. data/lib/puppet/data_providers/data_adapter.rb +7 -68
  34. data/lib/puppet/data_providers/data_function_support.rb +5 -26
  35. data/lib/puppet/data_providers/function_env_data_provider.rb +0 -10
  36. data/lib/puppet/data_providers/function_module_data_provider.rb +0 -22
  37. data/lib/puppet/data_providers/hiera_config.rb +106 -0
  38. data/lib/puppet/data_providers/hiera_env_data_provider.rb +18 -0
  39. data/lib/puppet/data_providers/hiera_interpolate.rb +97 -0
  40. data/lib/puppet/data_providers/hiera_module_data_provider.rb +23 -0
  41. data/lib/puppet/data_providers/hiera_support.rb +37 -0
  42. data/lib/puppet/data_providers/json_data_provider_factory.rb +31 -0
  43. data/lib/puppet/data_providers/lookup_adapter.rb +200 -0
  44. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +32 -0
  45. data/lib/puppet/data_providers.rb +12 -13
  46. data/lib/puppet/defaults.rb +14 -3
  47. data/lib/puppet/environments.rb +94 -6
  48. data/lib/puppet/error.rb +4 -0
  49. data/lib/puppet/face/module/changes.rb +2 -1
  50. data/lib/puppet/feature/cfacter.rb +1 -0
  51. data/lib/puppet/file_bucket/dipper.rb +58 -2
  52. data/lib/puppet/file_system/windows.rb +3 -1
  53. data/lib/puppet/functions/assert_type.rb +48 -12
  54. data/lib/puppet/functions/defined.rb +79 -48
  55. data/lib/puppet/functions/each.rb +85 -27
  56. data/lib/puppet/functions/epp.rb +29 -37
  57. data/lib/puppet/functions/filter.rb +60 -25
  58. data/lib/puppet/functions/hiera.rb +76 -3
  59. data/lib/puppet/functions/hiera_array.rb +65 -3
  60. data/lib/puppet/functions/hiera_hash.rb +74 -2
  61. data/lib/puppet/functions/hiera_include.rb +77 -4
  62. data/lib/puppet/functions/inline_epp.rb +44 -71
  63. data/lib/puppet/functions/lookup.rb +19 -17
  64. data/lib/puppet/functions/map.rb +56 -21
  65. data/lib/puppet/functions/match.rb +29 -12
  66. data/lib/puppet/functions/reduce.rb +95 -58
  67. data/lib/puppet/functions/versioncmp.rb +36 -0
  68. data/lib/puppet/functions/with.rb +15 -7
  69. data/lib/puppet/functions.rb +2 -4
  70. data/lib/puppet/indirector/catalog/compiler.rb +3 -3
  71. data/lib/puppet/indirector/catalog/static_compiler.rb +46 -30
  72. data/lib/puppet/indirector/data_binding/none.rb +4 -1
  73. data/lib/puppet/indirector/file_bucket_file/file.rb +58 -1
  74. data/lib/puppet/indirector/hiera.rb +4 -0
  75. data/lib/puppet/indirector/indirection.rb +6 -1
  76. data/lib/puppet/indirector/json.rb +1 -1
  77. data/lib/puppet/indirector/msgpack.rb +1 -1
  78. data/lib/puppet/indirector/request.rb +7 -8
  79. data/lib/puppet/indirector/resource_type/parser.rb +5 -3
  80. data/lib/puppet/info_service/class_information_service.rb +111 -0
  81. data/lib/puppet/info_service.rb +7 -0
  82. data/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  83. data/lib/puppet/module_tool/metadata.rb +32 -9
  84. data/lib/puppet/module_tool/skeleton/templates/generator/README.md.erb +42 -38
  85. data/lib/puppet/module_tool/skeleton/templates/generator/manifests/init.pp.erb +25 -18
  86. data/lib/puppet/network/authconfig.rb +21 -1
  87. data/lib/puppet/network/authorization.rb +8 -1
  88. data/lib/puppet/network/http/api/master/v3/environment.rb +59 -0
  89. data/lib/puppet/network/http/api/master/v3.rb +7 -1
  90. data/lib/puppet/node/environment.rb +9 -2
  91. data/lib/puppet/node.rb +11 -5
  92. data/lib/puppet/parser/ast/pops_bridge.rb +39 -1
  93. data/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +64 -0
  94. data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +38 -0
  95. data/lib/puppet/parser/compiler/catalog_validator/site_validator.rb +20 -0
  96. data/lib/puppet/parser/compiler/catalog_validator.rb +33 -0
  97. data/lib/puppet/parser/compiler.rb +300 -12
  98. data/lib/puppet/parser/environment_compiler.rb +165 -0
  99. data/lib/puppet/parser/functions/assert_type.rb +46 -16
  100. data/lib/puppet/parser/functions/defined.rb +105 -68
  101. data/lib/puppet/parser/functions/each.rb +85 -27
  102. data/lib/puppet/parser/functions/epp.rb +29 -37
  103. data/lib/puppet/parser/functions/filter.rb +59 -23
  104. data/lib/puppet/parser/functions/hiera.rb +83 -27
  105. data/lib/puppet/parser/functions/hiera_array.rb +71 -28
  106. data/lib/puppet/parser/functions/hiera_hash.rb +81 -30
  107. data/lib/puppet/parser/functions/hiera_include.rb +81 -40
  108. data/lib/puppet/parser/functions/inline_epp.rb +35 -60
  109. data/lib/puppet/parser/functions/inline_template.rb +2 -2
  110. data/lib/puppet/parser/functions/map.rb +55 -20
  111. data/lib/puppet/parser/functions/match.rb +27 -12
  112. data/lib/puppet/parser/functions/reduce.rb +97 -60
  113. data/lib/puppet/parser/functions/with.rb +16 -8
  114. data/lib/puppet/parser/resource.rb +103 -21
  115. data/lib/puppet/parser.rb +3 -0
  116. data/lib/puppet/plugins/configuration.rb +3 -2
  117. data/lib/puppet/plugins/data_providers/data_provider.rb +283 -0
  118. data/lib/puppet/plugins/data_providers/registry.rb +84 -0
  119. data/lib/puppet/plugins/data_providers.rb +12 -60
  120. data/lib/puppet/pops/adapters.rb +12 -0
  121. data/lib/puppet/pops/binder/binder.rb +2 -2
  122. data/lib/puppet/pops/binder/bindings_checker.rb +1 -1
  123. data/lib/puppet/pops/binder/bindings_label_provider.rb +3 -1
  124. data/lib/puppet/pops/binder/bindings_loader.rb +6 -2
  125. data/lib/puppet/pops/binder/bindings_model_meta.rb +2 -2
  126. data/lib/puppet/pops/binder/config/binder_config.rb +1 -1
  127. data/lib/puppet/pops/binder/injector.rb +4 -4
  128. data/lib/puppet/pops/binder/key_factory.rb +3 -9
  129. data/lib/puppet/pops/binder/scheme_handler/module_scheme.rb +68 -9
  130. data/lib/puppet/pops/evaluator/access_operator.rb +27 -60
  131. data/lib/puppet/pops/evaluator/closure.rb +8 -8
  132. data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +1 -1
  133. data/lib/puppet/pops/evaluator/evaluator_impl.rb +10 -6
  134. data/lib/puppet/pops/evaluator/literal_evaluator.rb +87 -0
  135. data/lib/puppet/pops/evaluator/relationship_operator.rb +7 -1
  136. data/lib/puppet/pops/functions/dispatcher.rb +3 -3
  137. data/lib/puppet/pops/issues.rb +11 -3
  138. data/lib/puppet/pops/label_provider.rb +1 -1
  139. data/lib/puppet/pops/lookup/explainer.rb +402 -0
  140. data/lib/puppet/pops/lookup/invocation.rb +117 -0
  141. data/lib/puppet/pops/lookup.rb +25 -47
  142. data/lib/puppet/pops/merge_strategy.rb +73 -5
  143. data/lib/puppet/pops/model/factory.rb +38 -3
  144. data/lib/puppet/pops/model/model_label_provider.rb +10 -1
  145. data/lib/puppet/pops/model/model_meta.rb +19 -1
  146. data/lib/puppet/pops/model/model_tree_dumper.rb +18 -0
  147. data/lib/puppet/pops/parser/code_merger.rb +13 -1
  148. data/lib/puppet/pops/parser/egrammar.ra +65 -2
  149. data/lib/puppet/pops/parser/eparser.rb +1569 -1241
  150. data/lib/puppet/pops/parser/lexer2.rb +32 -1
  151. data/lib/puppet/pops/parser/locator.rb +1 -1
  152. data/lib/puppet/pops/parser/parser_support.rb +25 -13
  153. data/lib/puppet/pops/patterns.rb +3 -0
  154. data/lib/puppet/pops/types/enumeration.rb +1 -2
  155. data/lib/puppet/pops/types/type_asserter.rb +16 -15
  156. data/lib/puppet/pops/types/type_assertion_error.rb +1 -0
  157. data/lib/puppet/pops/types/type_calculator.rb +171 -1020
  158. data/lib/puppet/pops/types/type_factory.rb +87 -148
  159. data/lib/puppet/pops/types/type_mismatch_describer.rb +743 -0
  160. data/lib/puppet/pops/types/type_parser.rb +118 -129
  161. data/lib/puppet/pops/types/types.rb +1394 -255
  162. data/lib/puppet/pops/types/types_meta.rb +0 -234
  163. data/lib/puppet/pops/validation/checker4_0.rb +49 -1
  164. data/lib/puppet/pops/validation/validator_factory_4_0.rb +3 -1
  165. data/lib/puppet/pops/validation.rb +7 -2
  166. data/lib/puppet/pops.rb +19 -17
  167. data/lib/puppet/provider/augeas/augeas.rb +50 -0
  168. data/lib/puppet/provider/exec.rb +6 -1
  169. data/lib/puppet/provider/group/directoryservice.rb +10 -0
  170. data/lib/puppet/provider/package/dnf.rb +41 -0
  171. data/lib/puppet/provider/package/gem.rb +7 -2
  172. data/lib/puppet/provider/package/nim.rb +1 -1
  173. data/lib/puppet/provider/package/rpm.rb +1 -0
  174. data/lib/puppet/provider/package/windows/exe_package.rb +10 -8
  175. data/lib/puppet/provider/package/windows/msi_package.rb +4 -3
  176. data/lib/puppet/provider/package/windows/package.rb +9 -1
  177. data/lib/puppet/provider/package/yum.rb +20 -9
  178. data/lib/puppet/provider/service/bsd.rb +1 -1
  179. data/lib/puppet/provider/service/debian.rb +21 -0
  180. data/lib/puppet/provider/service/init.rb +6 -0
  181. data/lib/puppet/provider/service/launchd.rb +36 -7
  182. data/lib/puppet/provider/service/rcng.rb +51 -0
  183. data/lib/puppet/provider/service/redhat.rb +2 -1
  184. data/lib/puppet/provider/service/smf.rb +43 -2
  185. data/lib/puppet/provider/service/src.rb +27 -0
  186. data/lib/puppet/provider/service/systemd.rb +25 -5
  187. data/lib/puppet/provider/sshkey/parsed.rb +19 -9
  188. data/lib/puppet/provider/zone/solaris.rb +2 -2
  189. data/lib/puppet/reference/configuration.rb +10 -4
  190. data/lib/puppet/reference/report.rb +9 -12
  191. data/lib/puppet/reports.rb +5 -1
  192. data/lib/puppet/resource/capability_finder.rb +95 -0
  193. data/lib/puppet/resource/catalog.rb +47 -7
  194. data/lib/puppet/resource/status.rb +0 -2
  195. data/lib/puppet/resource/type.rb +238 -44
  196. data/lib/puppet/resource/type_collection.rb +60 -2
  197. data/lib/puppet/resource.rb +50 -73
  198. data/lib/puppet/settings/file_setting.rb +10 -9
  199. data/lib/puppet/settings.rb +2 -2
  200. data/lib/puppet/ssl/certificate_authority/interface.rb +2 -2
  201. data/lib/puppet/ssl/oids.rb +9 -1
  202. data/lib/puppet/transaction/additional_resource_generator.rb +71 -8
  203. data/lib/puppet/transaction/resource_harness.rb +9 -4
  204. data/lib/puppet/transaction.rb +8 -1
  205. data/lib/puppet/type/augeas.rb +8 -0
  206. data/lib/puppet/type/file/source.rb +14 -12
  207. data/lib/puppet/type/package.rb +9 -6
  208. data/lib/puppet/type/user.rb +4 -2
  209. data/lib/puppet/type.rb +78 -7
  210. data/lib/puppet/util/command_line.rb +4 -0
  211. data/lib/puppet/util/execution.rb +18 -2
  212. data/lib/puppet/util/tagging.rb +7 -1
  213. data/lib/puppet/util/windows/adsi.rb +5 -2
  214. data/lib/puppet/util/windows/security.rb +4 -1
  215. data/lib/puppet/util/windows/taskscheduler.rb +1 -1
  216. data/lib/puppet/util.rb +9 -1
  217. data/lib/puppet/version.rb +1 -1
  218. data/lib/puppet.rb +12 -0
  219. data/spec/fixtures/unit/application/environments/production/data/common.yaml +3 -0
  220. data/spec/fixtures/unit/application/environments/production/environment.conf +1 -0
  221. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/data/bad.json +3 -0
  222. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/environment.conf +2 -0
  223. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/hiera.yaml +5 -0
  224. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/manifests/site.pp +5 -0
  225. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/data/bad.yaml +3 -0
  226. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/environment.conf +2 -0
  227. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/hiera.yaml +5 -0
  228. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/manifests/site.pp +5 -0
  229. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/data/common.yaml +2 -0
  230. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/environment.conf +2 -0
  231. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/manifests/site.pp +1 -0
  232. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/data/common.yaml +2 -0
  233. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/manifests/init.pp +5 -0
  234. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/metadata.json +9 -0
  235. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/first.json +3 -0
  236. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/name.yaml +2 -0
  237. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/second.json +3 -0
  238. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/single.yaml +2 -0
  239. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data2/single.yaml +2 -0
  240. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/environment.conf +2 -0
  241. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/hiera.yaml +18 -0
  242. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/manifests/site.pp +5 -0
  243. data/spec/fixtures/unit/data_providers/environments/hiera_misc/data/common.yaml +46 -0
  244. data/spec/fixtures/unit/data_providers/environments/hiera_misc/environment.conf +2 -0
  245. data/spec/fixtures/unit/data_providers/environments/hiera_misc/manifests/site.pp +1 -0
  246. data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/data/common.yaml +30 -0
  247. data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/manifests/init.pp +13 -0
  248. data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/metadata.json +9 -0
  249. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/environment.conf +2 -0
  250. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/manifests/site.pp +1 -0
  251. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/first.json +3 -0
  252. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/name.yaml +1 -0
  253. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/second.json +3 -0
  254. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/single.yaml +2 -0
  255. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data2/single.yaml +2 -0
  256. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/hiera.yaml +18 -0
  257. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/manifests/init.pp +5 -0
  258. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/metadata.json +9 -0
  259. data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_env_data.rb +1 -0
  260. data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_module_data.rb +1 -0
  261. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/data/first.json +3 -0
  262. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/hiera.yaml +8 -0
  263. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/manifests/init.pp +5 -0
  264. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/metadata.json +9 -0
  265. data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/lib/puppet/functions/meta/data.rb +9 -0
  266. data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/manifests/init.pp +3 -0
  267. data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/metadata.json +9 -0
  268. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/lib/puppet/bindings/metawcp/default.rb +10 -0
  269. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/lib/puppet_x/thallgren/sample_module_data.rb +23 -0
  270. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/manifests/init.pp +3 -0
  271. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/metadata.json +9 -0
  272. data/spec/fixtures/unit/provider/package/yum/yum-check-update-security.txt +184 -0
  273. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_get/should_yield_to_the_block.yml +24 -0
  274. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_head/should_yield_to_the_block.yml +24 -0
  275. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_post/should_yield_to_the_block.yml +24 -0
  276. data/spec/integration/data_binding_spec.rb +229 -0
  277. data/spec/integration/file_bucket/file_spec.rb +2 -2
  278. data/spec/integration/parser/compiler_spec.rb +30 -24
  279. data/spec/integration/parser/resource_expressions_spec.rb +4 -4
  280. data/spec/integration/parser/undef_param_spec.rb +1 -1
  281. data/spec/integration/provider/package_spec.rb +3 -1
  282. data/spec/integration/resource/catalog_spec.rb +1 -1
  283. data/spec/integration/ssl/certificate_authority_spec.rb +0 -1
  284. data/spec/integration/ssl/certificate_request_spec.rb +0 -1
  285. data/spec/integration/ssl/certificate_revocation_list_spec.rb +0 -1
  286. data/spec/integration/ssl/host_spec.rb +0 -1
  287. data/spec/integration/type/package_spec.rb +2 -0
  288. data/spec/integration/util/rdoc/parser_spec.rb +1 -1
  289. data/spec/integration/util/windows/security_spec.rb +18 -0
  290. data/spec/lib/matchers/include_in_order.rb +2 -2
  291. data/spec/shared_behaviours/iterative_functions.rb +8 -8
  292. data/spec/spec_helper.rb +7 -0
  293. data/spec/unit/agent/locker_spec.rb +4 -4
  294. data/spec/unit/agent_spec.rb +0 -8
  295. data/spec/unit/application/agent_spec.rb +5 -0
  296. data/spec/unit/application/apply_spec.rb +9 -1
  297. data/spec/unit/application/filebucket_spec.rb +88 -2
  298. data/spec/unit/application/lookup_spec.rb +195 -0
  299. data/spec/unit/application/master_spec.rb +2 -2
  300. data/spec/unit/application_spec.rb +3 -3
  301. data/spec/unit/appmgmt_spec.rb +657 -0
  302. data/spec/unit/capability_spec.rb +414 -0
  303. data/spec/unit/configurer_spec.rb +7 -1
  304. data/spec/unit/context/trusted_information_spec.rb +24 -1
  305. data/spec/unit/daemon_spec.rb +18 -8
  306. data/spec/unit/data_providers/hiera_data_provider_spec.rb +201 -0
  307. data/spec/unit/environments_spec.rb +2 -0
  308. data/spec/unit/face/node_spec.rb +1 -1
  309. data/spec/unit/file_bucket/dipper_spec.rb +210 -1
  310. data/spec/unit/file_serving/configuration_spec.rb +1 -1
  311. data/spec/unit/file_system_spec.rb +20 -0
  312. data/spec/unit/functions/assert_type_spec.rb +5 -7
  313. data/spec/unit/functions/defined_spec.rb +2 -2
  314. data/spec/unit/functions/epp_spec.rb +2 -2
  315. data/spec/unit/functions/filter_spec.rb +18 -0
  316. data/spec/unit/functions/hiera_spec.rb +2 -2
  317. data/spec/unit/functions/lookup_spec.rb +200 -9
  318. data/spec/unit/functions/regsubst_spec.rb +17 -8
  319. data/spec/unit/functions/scanf_spec.rb +1 -1
  320. data/spec/unit/functions/split_spec.rb +2 -2
  321. data/spec/unit/functions/versioncmp_spec.rb +36 -0
  322. data/spec/unit/functions4_spec.rb +58 -72
  323. data/spec/unit/graph/sequential_prioritizer_spec.rb +1 -1
  324. data/spec/unit/indirector/catalog/compiler_spec.rb +28 -8
  325. data/spec/unit/indirector/catalog/static_compiler_spec.rb +38 -20
  326. data/spec/unit/indirector/data_binding/none_spec.rb +2 -2
  327. data/spec/unit/indirector/file_bucket_file/file_spec.rb +52 -1
  328. data/spec/unit/indirector/indirection_spec.rb +13 -2
  329. data/spec/unit/indirector/request_spec.rb +8 -8
  330. data/spec/unit/indirector/ssl_file_spec.rb +1 -1
  331. data/spec/unit/indirector/yaml_spec.rb +1 -1
  332. data/spec/unit/info_service_spec.rb +236 -0
  333. data/spec/unit/module_tool/application_spec.rb +1 -1
  334. data/spec/unit/module_tool/applications/builder_spec.rb +1 -1
  335. data/spec/unit/module_tool/metadata_spec.rb +31 -2
  336. data/spec/unit/network/authconfig_spec.rb +62 -32
  337. data/spec/unit/network/authorization_spec.rb +30 -2
  338. data/spec/unit/network/authstore_spec.rb +1 -1
  339. data/spec/unit/network/http/compression_spec.rb +1 -1
  340. data/spec/unit/network/http/connection_spec.rb +14 -19
  341. data/spec/unit/network/http/handler_spec.rb +0 -5
  342. data/spec/unit/network/rights_spec.rb +3 -3
  343. data/spec/unit/node_spec.rb +27 -0
  344. data/spec/unit/parser/ast/leaf_spec.rb +1 -1
  345. data/spec/unit/parser/compiler_spec.rb +86 -2
  346. data/spec/unit/parser/functions/create_resources_spec.rb +1 -1
  347. data/spec/unit/parser/resource_spec.rb +2 -20
  348. data/spec/unit/pops/binder/config/binder_config_spec.rb +1 -1
  349. data/spec/unit/pops/binder/injector_spec.rb +3 -3
  350. data/spec/unit/pops/evaluator/access_ops_spec.rb +13 -11
  351. data/spec/unit/pops/evaluator/basic_expressions_spec.rb +1 -2
  352. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +20 -11
  353. data/spec/unit/pops/evaluator/literal_evaluator_spec.rb +43 -0
  354. data/spec/unit/pops/label_provider_spec.rb +5 -1
  355. data/spec/unit/pops/parser/lexer2_spec.rb +39 -0
  356. data/spec/unit/pops/parser/parse_application_spec.rb +40 -0
  357. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +4 -0
  358. data/spec/unit/pops/parser/parse_capabilities_spec.rb +47 -0
  359. data/spec/unit/pops/parser/parse_site_spec.rb +38 -0
  360. data/spec/unit/pops/parser/parser_rspec_helper.rb +5 -0
  361. data/spec/unit/pops/parser/parser_spec.rb +18 -0
  362. data/spec/unit/pops/types/type_calculator_spec.rb +427 -444
  363. data/spec/unit/pops/types/type_factory_spec.rb +12 -12
  364. data/spec/unit/pops/types/type_parser_spec.rb +15 -12
  365. data/spec/unit/pops/validator/validator_spec.rb +68 -0
  366. data/spec/unit/property_spec.rb +1 -1
  367. data/spec/unit/provider/augeas/augeas_spec.rb +50 -0
  368. data/spec/unit/provider/group/directoryservice_spec.rb +33 -0
  369. data/spec/unit/provider/group/windows_adsi_spec.rb +3 -0
  370. data/spec/unit/provider/package/dnf_spec.rb +92 -0
  371. data/spec/unit/provider/package/gem_spec.rb +7 -0
  372. data/spec/unit/provider/package/nim_spec.rb +6 -6
  373. data/spec/unit/provider/package/rpm_spec.rb +25 -2
  374. data/spec/unit/provider/package/windows/package_spec.rb +41 -0
  375. data/spec/unit/provider/package/yum_spec.rb +35 -12
  376. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +10 -0
  377. data/spec/unit/provider/service/debian_spec.rb +28 -0
  378. data/spec/unit/provider/service/gentoo_spec.rb +1 -0
  379. data/spec/unit/provider/service/init_spec.rb +6 -0
  380. data/spec/unit/provider/service/launchd_spec.rb +85 -10
  381. data/spec/unit/provider/service/openrc_spec.rb +1 -0
  382. data/spec/unit/provider/service/rcng_spec.rb +41 -0
  383. data/spec/unit/provider/service/redhat_spec.rb +8 -1
  384. data/spec/unit/provider/service/smf_spec.rb +30 -5
  385. data/spec/unit/provider/service/src_spec.rb +20 -4
  386. data/spec/unit/provider/service/systemd_spec.rb +79 -29
  387. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +1 -1
  388. data/spec/unit/provider/sshkey/parsed_spec.rb +23 -0
  389. data/spec/unit/provider/user/windows_adsi_spec.rb +2 -1
  390. data/spec/unit/provider/zone/solaris_spec.rb +19 -0
  391. data/spec/unit/reports_spec.rb +10 -0
  392. data/spec/unit/resource/capability_finder_spec.rb +56 -0
  393. data/spec/unit/resource/catalog_spec.rb +31 -8
  394. data/spec/unit/resource/type_collection_spec.rb +23 -2
  395. data/spec/unit/resource/type_spec.rb +1 -1
  396. data/spec/unit/resource_spec.rb +23 -5
  397. data/spec/unit/settings/file_setting_spec.rb +31 -0
  398. data/spec/unit/settings_spec.rb +91 -2
  399. data/spec/unit/ssl/certificate_authority/interface_spec.rb +4 -3
  400. data/spec/unit/ssl/certificate_authority_spec.rb +5 -3
  401. data/spec/unit/ssl/host_spec.rb +2 -2
  402. data/spec/unit/ssl/oids_spec.rb +8 -0
  403. data/spec/unit/transaction/additional_resource_generator_spec.rb +78 -5
  404. data/spec/unit/transaction/report_spec.rb +24 -1
  405. data/spec/unit/transaction_spec.rb +7 -0
  406. data/spec/unit/type/exec_spec.rb +16 -8
  407. data/spec/unit/type/host_spec.rb +4 -4
  408. data/spec/unit/type/package_spec.rb +1 -0
  409. data/spec/unit/type/tidy_spec.rb +4 -4
  410. data/spec/unit/type/user_spec.rb +14 -7
  411. data/spec/unit/type/vlan_spec.rb +1 -1
  412. data/spec/unit/type_spec.rb +1 -1
  413. data/spec/unit/util/ldap/generator_spec.rb +1 -1
  414. data/spec/unit/util/network_device/cisco/device_spec.rb +1 -1
  415. data/spec/unit/util/network_device/transport/ssh_spec.rb +1 -1
  416. data/spec/unit/util/network_device_spec.rb +1 -1
  417. data/spec/unit/util/storage_spec.rb +5 -1
  418. data/spec/unit/util/windows/adsi_spec.rb +13 -0
  419. data/spec/unit/util_spec.rb +21 -2
  420. metadata +173 -7
  421. data/lib/puppet/pops/evaluator/callable_mismatch_describer.rb +0 -175
  422. data/spec/integration/data_binding.rb +0 -104
@@ -1,30 +1,9 @@
1
1
  module Puppet::DataProviders::DataFunctionSupport
2
- # Gets the data from the compiler, or initializes it from a function call if not present in the compiler.
3
- # This means, that the function providing the data is called once per compilation, and the data is cached for
4
- # as long as the compiler lives (which is for one catalog production).
5
- # This makes it possible to return data that is tailored for the request.
6
- # The class including this module must implement `loader(scope)` to return the apropriate loader.
7
- #
8
- # If a block is given, it will be called to validate the data hash when it is retrieved from a function call. The
9
- # block must return the validated data or raise a {Puppet::Error} to indicate that the data is invalid.
10
- # The block is not called when the data is found in the compiler or in the cache.
11
- #
12
- # @param key [String] The data key such as the name of a module or the constant 'environment'
13
- # @param scope [Parser::Scope] The scope
14
- # @return [Hash] The data hash for the given _key_
15
- # @yield An optional block that can be used for validation of the data returned from the function
16
- # @yieldparam [Hash] data The data to validate
17
- # @yieldreturn [Hash] The validated data
18
- #
19
- def data(key, scope, &block)
20
- compiler = scope.compiler
21
- adapter = Puppet::DataProviders::DataAdapter.get(compiler) || Puppet::DataProviders::DataAdapter.adapt(compiler)
22
- adapter.data[key] ||= initialize_data_from_function("#{key}::data", key, scope, &block)
23
- end
24
-
25
- def initialize_data_from_function(name, key, scope)
2
+ def initialize_data(data_key, lookup_invocation)
3
+ name = "#{data_key}::data"
4
+ scope = lookup_invocation.scope
26
5
  Puppet::Util::Profiler.profile("Called #{name}", [ :functions, name ]) do
27
- loader = loader(key, scope)
6
+ loader = loader(data_key, scope)
28
7
  if loader && func = loader.load(:function, name)
29
8
  # function found, call without arguments, must return a Hash
30
9
  # TODO: Validate the function - to ensure it does not contain unwanted side effects
@@ -37,7 +16,7 @@ module Puppet::DataProviders::DataFunctionSupport
37
16
  # validate result if block given
38
17
  result = yield(result) if block_given?
39
18
  else
40
- raise Puppet::Error.new("Data from 'function' cannot find the required '#{name}' function")
19
+ raise Puppet::Error.new("Cannot find the function '#{name}' - required when using 'function' data provider scheme")
41
20
  end
42
21
  result
43
22
  end
@@ -11,16 +11,6 @@ module Puppet::DataProviders; end
11
11
  class Puppet::DataProviders::FunctionEnvDataProvider < Puppet::Plugins::DataProviders::EnvironmentDataProvider
12
12
  include Puppet::DataProviders::DataFunctionSupport
13
13
 
14
- def lookup(name, scope, merge)
15
- begin
16
- hash = data('environment', scope)
17
- throw :no_such_key unless hash.include?(name)
18
- hash[name]
19
- rescue *Puppet::Error => detail
20
- raise Puppet::DataBinding::LookupError.new(detail.message, detail)
21
- end
22
- end
23
-
24
14
  def loader(key, scope)
25
15
  # This loader allows the data function to be private or public in the environment
26
16
  scope.compiler.loaders.private_environment_loader
@@ -9,30 +9,8 @@ module Puppet::DataProviders; end
9
9
  # is only produced once per compilation.
10
10
  #
11
11
  class Puppet::DataProviders::FunctionModuleDataProvider < Puppet::Plugins::DataProviders::ModuleDataProvider
12
- MODULE_NAME = 'module_name'.freeze
13
12
  include Puppet::DataProviders::DataFunctionSupport
14
13
 
15
- def lookup(name, scope, merge)
16
- # Do not attempt to do a lookup in a module unless the name is qualified.
17
- qual_index = name.index('::')
18
- throw :no_such_key if qual_index.nil?
19
- module_name = name[0..qual_index-1]
20
- begin
21
- hash = data(module_name, scope) do | data |
22
- module_prefix = "#{module_name}::"
23
- data.each_pair do |k,v|
24
- unless k.is_a?(String) && k.start_with?(module_prefix)
25
- raise Puppet::Error, "Module data for module '#{module_name}' must use keys qualified with the name of the module"
26
- end
27
- end
28
- end
29
- throw :no_such_key unless hash.include?(name)
30
- hash[name]
31
- rescue *Puppet::Error => detail
32
- raise Puppet::DataBinding::LookupError.new(detail.message, detail)
33
- end
34
- end
35
-
36
14
  def loader(key, scope)
37
15
  scope.compiler.loaders.private_loader_for_module(key)
38
16
  end
@@ -0,0 +1,106 @@
1
+ require 'pathname'
2
+ require_relative 'hiera_interpolate'
3
+
4
+ module Puppet::DataProviders
5
+ class HieraConfig
6
+ include Puppet::Plugins::DataProviders
7
+ include HieraInterpolate
8
+
9
+ DEFAULT_CONFIG = {
10
+ 'version' => 4,
11
+ 'datadir' => 'data',
12
+ 'hierarchy' => [
13
+ {
14
+ 'name' => 'common',
15
+ 'backend' => 'yaml'
16
+ }
17
+ ]
18
+ }.freeze
19
+
20
+ def self.config_type
21
+ @@CONFIG_TYPE ||= create_config_type
22
+ end
23
+
24
+ def self.symkeys_to_string(struct)
25
+ case(struct)
26
+ when Hash
27
+ Hash[struct.map { |k,v| [k.to_s, symkeys_to_string(v)] }]
28
+ when Array
29
+ struct.map { |v| symkeys_to_string(v) }
30
+ else
31
+ struct
32
+ end
33
+ end
34
+
35
+ def self.create_config_type
36
+ hierarchy_elem_type_base = 'Struct[{'\
37
+ 'backend=>String[1],'\
38
+ 'name=>String[1],'\
39
+ 'datadir=>Optional[String[1]]'
40
+
41
+ hierarchy_elem_type_v1 = hierarchy_elem_type_base + ',path=>String[1]}]'
42
+ hierarchy_elem_type_v2 = hierarchy_elem_type_base + ',paths=>Array[String[1]]}]'
43
+ hierarchy_elem_type_v3 = hierarchy_elem_type_base + '}]'
44
+
45
+ Puppet::Pops::Types::TypeParser.new.parse('Struct[{'\
46
+ 'version=>Integer[4],'\
47
+ "hierarchy=>Optional[Array[Variant[#{hierarchy_elem_type_v1},#{hierarchy_elem_type_v2},#{hierarchy_elem_type_v3}]]],"\
48
+ 'datadir=>Optional[String[1]]}]')
49
+ end
50
+ private_class_method :create_config_type
51
+
52
+ attr_reader :config_path, :version
53
+
54
+ # Creates a new HieraConfig from the given _config_root_. This is where the 'hiera.yaml' is expected to be found
55
+ # and is also the base location used when resolving relative paths.
56
+ #
57
+ # @param config_root [Pathname] Absolute path to the configuration root
58
+ # @api public
59
+ def initialize(config_root)
60
+ @config_root = config_root
61
+ @config_path = config_root + 'hiera.yaml'
62
+ if @config_path.exist?
63
+ @config = validate_config(HieraConfig.symkeys_to_string(YAML.load_file(@config_path)))
64
+ @config['hierarchy'] ||= DEFAULT_CONFIG['hierarchy']
65
+ @config['datadir'] ||= DEFAULT_CONFIG['datadir']
66
+ else
67
+ @config = DEFAULT_CONFIG
68
+ end
69
+ @version = @config['version']
70
+ end
71
+
72
+ def create_data_providers(lookup_invocation)
73
+ injector = Puppet.lookup(:injector)
74
+ service_type = Registry.hash_of_path_based_data_provider_factories
75
+ default_datadir = @config['datadir']
76
+
77
+ # Hashes enumerate their values in the order that the corresponding keys were inserted so it's safe to use
78
+ # a hash for the data_providers.
79
+ data_providers = {}
80
+ @config['hierarchy'].each do |he|
81
+ name = he['name']
82
+ raise Puppet::DataBinding::LookupError, "#{path}: Name '#{name}' defined more than once" if data_providers.include?(name)
83
+ original_paths = he['paths']
84
+ if original_paths.nil?
85
+ single_path = he['path']
86
+ single_path = name if single_path.nil?
87
+ original_paths = [single_path]
88
+ end
89
+ paths = original_paths.map { |path| interpolate(path, lookup_invocation, false)}
90
+ provider_name = he['backend']
91
+ provider_factory = injector.lookup(nil, service_type, PATH_BASED_DATA_PROVIDER_FACTORIES_KEY)[provider_name]
92
+ raise Puppet::DataBinding::LookupError, "#{@config_path}: No data provider is registered for backend '#{provider_name}' " unless provider_factory
93
+
94
+ datadir = @config_root + (he['datadir'] || default_datadir)
95
+ resolved_paths = provider_factory.resolve_paths(datadir, original_paths, paths, lookup_invocation)
96
+ data_providers[name] = provider_factory.create(name, resolved_paths)
97
+ end
98
+ data_providers.values
99
+ end
100
+
101
+ def validate_config(hiera_config)
102
+ Puppet::Pops::Types::TypeAsserter.assert_instance_of(@config_path, self.class.config_type, hiera_config)
103
+ end
104
+ private :validate_config
105
+ end
106
+ end
@@ -0,0 +1,18 @@
1
+ # This file is loaded by the autoloader, and it does not find the hiera support unless required relative
2
+ require_relative 'hiera_support'
3
+
4
+ module Puppet::DataProviders
5
+ class HieraEnvDataProvider < Puppet::Plugins::DataProviders::EnvironmentDataProvider
6
+ include HieraSupport
7
+
8
+ # Return the root of the environment found in the given _scope_
9
+ #
10
+ # @param data_key [String] not used
11
+ # @param scope [Puppet::Parser::Scope] the parser scope where the environment is found
12
+ # @return [Pathname] Path to root of the environment
13
+ def provider_root(_, scope)
14
+ Pathname.new(scope.environment.configuration.path_to_env)
15
+ end
16
+ protected :provider_root
17
+ end
18
+ end
@@ -0,0 +1,97 @@
1
+ require_relative 'hiera_config'
2
+
3
+ # Add support for Hiera-like interpolation expressions. The expressions may contain keys that uses dot-notation
4
+ # to further navigate into hashes and arrays
5
+ #
6
+ module Puppet::DataProviders::HieraInterpolate
7
+ def interpolate(subject, lookup_invocation, allow_methods)
8
+ return subject unless subject.is_a?(String) && !subject.index('%{').nil?
9
+
10
+ lookup_invocation.with(:interpolate, subject) do
11
+ subject.gsub(/%\{([^\}]+)\}/) do |match|
12
+ method_key, key = get_method_and_data($1, allow_methods)
13
+ is_alias = method_key == 'alias'
14
+
15
+ # Alias is only permitted if the entire string is equal to the interpolate expression
16
+ raise Puppet::DataBinding::LookupError, "'alias' interpolation is only permitted if the expression is equal to the entire string" if is_alias && subject != match
17
+
18
+ segments = key.split('.')
19
+ value = interpolate_method(method_key).call(segments[0], lookup_invocation)
20
+ value = qualified_lookup(segments.drop(1), value) if segments.size > 1
21
+ value = lookup_invocation.check(key) { interpolate(value, lookup_invocation, allow_methods) } if value.is_a?(String)
22
+
23
+ # break gsub and return value immediately if this was an alias substitution. The value might be something other than a String
24
+ return value if is_alias
25
+
26
+ value || ''
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def interpolate_method(method_key)
34
+ @@interpolate_methods ||= begin
35
+ global_lookup = lambda { |key, lookup_invocation| Puppet::Pops::Lookup.lookup(key, nil, '', true, nil, lookup_invocation) }
36
+ scope_lookup = lambda do |key, lookup_invocation|
37
+ lookup_invocation.with(:scope, nil) do
38
+ ovr = lookup_invocation.override_values
39
+ if ovr.include?(key)
40
+ lookup_invocation.report_found_in_overrides(key, ovr[key])
41
+ else
42
+ scope = lookup_invocation.scope
43
+ if scope.include?(key)
44
+ lookup_invocation.report_found(key, scope[key])
45
+ else
46
+ defaults = lookup_invocation.default_values
47
+ if defaults.include?(key)
48
+ lookup_invocation.report_found_in_defaults(key, defaults[key])
49
+ else
50
+ nil
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+
58
+ {
59
+ 'lookup' => global_lookup,
60
+ 'hiera' => global_lookup, # this is just an alias for 'lookup'
61
+ 'alias' => global_lookup, # same as 'lookup' but expression must be entire string. The result that is not subject to string substitution
62
+ 'scope' => scope_lookup,
63
+ 'literal' => lambda { |key, _| key }
64
+ }
65
+ end
66
+ interpolate_method = @@interpolate_methods[method_key]
67
+ raise Puppet::DataBinding::LookupError, "Unknown interpolation method '#{method_key}'" unless interpolate_method
68
+ interpolate_method
69
+ end
70
+
71
+ def qualified_lookup(segments, value)
72
+ segments.each do |segment|
73
+ throw :no_such_key if value.nil?
74
+ if segment =~ /^[0-9]+$/
75
+ segment = segment.to_i
76
+ raise Puppet::DataBinding::LookupError, "Data provider type mismatch: Got #{value.class.name} when Array was expected to enable lookup using key '#{segment}'" unless value.instance_of?(Array)
77
+ throw :no_such_key unless segment < value.size
78
+ else
79
+ raise Puppet::DataBinding::LookupError, "Data provider type mismatch: Got #{value.class.name} when a non Array object that responds to '[]' was expected to enable lookup using key '#{segment}'" unless value.respond_to?(:'[]') && !value.instance_of?(Array)
80
+ throw :no_such_key unless value.include?(segment)
81
+ end
82
+ value = value[segment]
83
+ end
84
+ value
85
+ end
86
+
87
+ def get_method_and_data(data, allow_methods)
88
+ if match = data.match(/^(\w+)\((?:["]([^"]+)["]|[']([^']+)['])\)$/)
89
+ raise Puppet::DataBinding::LoookupError, 'Interpolation using method syntax is not allowed in this context' unless allow_methods
90
+ key = match[1]
91
+ data = match[2] || match[3] # double or single qouted
92
+ else
93
+ key = 'scope'
94
+ end
95
+ [key, data]
96
+ end
97
+ end
@@ -0,0 +1,23 @@
1
+ # This file is loaded by the autoloader, and it does not find the hiera support unless required relative
2
+ require_relative 'hiera_support'
3
+
4
+ module Puppet::DataProviders
5
+ class HieraModuleDataProvider < Puppet::Plugins::DataProviders::ModuleDataProvider
6
+ include HieraSupport
7
+
8
+ # Return the root of the module with the name equal to _data_key_ found in the environment of the given _scope_
9
+ #
10
+ # @param data_key [String] the name of the module
11
+ # @param scope [Puppet::Parser::Scope] the parser scope where the environment is found
12
+ # @return [Pathname] Path to root of the environment
13
+ # @raise [Puppet::DataBinder::LookupError] if the given module is can not be found
14
+ #
15
+ def provider_root(module_name, scope)
16
+ env = scope.environment
17
+ mod = env.modules.find { |m| m.name == module_name }
18
+ raise Puppet::DataBinder::LookupError, "Environment '#{env.name}', cannot find module '#{module_name}'" unless mod
19
+ Pathname.new(mod.path)
20
+ end
21
+ protected :provider_root
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'hiera_config'
2
+
3
+ module Puppet::DataProviders::HieraSupport
4
+ def config_path
5
+ @hiera_config.nil? ? 'not yet configured' : @hiera_config.config_path
6
+ end
7
+
8
+ def name
9
+ 'Hiera Data Provider' + (@hiera_config.nil? ? '' : ", version #{@hiera_config.version}")
10
+ end
11
+
12
+ # Performs a lookup by searching all given paths for the given _key_. A merge will be performed if
13
+ # the value is found in more than one location and _merge_ is not nil.
14
+ #
15
+ # @param key [String] The key to lookup
16
+ # @param lookup_invocation [Puppet::Pops::Lookup::Invocation] The current lookup invocation
17
+ # @param merge [Puppet::Pops::MergeStrategy,String,Hash<String,Object>,nil] Merge strategy or hash with strategy and options
18
+ #
19
+ # @api public
20
+ def unchecked_lookup(key, lookup_invocation, merge)
21
+ lookup_invocation.with(:data_provider, self) do
22
+ merge_strategy = Puppet::Pops::MergeStrategy.strategy(merge)
23
+ lookup_invocation.with(:merge, merge_strategy) do
24
+ merged_result = merge_strategy.merge_lookup(data_providers(data_key(key, lookup_invocation), lookup_invocation)) do |data_provider|
25
+ data_provider.unchecked_lookup(key, lookup_invocation, merge_strategy)
26
+ end
27
+ lookup_invocation.report_result(merged_result)
28
+ end
29
+ end
30
+ end
31
+
32
+ def data_providers(data_key, lookup_invocation)
33
+ @hiera_config ||= Puppet::DataProviders::HieraConfig.new(provider_root(data_key, lookup_invocation.scope))
34
+ @data_providers ||= @hiera_config.create_data_providers(lookup_invocation)
35
+ end
36
+ private :data_providers
37
+ end
@@ -0,0 +1,31 @@
1
+ # This file is loaded by the autoloader, and it does not find the data function support unless required relative
2
+ #
3
+ require 'json'
4
+ require_relative 'hiera_interpolate'
5
+
6
+ module Puppet::DataProviders
7
+ class JsonDataProviderFactory < Puppet::Plugins::DataProviders::FileBasedDataProviderFactory
8
+ def create(name, paths)
9
+ JsonDataProvider.new(name, paths)
10
+ end
11
+
12
+ def path_extension
13
+ '.json'
14
+ end
15
+ end
16
+
17
+ class JsonDataProvider < Puppet::Plugins::DataProviders::PathBasedDataProvider
18
+ include HieraInterpolate
19
+
20
+ def initialize_data(path, lookup_invocation)
21
+ JSON.parse(File.read(path))
22
+ rescue JSON::ParserError => ex
23
+ # Filename not included in message, so we add it here.
24
+ raise Puppet::DataBinding::LookupError, "Unable to parse (#{path}): #{ex.message}"
25
+ end
26
+
27
+ def post_process(value, lookup_invocation)
28
+ interpolate(value, lookup_invocation, true)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,200 @@
1
+ # A LookupAdapter is a specialized DataAdapter that uses its hash to store module providers. It also remembers the environment
2
+ # that it is attached to and maintains a cache of _lookup options_ retrieved from its data providers.
3
+ #
4
+ class Puppet::DataProviders::LookupAdapter < Puppet::DataProviders::DataAdapter
5
+
6
+ LOOKUP_OPTIONS = 'lookup_options'.freeze
7
+ HASH = 'hash'.freeze
8
+ MERGE = 'merge'.freeze
9
+
10
+ def self.create_adapter(env)
11
+ new(env)
12
+ end
13
+
14
+ def initialize(env)
15
+ super()
16
+ @env = env
17
+ @lookup_options = {}
18
+ end
19
+
20
+ # Performs a lookup using global, environment, and module data providers. Merge the result using the given
21
+ # _merge_ strategy. If the merge strategy is nil, then an attempt is made to find merge options in the
22
+ # `lookup_options` hash for an entry associated with the key. If no options are found, the no merge is performed
23
+ # and the first found entry is returned.
24
+ #
25
+ # @param key [String] The key to lookup
26
+ # @param merge [Puppet::Pops::MergeStrategy,String,Hash<String,Object>,nil] Merge strategy or hash with strategy and options
27
+ # @param lookup_invocation [Puppet::Pops::Lookup::Invocation] Invocation data containing scope, overrides, and defaults
28
+ # @return [Object] The found value
29
+ # @throws :no_such_key if the given key is not found
30
+ #
31
+ def lookup(key, lookup_invocation, merge)
32
+ merge = lookup_merge_options(key, lookup_invocation) if merge.nil?
33
+ merge_strategy = Puppet::Pops::MergeStrategy.strategy(merge)
34
+ lookup_invocation.with(:merge, merge_strategy) do
35
+ result = merge_strategy.merge_lookup([:lookup_global, :lookup_in_environment, :lookup_in_module]) { |m| send(m, key, lookup_invocation, merge_strategy) }
36
+ lookup_invocation.report_result(result)
37
+ result
38
+ end
39
+ end
40
+
41
+ # @api private
42
+ def lookup_global(name, lookup_invocation, merge_strategy)
43
+ terminus = Puppet[:data_binding_terminus]
44
+ lookup_invocation.with(:global, terminus) do
45
+ catch(:no_such_key) do
46
+ return lookup_invocation.report_found(name, Puppet::DataBinding.indirection.find(name,
47
+ { :environment => @env.to_s, :variables => lookup_invocation.scope, :merge => merge_strategy }))
48
+ end
49
+ lookup_invocation.report_not_found(name)
50
+ throw :no_such_key
51
+ end
52
+ rescue Puppet::DataBinding::LookupError => e
53
+ raise Puppet::Error.new("Error from DataBinding '#{terminus}' while looking up '#{name}': #{e.message}", e)
54
+ end
55
+
56
+ # @api private
57
+ def lookup_in_environment(name, lookup_invocation, merge_strategy)
58
+ env_provider.lookup(name, lookup_invocation, merge_strategy)
59
+ end
60
+
61
+ # @api private
62
+ def lookup_in_module(name, lookup_invocation, merge_strategy)
63
+ module_name = extract_module_name(name)
64
+
65
+ # Do not attempt to do a lookup in a module unless the name is qualified.
66
+ throw :no_such_key if module_name.nil?
67
+
68
+ lookup_invocation.with(:module, module_name) do
69
+ if @env.module(module_name).nil?
70
+ lookup_invocation.report_module_not_found
71
+ throw :no_such_key
72
+ end
73
+ module_provider(module_name).lookup(name, lookup_invocation, merge_strategy)
74
+ end
75
+ end
76
+
77
+ # Retrieve the merge options that match the given `name`.
78
+ #
79
+ # @param name [String] The key for which we want merge options
80
+ # @param lookup_invocation [Puppet::Pops::Lookup::Invocation] the lookup invocation
81
+ # @return [String,Hash,nil] The found merge options or nil
82
+ #
83
+ def lookup_merge_options(name, lookup_invocation)
84
+ lookup_options = lookup_lookup_options(name, lookup_invocation)
85
+ lookup_options.nil? ? nil : lookup_options[MERGE]
86
+ end
87
+
88
+ # Retrieve the lookup options that match the given `name`.
89
+ #
90
+ # @param name [String] The key for which we want lookup options
91
+ # @param lookup_invocation [Puppet::Pops::Lookup::Invocation] the lookup invocation
92
+ # @return [String,Hash,nil] The found lookup options or nil
93
+ #
94
+ def lookup_lookup_options(name, lookup_invocation)
95
+ module_name = extract_module_name(name)
96
+
97
+ # Retrieve the options for the module. We use nil as a key in case we have none
98
+ options = @lookup_options[module_name]
99
+ if options.nil? && !@lookup_options.include?(module_name)
100
+ options = retrieve_lookup_options(module_name, lookup_invocation, Puppet::Pops::MergeStrategy.strategy(HASH))
101
+ raise Puppet::DataBinding::LookupError.new("value of #{LOOKUP_OPTIONS} must be a hash") unless options.nil? || options.is_a?(Hash)
102
+ @lookup_options[module_name] = options
103
+ end
104
+ options.nil? ? nil : options[name]
105
+ end
106
+
107
+ private
108
+
109
+ # Retrieve lookup options that applies when using a specific module (i.e. a merge of the pre-cached
110
+ # `env_lookup_options` and the module specific data)
111
+ def retrieve_lookup_options(module_name, lookup_invocation, merge_strategy)
112
+ lookup_invocation.with(:meta, module_name) do
113
+ env_opts = env_lookup_options(lookup_invocation, merge_strategy)
114
+ options = nil
115
+ unless module_name.nil?
116
+ catch(:no_such_key) do
117
+ options = module_provider(module_name).lookup(LOOKUP_OPTIONS, lookup_invocation, merge_strategy)
118
+ options = merge_strategy.merge(env_opts, options) unless env_opts.nil?
119
+ end
120
+ end
121
+ options.nil? ? env_opts : options
122
+ end
123
+ end
124
+
125
+ # Retrieve and cache lookup options specific to the environment that this adapter is attached to (i.e. a merge
126
+ # of global and environment lookup options).
127
+ def env_lookup_options(lookup_invocation, merge_strategy)
128
+ unless instance_variable_defined?(:@env_lookup_options)
129
+ @env_lookup_options = nil
130
+ catch(:no_such_key) do
131
+ @env_lookup_options = merge_strategy.merge_lookup([:lookup_global, :lookup_in_environment]) do |m|
132
+ send(m, LOOKUP_OPTIONS, lookup_invocation, merge_strategy)
133
+ end
134
+ end
135
+ end
136
+ @env_lookup_options
137
+ end
138
+
139
+ def env_provider
140
+ @env_provider ||= initialize_env_provider
141
+ end
142
+
143
+ def module_provider(module_name)
144
+ # Test if the key is present for the given module_name. It might be there even if the
145
+ # value is nil (which indicates that no module provider is configured for the given name)
146
+ unless data.include?(module_name)
147
+ data[module_name] = initialize_module_provider(module_name)
148
+ end
149
+ data[module_name]
150
+ end
151
+
152
+ def initialize_module_provider(module_name)
153
+ injector = Puppet.lookup(:injector) { nil }
154
+
155
+ # Support running tests without an injector being configured == using a null implementation
156
+ return ModuleDataProvider.new() unless injector
157
+
158
+ # Get the registry of module to provider implementation name
159
+ module_service_type = Registry.hash_of_per_module_data_provider
160
+ module_service_name = PER_MODULE_DATA_PROVIDER_KEY
161
+ module_service = injector.lookup(nil, module_service_type, module_service_name)
162
+ provider_name = module_service[module_name] || 'none'
163
+
164
+ service_type = Registry.hash_of_module_data_providers
165
+ service_name = MODULE_DATA_PROVIDERS_KEY
166
+
167
+ # Get the service (registry of known implementations)
168
+ service = injector.lookup(nil, service_type, service_name)
169
+ provider = service[provider_name]
170
+ unless provider
171
+ raise Puppet::Error.new("Environment '#{@env.name}', cannot find module_data_provider '#{provider_name}'")
172
+ end
173
+ provider
174
+ end
175
+
176
+ def initialize_env_provider
177
+ injector = Puppet.lookup(:injector) { nil }
178
+
179
+ # Support running tests without an injector being configured == using a null implementation
180
+ return EnvironmentDataProvider.new() unless injector
181
+
182
+ # Get the name of the data provider from the environment's configuration and find the bound implementation
183
+ provider_name = @env.configuration.environment_data_provider
184
+ service_type = Registry.hash_of_environment_data_providers
185
+ service_name = ENV_DATA_PROVIDERS_KEY
186
+
187
+ # Get the service (registry of known implementations)
188
+ service = injector.lookup(nil, service_type, service_name)
189
+ provider = service[provider_name]
190
+ unless provider
191
+ raise Puppet::Error.new("Environment '#{@env.name}', cannot find environment_data_provider '#{provider_name}'")
192
+ end
193
+ provider
194
+ end
195
+
196
+ def extract_module_name(name)
197
+ qual_index = name.index('::')
198
+ qual_index.nil? ? nil : name[0..qual_index-1]
199
+ end
200
+ end
@@ -0,0 +1,32 @@
1
+ # This file is loaded by the autoloader, and it does not find the data function support unless required relative
2
+ #
3
+ require 'yaml'
4
+ require_relative 'hiera_interpolate'
5
+
6
+ module Puppet::DataProviders
7
+ class YamlDataProviderFactory < Puppet::Plugins::DataProviders::FileBasedDataProviderFactory
8
+ def create(name, paths)
9
+ YamlDataProvider.new(name, paths)
10
+ end
11
+
12
+ def path_extension
13
+ '.yaml'
14
+ end
15
+ end
16
+
17
+ class YamlDataProvider < Puppet::Plugins::DataProviders::PathBasedDataProvider
18
+ include HieraInterpolate
19
+
20
+ def initialize_data(path, lookup_invocation)
21
+ HieraConfig.symkeys_to_string(YAML.load_file(path))
22
+ rescue YAML::SyntaxError => ex
23
+ # Psych errors includes the absolute path to the file, so no need to add that
24
+ # to the message
25
+ raise Puppet::DataBinding::LookupError, "Unable to parse #{ex.message}"
26
+ end
27
+
28
+ def post_process(value, lookup_invocation)
29
+ interpolate(value, lookup_invocation, true)
30
+ end
31
+ end
32
+ end