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
@@ -0,0 +1,95 @@
1
+ #
2
+ # A helper module to look a capability up from PuppetDB
3
+ #
4
+ # @todo lutter 2015-03-10: determine whether this should be based on
5
+ # Puppet::Pops::Evaluator::Collectors, or at least use
6
+ # Puppet::Util::Puppetdb::Http
7
+
8
+ require 'net/http'
9
+ require 'cgi'
10
+ require 'json'
11
+
12
+ # @api private
13
+ module Puppet::Resource::CapabilityFinder
14
+
15
+ # Looks the capability resource from PuppetDB.
16
+ # @param environment [String] environment name
17
+ # @param code_id [String,nil] code_id of the catalog
18
+ # @param cap [Puppet::Type] the capability resource type instance
19
+ # @return [Puppet::Resource,nil] The found capability resource or `nil` if it could not be found
20
+ def self.find(environment, code_id, cap)
21
+ unless Puppet::Util.const_defined?('Puppetdb')
22
+ raise Puppet::DevError, 'PuppetDB is not available'
23
+ end
24
+
25
+ query_terms = [
26
+ 'and',
27
+ ['=', 'type', cap.type.capitalize],
28
+ ['=', 'title', cap.title.to_s],
29
+ ['=', 'tag', "producer:#{environment}"]
30
+ ]
31
+
32
+ unless code_id.nil?
33
+ query_terms << ['in', 'certname',
34
+ ['extract', 'certname',
35
+ ['select_catalogs',
36
+ ['=', 'code_id', code_id]]]]
37
+ end
38
+ query = query_terms.to_json
39
+
40
+ Puppet.notice "Capability lookup #{cap}]: #{query}"
41
+
42
+ http = Puppet::Util.const_get('Puppetdb').const_get('Http')
43
+ response = http.action("/pdb/query/v4/resources?query=#{CGI.escape(query)}") do |conn, uri|
44
+ conn.get(uri, { 'Accept' => 'application/json'})
45
+ end
46
+ json = response.body
47
+
48
+ # The format of the response body is documented at
49
+ # http://docs.puppetlabs.com/puppetdb/3.0/api/query/v4/resources.html#response-format
50
+ # In a nutshell, we expect to get an array of resources back. If the
51
+ # array is empty, the lookup failed and we return +nil+, if it
52
+ # contains exactly one, we turn that resource back into a Puppet
53
+ # ::Resource. If the array contains more than one entry, we have a
54
+ # bug in the overall system, as we allowed multiple capabilities with
55
+ # the same type and title to be produced in this environment.
56
+ begin
57
+ data = JSON.parse(json)
58
+ rescue JSON::JSONError => e
59
+ raise Puppet::DevError,
60
+ "Invalid JSON from PuppetDB when looking up #{cap}\n#{e}\nRaw JSON was:\n#{json}"
61
+ end
62
+ unless data.is_a?(Array)
63
+ raise Puppet::DevError,
64
+ "Unexpected response from PuppetDB when looking up #{cap}: " +
65
+ "expected an Array but got #{data.inspect}"
66
+ end
67
+ if data.size > 1
68
+ raise Puppet::DevError,
69
+ "Unexpected response from PuppetDB when looking up #{cap}:\n" +
70
+ "expected exactly one resource but got #{data.size};\n" +
71
+ "returned data is:\n#{data.inspect}"
72
+ end
73
+
74
+ unless data.empty?
75
+ resource_hash = data.first
76
+ resource = Puppet::Resource.new(resource_hash['type'],
77
+ resource_hash['title'])
78
+ real_type = Puppet::Type.type(resource.type)
79
+ if real_type.nil?
80
+ fail Puppet::ParseError,
81
+ "Could not find resource type #{resource.type} returned from PuppetDB"
82
+ end
83
+ real_type.parameters.each do |param|
84
+ param = param.to_s
85
+ next if param == 'name'
86
+ if value = resource_hash['parameters'][param]
87
+ resource[param] = value
88
+ else
89
+ Puppet.debug "No capability value for #{resource}->#{param}"
90
+ end
91
+ end
92
+ return resource
93
+ end
94
+ end
95
+ end
@@ -4,6 +4,8 @@ require 'puppet/transaction'
4
4
  require 'puppet/util/tagging'
5
5
  require 'puppet/graph'
6
6
 
7
+ require 'puppet/resource/capability_finder'
8
+
7
9
  # This class models a node catalog. It is the thing meant to be passed
8
10
  # from server to client, and it contains all of the information in the
9
11
  # catalog, including the resources and the relationships between them.
@@ -27,6 +29,9 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
27
29
  # is up to date.
28
30
  attr_accessor :version
29
31
 
32
+ # The id of the code input to the compiler.
33
+ attr_accessor :code_id
34
+
30
35
  # How long this catalog took to retrieve. Used for reporting stats.
31
36
  attr_accessor :retrieval_duration
32
37
 
@@ -71,6 +76,25 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
71
76
  return a
72
77
  end
73
78
 
79
+ def add_resource_before(other, *resources)
80
+ resources.each do |resource|
81
+ other_title_key = title_key_for_ref(other.ref)
82
+ idx = @resources.index(other_title_key)
83
+ raise ArgumentError, "Cannot add resource #{resource.ref} before #{other.ref} because #{other.ref} is not yet in the catalog" if idx.nil?
84
+ add_one_resource(resource, idx)
85
+ end
86
+ end
87
+
88
+ def add_resource_after(other, *resources)
89
+ resources.each do |resource|
90
+ other_title_key = title_key_for_ref(other.ref)
91
+ idx = @resources.index(other_title_key)
92
+ raise ArgumentError, "Cannot add resource #{resource.ref} after #{other.ref} because #{other.ref} is not yet in the catalog" if idx.nil?
93
+ add_one_resource(resource, idx+1)
94
+ end
95
+ end
96
+
97
+
74
98
  def add_resource(*resources)
75
99
  resources.each do |resource|
76
100
  add_one_resource(resource)
@@ -84,13 +108,13 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
84
108
  adjacent(resource, :direction => :in)[0]
85
109
  end
86
110
 
87
- def add_one_resource(resource)
111
+ def add_one_resource(resource, idx=-1)
88
112
  title_key = title_key_for_ref(resource.ref)
89
113
  if @resource_table[title_key]
90
114
  fail_on_duplicate_type_and_title(resource, title_key)
91
115
  end
92
116
 
93
- add_resource_to_table(resource, title_key)
117
+ add_resource_to_table(resource, title_key, idx)
94
118
  create_resource_aliases(resource)
95
119
 
96
120
  resource.catalog = self if resource.respond_to?(:catalog=)
@@ -98,9 +122,9 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
98
122
  end
99
123
  private :add_one_resource
100
124
 
101
- def add_resource_to_table(resource, title_key)
125
+ def add_resource_to_table(resource, title_key, idx)
102
126
  @resource_table[title_key] = resource
103
- @resources << title_key
127
+ @resources.insert(idx, title_key)
104
128
  end
105
129
  private :add_resource_to_table
106
130
 
@@ -245,7 +269,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
245
269
  host_config
246
270
  end
247
271
 
248
- def initialize(name = nil, environment = Puppet::Node::Environment::NONE)
272
+ def initialize(name = nil, environment = Puppet::Node::Environment::NONE, code_id = nil)
249
273
  super()
250
274
  @name = name
251
275
  @classes = []
@@ -256,6 +280,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
256
280
  @host_config = true
257
281
  @environment_instance = environment
258
282
  @environment = environment.to_s
283
+ @code_id = code_id
259
284
 
260
285
  @aliases = {}
261
286
 
@@ -293,7 +318,8 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
293
318
  remove_vertex!(resource) if vertex?(resource)
294
319
  @relationship_graph.remove_vertex!(resource) if @relationship_graph and @relationship_graph.vertex?(resource)
295
320
  @resources.delete(title_key)
296
- resource.remove
321
+ # Only Puppet::Type kind of resources respond to :remove, not Puppet::Resource
322
+ resource.remove if resource.respond_to?(:remove)
297
323
  end
298
324
  end
299
325
 
@@ -313,7 +339,15 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
313
339
  res.catalog = self
314
340
  title_key = [res.type, res.title.to_s]
315
341
  uniqueness_key = [res.type, res.uniqueness_key].flatten
316
- @resource_table[title_key] || @resource_table[uniqueness_key]
342
+ result = @resource_table[title_key] || @resource_table[uniqueness_key]
343
+ if ! result && res.resource_type && res.resource_type.is_capability?
344
+ # @todo lutter 2015-03-10: this assumes that it is legal to just
345
+ # mention a capability resource in code and have it automatically
346
+ # made available, even if the current component does not require it
347
+ result = Puppet::Resource::CapabilityFinder.find(environment, code_id, res)
348
+ add_resource(result) if result
349
+ end
350
+ result
317
351
  end
318
352
 
319
353
  def resource_refs
@@ -341,6 +375,10 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
341
375
  result.version = version
342
376
  end
343
377
 
378
+ if code_id = data['code_id']
379
+ result.code_id = code_id
380
+ end
381
+
344
382
  if environment = data['environment']
345
383
  result.environment = environment
346
384
  result.environment_instance = Puppet::Node::Environment.remote(environment.to_sym)
@@ -381,6 +419,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
381
419
  'tags' => tags,
382
420
  'name' => name,
383
421
  'version' => version,
422
+ 'code_id' => code_id,
384
423
  'environment' => environment.to_s,
385
424
  'resources' => @resources.collect { |v| @resource_table[v].to_data_hash },
386
425
  'edges' => edges. collect { |e| e.to_data_hash },
@@ -496,6 +535,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
496
535
  result = self.class.new(self.name, self.environment_instance)
497
536
 
498
537
  result.version = self.version
538
+ result.code_id = self.code_id
499
539
 
500
540
  map = {}
501
541
  resources.each do |resource|
@@ -1,6 +1,5 @@
1
1
  require 'time'
2
2
  require 'puppet/network/format_support'
3
- require 'puppet/util/psych_support'
4
3
 
5
4
  module Puppet
6
5
  class Resource
@@ -14,7 +13,6 @@ module Puppet
14
13
  class Status
15
14
  include Puppet::Util::Tagging
16
15
  include Puppet::Network::FormatSupport
17
- include Puppet::Util::PsychSupport
18
16
 
19
17
  # @!attribute [rw] file
20
18
  # @return [String] The file where `@real_resource` was defined.
@@ -16,19 +16,40 @@ class Puppet::Resource::Type
16
16
  include Puppet::Util::Warnings
17
17
  include Puppet::Util::Errors
18
18
 
19
- RESOURCE_KINDS = [:hostclass, :node, :definition]
19
+ RESOURCE_KINDS = [:hostclass, :node, :definition, :capability_mapping, :application, :site]
20
20
 
21
21
  # Map the names used in our documentation to the names used internally
22
22
  RESOURCE_KINDS_TO_EXTERNAL_NAMES = {
23
23
  :hostclass => "class",
24
24
  :node => "node",
25
25
  :definition => "defined_type",
26
+ :application => "application",
27
+ :site => 'site'
26
28
  }
27
29
  RESOURCE_EXTERNAL_NAMES_TO_KINDS = RESOURCE_KINDS_TO_EXTERNAL_NAMES.invert
28
30
 
31
+ NAME = 'name'.freeze
32
+ TITLE = 'title'.freeze
33
+ MODULE_NAME = 'module_name'.freeze
34
+ CALLER_MODULE_NAME = 'caller_module_name'.freeze
35
+ PARAMETERS = 'parameters'.freeze
36
+ KIND = 'kind'.freeze
37
+ NODES = 'nodes'.freeze
38
+ DOUBLE_COLON = '::'.freeze
39
+ EMPTY_ARRAY = [].freeze
40
+
29
41
  attr_accessor :file, :line, :doc, :code, :parent, :resource_type_collection
30
42
  attr_reader :namespace, :arguments, :behaves_like, :module_name
31
43
 
44
+ # The attributes 'produces' and 'consumes' are arrays of the blueprints
45
+ # of capabilities this type can produce/consume. The entries in the array
46
+ # are a fairly direct representation of what goes into produces/consumes
47
+ # clauses. Each entry is a hash with attributes
48
+ # :capability - the type name of the capres produced/consumed
49
+ # :mappings - a hash of attribute_name => Expression
50
+ # These two attributes are populated in
51
+ # PopsBridge::instantiate_CapabilityMaping
52
+
32
53
  # Map from argument (aka parameter) names to Puppet Type
33
54
  # @return [Hash<Symbol, Puppet::Pops::Types::PAnyType] map from name to type
34
55
  #
@@ -48,8 +69,8 @@ class Puppet::Resource::Type
48
69
  indirects :resource_type, :terminus_class => :parser
49
70
 
50
71
  def self.from_data_hash(data)
51
- name = data.delete('name') or raise ArgumentError, "Resource Type names must be specified"
52
- kind = data.delete('kind') || "definition"
72
+ name = data.delete(NAME) or raise ArgumentError, 'Resource Type names must be specified'
73
+ kind = data.delete(KIND) || 'definition'
53
74
 
54
75
  unless type = RESOURCE_EXTERNAL_NAMES_TO_KINDS[kind]
55
76
  raise ArgumentError, "Unsupported resource kind '#{kind}'"
@@ -74,15 +95,15 @@ class Puppet::Resource::Type
74
95
  # External documentation uses "parameters" but the internal name
75
96
  # is "arguments"
76
97
  # Dump any arguments as source
77
- data['parameters'] = Hash[arguments.map do |k,v|
98
+ data[PARAMETERS] = Hash[arguments.map do |k,v|
78
99
  [k, v.respond_to?(:source_text) ? v.source_text : v]
79
100
  end]
80
- data['name'] = name
101
+ data[NAME] = name
81
102
 
82
103
  unless RESOURCE_KINDS_TO_EXTERNAL_NAMES.has_key?(type)
83
104
  raise ArgumentError, "Unsupported resource kind '#{type}'"
84
105
  end
85
- data['kind'] = RESOURCE_KINDS_TO_EXTERNAL_NAMES[type]
106
+ data[KIND] = RESOURCE_KINDS_TO_EXTERNAL_NAMES[type]
86
107
  data
87
108
  end
88
109
 
@@ -94,6 +115,48 @@ class Puppet::Resource::Type
94
115
  return(klass == parent_type ? true : parent_type.child_of?(klass))
95
116
  end
96
117
 
118
+ # Evaluate the resources produced by the given resource. These resources are
119
+ # evaluated in a separate but identical scope from the rest of the resource.
120
+ def evaluate_produces(resource, scope)
121
+ # Only defined types and classes can produce capabilities
122
+ return unless definition? || hostclass?
123
+
124
+ resource.export.map do |ex|
125
+ # Assert that the ref really is a resource reference
126
+ raise Puppet::Error, "Invalid export in #{resource.ref}: #{ex} is not a resource" unless ex.is_a?(Puppet::Resource)
127
+ raise Puppet::Error, "Invalid export in #{resource.ref}: #{ex} is not a capability resource" if ex.resource_type.nil? || !ex.resource_type.is_capability?
128
+
129
+ blueprint = produces.find { |pr| pr[:capability] == ex.type }
130
+ if blueprint.nil?
131
+ raise Puppet::ParseError, "Resource type #{resource.type} does not produce #{ex.type}"
132
+ end
133
+ produced_resource = Puppet::Parser::Resource.new(ex.type, ex.title, :scope => scope, :source => self)
134
+
135
+ produced_resource.resource_type.parameters.each do |name|
136
+ next if name == :name
137
+
138
+ if expr = blueprint[:mappings][name.to_s]
139
+ produced_resource[name] = expr.safeevaluate(scope)
140
+ else
141
+ produced_resource[name] = scope[name.to_s]
142
+ end
143
+ end
144
+ # Tag the produced resource so we can later distinguish it from
145
+ # copies of the resource that wind up in the catalogs of nodes that
146
+ # use this resource. We tag the resource with producer:<environment>,
147
+ # meaning produced resources need to be unique within their
148
+ # environment
149
+ # @todo lutter 2014-11-13: we would really like to use a dedicated
150
+ # metadata field to indicate the producer of a resource, but that
151
+ # requires changes to PuppetDB and its API; so for now, we just use
152
+ # tagging
153
+ produced_resource.tag("producer:#{scope.catalog.environment}")
154
+ scope.catalog.add_resource(produced_resource)
155
+ produced_resource[:require] = resource.ref
156
+ produced_resource
157
+ end
158
+ end
159
+
97
160
  # Now evaluate the code associated with this class or definition.
98
161
  def evaluate_code(resource)
99
162
 
@@ -107,6 +170,8 @@ class Puppet::Resource::Type
107
170
 
108
171
  resource.add_edge_to_stage
109
172
 
173
+ evaluate_produces(resource, scope)
174
+
110
175
  if code
111
176
  if @match # Only bother setting up the ephemeral scope if there are match variables to add into it
112
177
  begin
@@ -132,7 +197,7 @@ class Puppet::Resource::Type
132
197
 
133
198
  [:code, :doc, :line, :file, :parent].each do |param|
134
199
  next unless value = options[param]
135
- send(param.to_s + "=", value)
200
+ send(param.to_s + '=', value)
136
201
  end
137
202
 
138
203
  set_arguments(options[:arguments])
@@ -143,6 +208,24 @@ class Puppet::Resource::Type
143
208
  @module_name = options[:module_name]
144
209
  end
145
210
 
211
+ def produces
212
+ @produces || EMPTY_ARRAY
213
+ end
214
+
215
+ def consumes
216
+ @consumes || EMPTY_ARRAY
217
+ end
218
+
219
+ def add_produces(blueprint)
220
+ @produces ||= []
221
+ @produces << blueprint
222
+ end
223
+
224
+ def add_consumes(blueprint)
225
+ @consumes ||= []
226
+ @consumes << blueprint
227
+ end
228
+
146
229
  # This is only used for node names, and really only when the node name
147
230
  # is a regexp.
148
231
  def match(string)
@@ -186,8 +269,17 @@ class Puppet::Resource::Type
186
269
  # parameterized class, then all parameters take on their default
187
270
  # values.
188
271
  def ensure_in_catalog(scope, parameters=nil)
189
- type == :definition and raise ArgumentError, "Cannot create resources for defined resource types"
190
- resource_type = type == :hostclass ? :class : :node
272
+ resource_type =
273
+ case type
274
+ when :definition
275
+ raise ArgumentError, 'Cannot create resources for defined resource types'
276
+ when :hostclass
277
+ :class
278
+ when :node
279
+ :node
280
+ when :site
281
+ :site
282
+ end
191
283
 
192
284
  # Do nothing if the resource already exists; this makes sure we don't
193
285
  # get multiple copies of the class resource, which helps provide the
@@ -196,11 +288,13 @@ class Puppet::Resource::Type
196
288
  # if parameters are passed, we should still try to create the resource
197
289
  # even if it exists so that we can fail
198
290
  # this prevents us from being able to combine param classes with include
199
- if resource = scope.catalog.resource(resource_type, name) and !parameters
200
- return resource
291
+ if parameters.nil?
292
+ resource = scope.catalog.resource(resource_type, name)
293
+ return resource unless resource.nil?
294
+ elsif parameters.is_a?(Hash)
295
+ parameters = parameters.map {|k, v| Puppet::Parser::Resource::Param.new(:name => k, :value => v, :source => self)}
201
296
  end
202
- resource = Puppet::Parser::Resource.new(resource_type, name, :scope => scope, :source => self)
203
- assign_parameter_values(parameters, resource)
297
+ resource = Puppet::Parser::Resource.new(resource_type, name, :scope => scope, :source => self, :parameters => parameters)
204
298
  instantiate_resource(scope, resource)
205
299
  scope.compiler.add_resource(scope, resource)
206
300
  resource
@@ -229,7 +323,11 @@ class Puppet::Resource::Type
229
323
  @name.is_a?(Regexp)
230
324
  end
231
325
 
326
+ # @deprecated Not used by Puppet
327
+ # @api private
232
328
  def assign_parameter_values(parameters, resource)
329
+ Puppet.deprecation_warning('The method Puppet::Resource::Type.assign_parameter_values is deprecated and will be removed in the next major release of Puppet.')
330
+
233
331
  return unless parameters
234
332
 
235
333
  # It'd be nice to assign default parameter values here,
@@ -247,53 +345,91 @@ class Puppet::Resource::Type
247
345
  fail(Puppet::ParseError, "Could not find parent resource type '#{parent}' of type #{type} in #{scope.environment}")
248
346
  end
249
347
 
250
- # Set any arguments passed by the resource as variables in the scope.
348
+ # Validate and set any arguments passed by the resource as variables in the scope.
349
+ # @param resource [Puppet::Parser::Resource] the resource
350
+ # @param scope [Puppet::Parser::Scope] the scope
351
+ #
352
+ # @api private
251
353
  def set_resource_parameters(resource, scope)
252
- set = {}
253
- resource.to_hash.each do |param, value|
254
- param = param.to_sym
255
- fail Puppet::ParseError, "#{resource.ref} does not accept attribute #{param}" unless valid_parameter?(param)
354
+ # Inject parameters from using external lookup
355
+ resource.add_parameters_from_consume
356
+ inject_external_parameters(resource, scope)
256
357
 
257
- exceptwrap { scope[param.to_s] = value }
258
-
259
- set[param] = true
260
- end
358
+ resource_hash = {}
359
+ resource.each { |k, v| resource_hash[k.to_s] = v.value unless k == :name || k == :title }
261
360
 
262
361
  if @type == :hostclass
263
- scope["title"] = resource.title.to_s.downcase unless set.include? :title
264
- scope["name"] = resource.name.to_s.downcase unless set.include? :name
362
+ scope[TITLE] = resource.title.to_s.downcase
363
+ scope[NAME] = resource.name.to_s.downcase
265
364
  else
266
- scope["title"] = resource.title unless set.include? :title
267
- scope["name"] = resource.name unless set.include? :name
365
+ scope[TITLE] = resource.title
366
+ scope[NAME] = resource.name
268
367
  end
269
- scope["module_name"] = module_name if module_name and ! set.include? :module_name
270
368
 
271
- if caller_name = scope.parent_module_name and ! set.include?(:caller_module_name)
272
- scope["caller_module_name"] = caller_name
369
+ modname = resource_hash[MODULE_NAME] || module_name
370
+ scope[MODULE_NAME] = modname unless modname.nil?
371
+ caller_name = resource_hash[CALLER_MODULE_NAME] || scope.parent_module_name
372
+ scope[CALLER_MODULE_NAME] = caller_name unless caller_name.nil?
373
+
374
+ scope.class_set(self.name,scope) if hostclass? || node?
375
+
376
+ assign_defaults(resource, scope, resource_hash)
377
+ validate_resource_hash(resource, resource_hash)
378
+ resource_hash.each { |param, value| exceptwrap { scope[param] = value }}
379
+ end
380
+
381
+ # Lookup and inject parameters from external scope
382
+ # @param resource [Puppet::Parser::Resource] the resource
383
+ # @param scope [Puppet::Parser::Scope] the scope
384
+ def inject_external_parameters(resource, scope)
385
+ # Only lookup parameters for host classes
386
+ return unless type == :hostclass
387
+ parameters = resource.parameters
388
+ arguments.each do |param_name, _|
389
+ name = param_name.to_sym
390
+ next if parameters.include?(name)
391
+ value = lookup_external_default_for(param_name, scope)
392
+ resource[name] = value unless value.nil?
393
+ end
394
+ end
395
+ private :inject_external_parameters
396
+
397
+ def assign_defaults(resource, scope, resource_hash)
398
+ return unless resource.is_a?(Puppet::Parser::Resource)
399
+ parameters = resource.parameters
400
+ hashed_types = parameter_struct.hashed_elements
401
+ arguments.each do |param_name, default|
402
+ next if default.nil?
403
+ name = param_name.to_sym
404
+ param = parameters[name]
405
+ next unless param.nil? || param.value.nil?
406
+
407
+ value = default.safeevaluate(scope)
408
+ resource[name] = value
409
+ resource_hash[param_name] = value
273
410
  end
274
- scope.class_set(self.name,scope) if hostclass? or node?
411
+ end
412
+ private :assign_defaults
275
413
 
276
- # Evaluate the default parameters, now that all other variables are set
277
- default_params = resource.set_default_parameters(scope)
278
- default_params.each { |param| scope[param] = resource[param] }
414
+ def validate_resource_hash(resource, resource_hash)
415
+ Puppet::Pops::Types::TypeMismatchDescriber.validate_parameters(resource.to_s, parameter_struct, resource_hash, resource.is_unevaluated_consumer?)
416
+ end
417
+ private :validate_resource_hash
279
418
 
280
- # This has to come after the above parameters so that default values
281
- # can use their values
282
- resource.validate_complete
419
+ # Validate that all parameters given to the resource are correct
420
+ # @param resource [Puppet::Resource] the resource to validate
421
+ def validate_resource(resource)
422
+ validate_resource_hash(resource, Hash[resource.parameters.map { |name, value| [name.to_s, value.value] }])
283
423
  end
284
424
 
285
425
  # Check whether a given argument is valid.
286
426
  def valid_parameter?(param)
287
- param = param.to_s
288
-
289
- return true if param == "name"
290
- return true if Puppet::Type.metaparam?(param)
291
- return false unless defined?(@arguments)
292
- return(arguments.include?(param) ? true : false)
427
+ parameter_struct.hashed_elements.include?(param.to_s)
293
428
  end
294
429
 
295
430
  def set_arguments(arguments)
296
431
  @arguments = {}
432
+ @parameter_struct = nil
297
433
  return if arguments.nil?
298
434
 
299
435
  arguments.each do |arg, default|
@@ -309,6 +445,7 @@ class Puppet::Resource::Type
309
445
  #
310
446
  def set_argument_types(name_to_type_hash)
311
447
  @argument_types = {}
448
+ @parameter_struct = nil
312
449
  return unless name_to_type_hash
313
450
  name_to_type_hash.each do |name, t|
314
451
  # catch internal errors
@@ -322,6 +459,14 @@ class Puppet::Resource::Type
322
459
  end
323
460
  end
324
461
 
462
+ # Returns boolean true if an instance of this type is a capability. This
463
+ # implementation always returns false. This "duck-typing" interface is
464
+ # shared among other classes and makes it easier to detect capabilities
465
+ # when they are intermixed with non capability instances.
466
+ def is_capability?
467
+ false
468
+ end
469
+
325
470
  private
326
471
 
327
472
  def convert_from_ast(name)
@@ -341,9 +486,9 @@ class Puppet::Resource::Type
341
486
 
342
487
  # Split an fq name into a namespace and name
343
488
  def namesplit(fullname)
344
- ary = fullname.split("::")
489
+ ary = fullname.split(DOUBLE_COLON)
345
490
  n = ary.pop || ""
346
- ns = ary.join("::")
491
+ ns = ary.join(DOUBLE_COLON)
347
492
  return ns, n
348
493
  end
349
494
 
@@ -374,4 +519,53 @@ class Puppet::Resource::Type
374
519
  raise Puppet::ParseError, "#{param} is a metaparameter; please choose another parameter name in the #{self.name} definition"
375
520
  end
376
521
  end
522
+
523
+ def parameter_struct
524
+ @parameter_struct ||= create_params_struct
525
+ end
526
+
527
+ def create_params_struct
528
+ arg_types = argument_types
529
+ type_factory = Puppet::Pops::Types::TypeFactory
530
+ members = { type_factory.optional(type_factory.string(nil, NAME)) => type_factory.any }
531
+
532
+ if application?
533
+ resource_type = type_factory.type_type(type_factory.resource)
534
+ members[type_factory.optional(type_factory.string(nil, NODES))] = type_factory.hash_of(type_factory.variant(
535
+ resource_type, type_factory.array_of(resource_type)), type_factory.type_type(type_factory.resource('node')))
536
+ end
537
+
538
+ Puppet::Type.eachmetaparam do |name|
539
+ # TODO: Once meta parameters are typed, this should change to reflect that type
540
+ members[name.to_s] = type_factory.any
541
+ end
542
+
543
+ arguments.each_pair do |name, default|
544
+ key_type = type_factory.string(nil, name.to_s)
545
+ key_type = type_factory.optional(key_type) unless default.nil?
546
+
547
+ arg_type = arg_types[name]
548
+ arg_type = type_factory.any if arg_type.nil?
549
+ members[key_type] = arg_type
550
+ end
551
+ type_factory.struct(members)
552
+ end
553
+ private :create_params_struct
554
+
555
+ # Consult external data bindings for class parameter values which must be
556
+ # namespaced in the backend.
557
+ #
558
+ # Example:
559
+ #
560
+ # class foo($port=0){ ... }
561
+ #
562
+ # We make a request to the backend for the key 'foo::port' not 'foo'
563
+ #
564
+ def lookup_external_default_for(param, scope)
565
+ if type == :hostclass
566
+ catch(:no_such_key) { return Puppet::Pops::Lookup.search_and_merge("#{name}::#{param}", Puppet::Pops::Lookup::Invocation.new(scope), nil) }
567
+ end
568
+ nil
569
+ end
570
+ private :lookup_external_default_for
377
571
  end