puppet 3.5.1-x86-mingw32 → 3.6.0.rc1-x86-mingw32

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

Potentially problematic release.


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

Files changed (342) hide show
  1. data/CONTRIBUTING.md +5 -0
  2. data/Gemfile +17 -9
  3. data/README.md +1 -0
  4. data/conf/fileserver.conf +4 -3
  5. data/ext/README.environment +8 -0
  6. data/ext/build_defaults.yaml +1 -1
  7. data/ext/debian/control +2 -2
  8. data/ext/debian/puppet-common.dirs +4 -0
  9. data/ext/debian/rules +4 -0
  10. data/ext/emacs/puppet-mode-init.el +1 -1
  11. data/ext/emacs/puppet-mode.el +36 -17
  12. data/ext/redhat/client.init +3 -3
  13. data/ext/redhat/puppet.spec.erb +9 -0
  14. data/ext/systemd/puppet.service +3 -4
  15. data/ext/systemd/puppetmaster.service +1 -3
  16. data/install.rb +1 -1
  17. data/lib/puppet.rb +2 -1
  18. data/lib/puppet/agent.rb +1 -1
  19. data/lib/puppet/application.rb +17 -17
  20. data/lib/puppet/application/doc.rb +1 -1
  21. data/lib/puppet/configurer.rb +4 -1
  22. data/lib/puppet/configurer/downloader.rb +13 -12
  23. data/lib/puppet/configurer/plugin_handler.rb +3 -3
  24. data/lib/puppet/context.rb +6 -1
  25. data/lib/puppet/defaults.rb +82 -12
  26. data/lib/puppet/environments.rb +169 -13
  27. data/lib/puppet/external/nagios/grammar.ry +2 -0
  28. data/lib/puppet/external/nagios/parser.rb +28 -19
  29. data/lib/puppet/face/config.rb +19 -6
  30. data/lib/puppet/face/module/generate.rb +209 -7
  31. data/lib/puppet/face/module/install.rb +17 -16
  32. data/lib/puppet/face/module/list.rb +83 -82
  33. data/lib/puppet/face/module/search.rb +1 -1
  34. data/lib/puppet/face/module/upgrade.rb +10 -9
  35. data/lib/puppet/face/parser.rb +3 -2
  36. data/lib/puppet/face/plugin.rb +8 -4
  37. data/lib/puppet/file_bucket/dipper.rb +6 -3
  38. data/lib/puppet/file_bucket/file.rb +4 -2
  39. data/lib/puppet/file_serving/metadata.rb +1 -1
  40. data/lib/puppet/file_system/memory_file.rb +27 -1
  41. data/lib/puppet/file_system/memory_impl.rb +15 -1
  42. data/lib/puppet/forge.rb +148 -52
  43. data/lib/puppet/forge/cache.rb +5 -1
  44. data/lib/puppet/forge/errors.rb +10 -0
  45. data/lib/puppet/forge/repository.rb +61 -26
  46. data/lib/puppet/functions.rb +548 -0
  47. data/lib/puppet/functions/assert_type.rb +42 -0
  48. data/lib/puppet/functions/import.rb +7 -0
  49. data/lib/puppet/indirector/facts/facter.rb +1 -1
  50. data/lib/puppet/indirector/file_bucket_file/file.rb +3 -2
  51. data/lib/puppet/indirector/rest.rb +18 -0
  52. data/lib/puppet/loaders.rb +20 -0
  53. data/lib/puppet/module.rb +2 -2
  54. data/lib/puppet/module_tool.rb +40 -14
  55. data/lib/puppet/module_tool/applications.rb +0 -1
  56. data/lib/puppet/module_tool/applications/application.rb +35 -26
  57. data/lib/puppet/module_tool/applications/builder.rb +16 -6
  58. data/lib/puppet/module_tool/applications/checksummer.rb +25 -19
  59. data/lib/puppet/module_tool/applications/installer.rb +196 -35
  60. data/lib/puppet/module_tool/applications/searcher.rb +1 -0
  61. data/lib/puppet/module_tool/applications/uninstaller.rb +7 -1
  62. data/lib/puppet/module_tool/applications/unpacker.rb +57 -31
  63. data/lib/puppet/module_tool/applications/upgrader.rb +221 -65
  64. data/lib/puppet/module_tool/checksums.rb +5 -8
  65. data/lib/puppet/module_tool/errors/installer.rb +12 -44
  66. data/lib/puppet/module_tool/errors/shared.rb +84 -11
  67. data/lib/puppet/module_tool/errors/upgrader.rb +16 -45
  68. data/lib/puppet/module_tool/install_directory.rb +7 -6
  69. data/lib/puppet/module_tool/installed_modules.rb +92 -0
  70. data/lib/puppet/module_tool/local_tarball.rb +91 -0
  71. data/lib/puppet/module_tool/metadata.rb +119 -115
  72. data/lib/puppet/module_tool/modulefile.rb +9 -9
  73. data/lib/puppet/module_tool/shared_behaviors.rb +19 -7
  74. data/lib/puppet/module_tool/skeleton/templates/generator/README.md.erb +79 -0
  75. data/lib/puppet/module_tool/skeleton/templates/generator/Rakefile +18 -0
  76. data/lib/puppet/module_tool/skeleton/templates/generator/metadata.json.erb +1 -0
  77. data/lib/puppet/module_tool/skeleton/templates/generator/spec/classes/init_spec.rb.erb +7 -0
  78. data/lib/puppet/module_tool/tar.rb +3 -7
  79. data/lib/puppet/module_tool/tar/gnu.rb +21 -9
  80. data/lib/puppet/module_tool/tar/mini.rb +2 -8
  81. data/lib/puppet/network/http/api/v1.rb +1 -1
  82. data/lib/puppet/network/http/api/v2/authorization.rb +4 -2
  83. data/lib/puppet/network/http/issues.rb +1 -0
  84. data/lib/puppet/network/http_pool.rb +15 -6
  85. data/lib/puppet/node/environment.rb +91 -20
  86. data/lib/puppet/parser/ast/pops_bridge.rb +44 -3
  87. data/lib/puppet/parser/collector.rb +1 -1
  88. data/lib/puppet/parser/compiler.rb +50 -7
  89. data/lib/puppet/parser/functions.rb +6 -0
  90. data/lib/puppet/parser/functions/generate.rb +1 -1
  91. data/lib/puppet/parser/resource.rb +1 -1
  92. data/lib/puppet/pops.rb +22 -1
  93. data/lib/puppet/pops/adapters.rb +8 -1
  94. data/lib/puppet/pops/binder/bindings_composer.rb +1 -1
  95. data/lib/puppet/pops/binder/bindings_factory.rb +1 -1
  96. data/lib/puppet/pops/binder/config/binder_config_checker.rb +1 -1
  97. data/lib/puppet/pops/binder/producers.rb +2 -2
  98. data/lib/puppet/pops/evaluator/access_operator.rb +65 -25
  99. data/lib/puppet/pops/evaluator/callable_signature.rb +101 -0
  100. data/lib/puppet/pops/evaluator/closure.rb +57 -2
  101. data/lib/puppet/pops/evaluator/compare_operator.rb +1 -1
  102. data/lib/puppet/pops/evaluator/evaluator_impl.rb +9 -11
  103. data/lib/puppet/pops/evaluator/runtime3_support.rb +72 -21
  104. data/lib/puppet/pops/functions/dispatch.rb +71 -0
  105. data/lib/puppet/pops/functions/dispatcher.rb +237 -0
  106. data/lib/puppet/pops/functions/function.rb +77 -0
  107. data/lib/puppet/pops/issues.rb +12 -0
  108. data/lib/puppet/pops/loader/base_loader.rb +102 -0
  109. data/lib/puppet/pops/loader/dependency_loader.rb +60 -0
  110. data/lib/puppet/pops/loader/gem_support.rb +49 -0
  111. data/lib/puppet/pops/loader/loader.rb +180 -0
  112. data/lib/puppet/pops/loader/loader_paths.rb +137 -0
  113. data/lib/puppet/pops/loader/module_loaders.rb +242 -0
  114. data/lib/puppet/pops/loader/null_loader.rb +44 -0
  115. data/lib/puppet/pops/loader/ruby_function_instantiator.rb +34 -0
  116. data/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +109 -0
  117. data/lib/puppet/pops/loader/simple_environment_loader.rb +20 -0
  118. data/lib/puppet/pops/loader/static_loader.rb +69 -0
  119. data/lib/puppet/pops/loader/uri_helper.rb +22 -0
  120. data/lib/puppet/pops/loaders.rb +240 -0
  121. data/lib/puppet/pops/model/factory.rb +13 -5
  122. data/lib/puppet/pops/model/model_tree_dumper.rb +12 -4
  123. data/lib/puppet/pops/parser/egrammar.ra +31 -18
  124. data/lib/puppet/pops/parser/eparser.rb +1137 -1106
  125. data/lib/puppet/pops/parser/lexer2.rb +17 -16
  126. data/lib/puppet/pops/semantic_error.rb +17 -0
  127. data/lib/puppet/pops/types/type_calculator.rb +150 -15
  128. data/lib/puppet/pops/types/type_factory.rb +69 -0
  129. data/lib/puppet/pops/types/type_parser.rb +9 -0
  130. data/lib/puppet/pops/types/types.rb +65 -4
  131. data/lib/puppet/pops/validation/checker4_0.rb +1 -1
  132. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -1
  133. data/lib/puppet/property/list.rb +1 -1
  134. data/lib/puppet/provider/augeas/augeas.rb +2 -2
  135. data/lib/puppet/provider/cron/crontab.rb +13 -2
  136. data/lib/puppet/provider/package.rb +24 -0
  137. data/lib/puppet/provider/package/apt.rb +6 -1
  138. data/lib/puppet/provider/package/gem.rb +8 -2
  139. data/lib/puppet/provider/package/msi.rb +0 -15
  140. data/lib/puppet/provider/package/openbsd.rb +0 -24
  141. data/lib/puppet/provider/package/rpm.rb +3 -29
  142. data/lib/puppet/provider/package/windows.rb +0 -15
  143. data/lib/puppet/provider/package/yum.rb +101 -24
  144. data/lib/puppet/provider/package/yumhelper.py +31 -1
  145. data/lib/puppet/provider/package/zypper.rb +10 -28
  146. data/lib/puppet/provider/service/debian.rb +1 -1
  147. data/lib/puppet/provider/service/init.rb +3 -0
  148. data/lib/puppet/provider/service/openbsd.rb +318 -0
  149. data/lib/puppet/provider/service/redhat.rb +6 -3
  150. data/lib/puppet/provider/service/systemd.rb +2 -2
  151. data/lib/puppet/provider/yumrepo/inifile.rb +115 -42
  152. data/lib/puppet/resource.rb +13 -9
  153. data/lib/puppet/resource/catalog.rb +12 -6
  154. data/lib/puppet/resource/type_collection.rb +3 -3
  155. data/lib/puppet/settings.rb +57 -36
  156. data/lib/puppet/settings/config_file.rb +5 -0
  157. data/lib/puppet/settings/environment_conf.rb +147 -0
  158. data/lib/puppet/settings/ttl_setting.rb +48 -0
  159. data/lib/puppet/ssl/certificate_authority.rb +2 -3
  160. data/lib/puppet/ssl/certificate_authority/autosign_command.rb +1 -1
  161. data/lib/puppet/ssl/certificate_request.rb +4 -4
  162. data/lib/puppet/ssl/validator/default_validator.rb +2 -2
  163. data/lib/puppet/status.rb +1 -1
  164. data/lib/puppet/test/test_helper.rb +1 -0
  165. data/lib/puppet/type/augeas.rb +13 -1
  166. data/lib/puppet/type/cron.rb +32 -18
  167. data/lib/puppet/type/file.rb +4 -2
  168. data/lib/puppet/type/file/checksum.rb +15 -5
  169. data/lib/puppet/type/file/content.rb +3 -1
  170. data/lib/puppet/type/file/source.rb +5 -5
  171. data/lib/puppet/type/package.rb +12 -17
  172. data/lib/puppet/type/resources.rb +3 -1
  173. data/lib/puppet/type/scheduled_task.rb +4 -5
  174. data/lib/puppet/type/service.rb +12 -2
  175. data/lib/puppet/type/user.rb +106 -0
  176. data/lib/puppet/type/yumrepo.rb +9 -1
  177. data/lib/puppet/util/checksums.rb +60 -1
  178. data/lib/puppet/util/diff.rb +3 -1
  179. data/lib/puppet/util/execution.rb +20 -16
  180. data/lib/puppet/util/feature.rb +3 -0
  181. data/lib/puppet/util/logging.rb +19 -12
  182. data/lib/puppet/util/rubygems.rb +10 -0
  183. data/lib/puppet/util/watched_file.rb +1 -1
  184. data/lib/puppet/util/windows/security.rb +5 -3
  185. data/lib/puppet/vendor/load_semantic.rb +1 -0
  186. data/lib/puppet/vendor/require_vendored.rb +2 -0
  187. data/lib/puppet/vendor/semantic/Gemfile +20 -0
  188. data/lib/puppet/vendor/semantic/Rakefile +69 -0
  189. data/lib/puppet/vendor/semantic/lib/semantic.rb +7 -0
  190. data/lib/puppet/vendor/semantic/lib/semantic/dependency.rb +181 -0
  191. data/lib/puppet/vendor/semantic/lib/semantic/dependency/graph.rb +60 -0
  192. data/lib/puppet/vendor/semantic/lib/semantic/dependency/graph_node.rb +117 -0
  193. data/lib/puppet/vendor/semantic/lib/semantic/dependency/module_release.rb +46 -0
  194. data/lib/puppet/vendor/semantic/lib/semantic/dependency/source.rb +25 -0
  195. data/lib/puppet/vendor/semantic/lib/semantic/dependency/unsatisfiable_graph.rb +31 -0
  196. data/lib/puppet/vendor/semantic/lib/semantic/version.rb +168 -0
  197. data/lib/puppet/vendor/semantic/lib/semantic/version_range.rb +424 -0
  198. data/lib/puppet/vendor/semantic/spec/spec_helper.rb +24 -0
  199. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_node_spec.rb +141 -0
  200. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/graph_spec.rb +162 -0
  201. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/module_release_spec.rb +143 -0
  202. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/source_spec.rb +5 -0
  203. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency/unsatisfiable_graph_spec.rb +44 -0
  204. data/lib/puppet/vendor/semantic/spec/unit/semantic/dependency_spec.rb +383 -0
  205. data/lib/puppet/vendor/semantic/spec/unit/semantic/version_range_spec.rb +307 -0
  206. data/lib/puppet/vendor/semantic/spec/unit/semantic/version_spec.rb +608 -0
  207. data/lib/puppet/version.rb +1 -1
  208. data/spec/fixtures/java.tgz +0 -0
  209. data/spec/fixtures/stdlib.tgz +0 -0
  210. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/usee/lib/puppet/functions/usee/callee.rb +5 -0
  211. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/user/lib/puppet/functions/user/caller.rb +5 -0
  212. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/user/metadata.json +9 -0
  213. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/lib/puppet/functions/modulea/rb_func_a.rb +5 -0
  214. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/lib/puppet/functions/rb_func_a.rb +5 -0
  215. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/manifests/init.pp +3 -0
  216. data/spec/fixtures/unit/pops/loaders/loaders/single_module/modules/modulea/metadata.json +19 -0
  217. data/spec/fixtures/unit/pops/loaders/loaders/wo_metadata_module/modules/moduleb/lib/puppet/functions/moduleb/rb_func_b.rb +6 -0
  218. data/spec/fixtures/unit/pops/loaders/loaders/wo_metadata_module/modules/moduleb/manifests/init.pp +3 -0
  219. data/spec/fixtures/unit/provider/naginator/define_empty_param +6 -0
  220. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services +7 -0
  221. data/spec/fixtures/unit/type/user/authorized_keys +5 -0
  222. data/spec/integration/application/apply_spec.rb +1 -2
  223. data/spec/integration/configurer_spec.rb +2 -2
  224. data/spec/integration/faces/plugin_spec.rb +62 -0
  225. data/spec/integration/indirector/catalog/compiler_spec.rb +1 -1
  226. data/spec/integration/indirector/catalog/queue_spec.rb +1 -1
  227. data/spec/integration/node/environment_spec.rb +2 -2
  228. data/spec/integration/parser/future_compiler_spec.rb +96 -142
  229. data/spec/integration/parser/ruby_manifest_spec.rb +0 -5
  230. data/spec/integration/provider/cron/crontab_spec.rb +35 -0
  231. data/spec/integration/type/file_spec.rb +74 -72
  232. data/spec/integration/util/windows/security_spec.rb +17 -0
  233. data/spec/lib/matchers/resource.rb +45 -13
  234. data/spec/lib/puppet_spec/files.rb +18 -0
  235. data/spec/lib/puppet_spec/module_tool/shared_functions.rb +56 -0
  236. data/spec/lib/puppet_spec/module_tool/stub_source.rb +133 -0
  237. data/spec/shared_contexts/checksums.rb +55 -0
  238. data/spec/unit/application/apply_spec.rb +10 -7
  239. data/spec/unit/application/doc_spec.rb +17 -10
  240. data/spec/unit/application/indirection_base_spec.rb +18 -10
  241. data/spec/unit/application/inspect_spec.rb +22 -20
  242. data/spec/unit/configurer/downloader_spec.rb +7 -6
  243. data/spec/unit/configurer/plugin_handler_spec.rb +5 -8
  244. data/spec/unit/configurer_spec.rb +1 -1
  245. data/spec/unit/context_spec.rb +23 -0
  246. data/spec/unit/environments_spec.rb +274 -16
  247. data/spec/unit/face/config_spec.rb +111 -11
  248. data/spec/unit/face/module/install_spec.rb +14 -85
  249. data/spec/unit/face/module/list_spec.rb +108 -62
  250. data/spec/unit/face/module/search_spec.rb +1 -1
  251. data/spec/unit/face/module/uninstall_spec.rb +21 -42
  252. data/spec/unit/face/parser_spec.rb +5 -2
  253. data/spec/unit/file_bucket/dipper_spec.rb +92 -86
  254. data/spec/unit/file_bucket/file_spec.rb +23 -75
  255. data/spec/unit/file_serving/metadata_spec.rb +74 -74
  256. data/spec/unit/forge/module_release_spec.rb +131 -0
  257. data/spec/unit/forge/repository_spec.rb +21 -20
  258. data/spec/unit/forge_spec.rb +99 -23
  259. data/spec/unit/functions/assert_type_spec.rb +59 -0
  260. data/spec/unit/functions4_spec.rb +671 -0
  261. data/spec/unit/indirector/catalog/static_compiler_spec.rb +2 -2
  262. data/spec/unit/indirector/facts/facter_spec.rb +9 -3
  263. data/spec/unit/indirector/file_bucket_file/file_spec.rb +156 -155
  264. data/spec/unit/indirector/rest_spec.rb +8 -0
  265. data/spec/unit/interface/face_collection_spec.rb +35 -23
  266. data/spec/unit/module_spec.rb +20 -8
  267. data/spec/unit/module_tool/applications/builder_spec.rb +40 -12
  268. data/spec/unit/module_tool/applications/checksummer_spec.rb +86 -105
  269. data/spec/unit/module_tool/applications/installer_spec.rb +293 -261
  270. data/spec/unit/module_tool/applications/searcher_spec.rb +1 -1
  271. data/spec/unit/module_tool/applications/uninstaller_spec.rb +90 -154
  272. data/spec/unit/module_tool/applications/unpacker_spec.rb +12 -12
  273. data/spec/unit/module_tool/applications/upgrader_spec.rb +286 -18
  274. data/spec/unit/module_tool/metadata_spec.rb +223 -14
  275. data/spec/unit/module_tool/tar/gnu_spec.rb +12 -9
  276. data/spec/unit/module_tool/tar/mini_spec.rb +1 -1
  277. data/spec/unit/module_tool/tar_spec.rb +4 -18
  278. data/spec/unit/module_tool_spec.rb +123 -27
  279. data/spec/unit/network/formats_spec.rb +2 -2
  280. data/spec/unit/network/http_pool_spec.rb +21 -0
  281. data/spec/unit/network/rights_spec.rb +10 -8
  282. data/spec/unit/node/environment_spec.rb +27 -2
  283. data/spec/unit/parser/collector_spec.rb +1 -1
  284. data/spec/unit/parser/compiler_spec.rb +1 -1
  285. data/spec/unit/parser/functions/generate_spec.rb +4 -0
  286. data/spec/unit/pops/evaluator/access_ops_spec.rb +50 -11
  287. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +25 -0
  288. data/spec/unit/pops/loaders/dependency_loader_spec.rb +44 -0
  289. data/spec/unit/pops/loaders/loader_paths_spec.rb +66 -0
  290. data/spec/unit/pops/loaders/loaders_spec.rb +105 -0
  291. data/spec/unit/pops/loaders/module_loaders_spec.rb +119 -0
  292. data/spec/unit/pops/loaders/static_loader_spec.rb +46 -0
  293. data/spec/unit/pops/types/type_calculator_spec.rb +145 -10
  294. data/spec/unit/pops/types/type_factory_spec.rb +101 -0
  295. data/spec/unit/pops/types/type_parser_spec.rb +22 -0
  296. data/spec/unit/property/list_spec.rb +9 -1
  297. data/spec/unit/provider/augeas/augeas_spec.rb +58 -11
  298. data/spec/unit/provider/cron/crontab_spec.rb +1 -0
  299. data/spec/unit/provider/cron/parsed_spec.rb +15 -0
  300. data/spec/unit/provider/naginator_spec.rb +14 -0
  301. data/spec/unit/provider/package/apt_spec.rb +78 -64
  302. data/spec/unit/provider/package/gem_spec.rb +15 -0
  303. data/spec/unit/provider/package/rpm_spec.rb +6 -6
  304. data/spec/unit/provider/package/windows_spec.rb +1 -1
  305. data/spec/unit/provider/package/yum_spec.rb +199 -104
  306. data/spec/unit/provider/package/zypper_spec.rb +41 -15
  307. data/spec/unit/provider/service/openbsd_spec.rb +129 -22
  308. data/spec/unit/provider/service/redhat_spec.rb +18 -4
  309. data/spec/unit/provider/service/systemd_spec.rb +5 -9
  310. data/spec/unit/provider/service/upstart_spec.rb +1 -1
  311. data/spec/unit/provider/user/directoryservice_spec.rb +10 -0
  312. data/spec/unit/provider/yumrepo/inifile_spec.rb +171 -15
  313. data/spec/unit/resource/catalog_spec.rb +20 -104
  314. data/spec/unit/resource/type_collection_spec.rb +10 -9
  315. data/spec/unit/settings/config_file_spec.rb +29 -6
  316. data/spec/unit/settings/environment_conf_spec.rb +51 -0
  317. data/spec/unit/settings_spec.rb +97 -12
  318. data/spec/unit/ssl/certificate_authority_spec.rb +2 -0
  319. data/spec/unit/type/augeas_spec.rb +1 -1
  320. data/spec/unit/type/cron_spec.rb +6 -7
  321. data/spec/unit/type/file/checksum_spec.rb +6 -0
  322. data/spec/unit/type/file/content_spec.rb +277 -207
  323. data/spec/unit/type/file_spec.rb +9 -7
  324. data/spec/unit/type/user_spec.rb +106 -18
  325. data/spec/unit/type/yumrepo_spec.rb +8 -0
  326. data/spec/unit/util/checksums_spec.rb +12 -5
  327. data/spec/unit/util/diff_spec.rb +8 -0
  328. data/spec/unit/util/execution_spec.rb +4 -4
  329. data/spec/unit/util/feature_spec.rb +2 -0
  330. data/spec/unit/util/logging_spec.rb +14 -4
  331. data/spec/unit/util/rdoc/parser_spec.rb +5 -4
  332. data/spec/unit/util/rubygems_spec.rb +14 -0
  333. data/tasks/parallel.rake +2 -2
  334. metadata +154 -21
  335. checksums.yaml +0 -7
  336. data/lib/puppet/module_tool/applications/generator.rb +0 -142
  337. data/lib/puppet/module_tool/skeleton.rb +0 -37
  338. data/lib/puppet/module_tool/skeleton/templates/generator/Modulefile.erb +0 -11
  339. data/lib/puppet/module_tool/skeleton/templates/generator/README.erb +0 -16
  340. data/lib/puppet/module_tool/tar/solaris.rb +0 -5
  341. data/spec/fixtures/unit/provider/service/systemd/list_units_services +0 -17
  342. data/spec/unit/module_tool/tar/solaris_spec.rb +0 -22
@@ -1,5 +1,7 @@
1
1
  require 'uri'
2
2
 
3
+ require 'puppet/forge'
4
+
3
5
  class Puppet::Forge
4
6
  # = Cache
5
7
  #
@@ -44,7 +46,9 @@ class Puppet::Forge
44
46
 
45
47
  # Return the base Pathname for all the caches.
46
48
  def self.base_path
47
- Pathname(Puppet.settings[:module_working_dir]) + 'cache'
49
+ (Pathname(Puppet.settings[:module_working_dir]) + 'cache').tap do |o|
50
+ o.mkpath unless o.exist?
51
+ end
48
52
  end
49
53
 
50
54
  # Clean out all the caches.
@@ -1,4 +1,6 @@
1
+ require 'json'
1
2
  require 'puppet/error'
3
+ require 'puppet/forge'
2
4
 
3
5
  # Puppet::Forge specific exceptions
4
6
  module Puppet::Forge::Errors
@@ -80,6 +82,14 @@ Could not connect to #{@uri}
80
82
  response = options[:response]
81
83
  @response = "#{response.code} #{response.message.strip}"
82
84
 
85
+ begin
86
+ body = JSON.parse(response.body)
87
+ if body['message']
88
+ @message ||= body['message'].strip
89
+ end
90
+ rescue JSON::ParserError
91
+ end
92
+
83
93
  message = "Could not execute operation for '#{@input}'. Detail: "
84
94
  message << @message << " / " if @message
85
95
  message << @response << "."
@@ -2,6 +2,8 @@ require 'net/https'
2
2
  require 'digest/sha1'
3
3
  require 'uri'
4
4
  require 'puppet/util/http_proxy'
5
+ require 'puppet/forge'
6
+ require 'puppet/forge/errors'
5
7
 
6
8
  if Puppet.features.zlib? && Puppet[:zlib]
7
9
  require 'zlib'
@@ -35,21 +37,39 @@ class Puppet::Forge
35
37
  end
36
38
 
37
39
  # Instantiate a new repository instance rooted at the +url+.
38
- # The agent will report +consumer_version+ in the User-Agent to
39
- # the repository.
40
- def initialize(url, consumer_version)
41
- @uri = url.is_a?(::URI) ? url : ::URI.parse(url)
40
+ # The library will report +for_agent+ in the User-Agent to the repository.
41
+ def initialize(host, for_agent)
42
+ @host = host
43
+ @agent = for_agent
42
44
  @cache = Cache.new(self)
43
- @consumer_version = consumer_version
45
+ @uri = URI.parse(host)
44
46
  end
45
47
 
46
- # Return a Net::HTTPResponse read for this +request_path+.
47
- def make_http_request(request_path)
48
- request = Net::HTTP::Get.new(URI.escape(@uri.path + request_path), { "User-Agent" => user_agent })
49
- if ! @uri.user.nil? && ! @uri.password.nil?
48
+ # Return a Net::HTTPResponse read for this +path+.
49
+ def make_http_request(path, io = nil)
50
+ Puppet.debug "HTTP GET #{@host}#{path}"
51
+ request = get_request_object(path)
52
+ return read_response(request, io)
53
+ end
54
+
55
+ def get_request_object(path)
56
+ headers = {
57
+ "User-Agent" => user_agent,
58
+ }
59
+
60
+ if Puppet.features.zlib? && Puppet[:zlib] && RUBY_VERSION >= "1.9"
61
+ headers = headers.merge({
62
+ "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
63
+ })
64
+ end
65
+
66
+ request = Net::HTTP::Get.new(URI.escape(path), headers)
67
+
68
+ unless @uri.user.nil? || @uri.password.nil?
50
69
  request.basic_auth(@uri.user, @uri.password)
51
70
  end
52
- return read_response(request)
71
+
72
+ return request
53
73
  end
54
74
 
55
75
  # Return a Net::HTTPResponse read from this HTTPRequest +request+.
@@ -60,11 +80,27 @@ class Puppet::Forge
60
80
  # related error
61
81
  # @raise [Puppet::Forge::Errors::SSLVerifyError] if there is a problem
62
82
  # verifying the remote SSL certificate
63
- def read_response(request)
83
+ def read_response(request, io = nil)
64
84
  http_object = get_http_object
65
85
 
66
86
  http_object.start do |http|
67
- http.request(request)
87
+ response = http.request(request)
88
+
89
+ if Puppet.features.zlib? && Puppet[:zlib]
90
+ if response && response.key?("content-encoding")
91
+ case response["content-encoding"]
92
+ when "gzip"
93
+ response.body = Zlib::GzipReader.new(StringIO.new(response.read_body), :encoding => "ASCII-8BIT").read
94
+ response.delete("content-encoding")
95
+ when "deflate"
96
+ response.body = Zlib::Inflate.inflate(response.read_body)
97
+ response.delete("content-encoding")
98
+ end
99
+ end
100
+ end
101
+
102
+ io.write(response.body) if io.respond_to? :write
103
+ response
68
104
  end
69
105
  rescue *NET_HTTP_EXCEPTIONS => e
70
106
  raise CommunicationError.new(:uri => @uri.to_s, :original => e)
@@ -103,33 +139,32 @@ class Puppet::Forge
103
139
  # Return the local file name containing the data downloaded from the
104
140
  # repository at +release+ (e.g. "myuser-mymodule").
105
141
  def retrieve(release)
106
- uri = @uri.dup
107
- uri.path = uri.path.chomp('/') + release
108
- return cache.retrieve(uri)
142
+ path = @host.chomp('/') + release
143
+ return cache.retrieve(path)
109
144
  end
110
145
 
111
146
  # Return the URI string for this repository.
112
147
  def to_s
113
- return @uri.to_s
148
+ "#<#{self.class} #{@host}>"
114
149
  end
115
150
 
116
151
  # Return the cache key for this repository, this a hashed string based on
117
152
  # the URI.
118
153
  def cache_key
119
154
  return @cache_key ||= [
120
- @uri.to_s.gsub(/[^[:alnum:]]+/, '_').sub(/_$/, ''),
121
- Digest::SHA1.hexdigest(@uri.to_s)
122
- ].join('-')
155
+ @host.to_s.gsub(/[^[:alnum:]]+/, '_').sub(/_$/, ''),
156
+ Digest::SHA1.hexdigest(@host.to_s)
157
+ ].join('-').freeze
123
158
  end
124
159
 
125
- def user_agent
126
- "#{@consumer_version} Puppet/#{Puppet.version} (#{Facter.value(:operatingsystem)} #{Facter.value(:operatingsystemrelease)}) #{ruby_version}"
127
- end
128
- private :user_agent
160
+ private
129
161
 
130
- def ruby_version
131
- "Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE}; #{RUBY_PLATFORM})"
162
+ def user_agent
163
+ @user_agent ||= [
164
+ @agent,
165
+ "Puppet/#{Puppet.version}",
166
+ "Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})",
167
+ ].join(' ').freeze
132
168
  end
133
- private :ruby_version
134
169
  end
135
170
  end
@@ -0,0 +1,548 @@
1
+ # @note WARNING: This new function API is still under development and may change at any time
2
+ #
3
+ # Functions in the puppet language can be written in Ruby and distributed in
4
+ # puppet modules. The function is written by creating a file in the module's
5
+ # `lib/puppet/functions/<modulename>` directory, where `<modulename>` is
6
+ # replaced with the module's name. The file should have the name of the function.
7
+ # For example, to create a function named `min` in a module named `math` create
8
+ # a file named `lib/puppet/functions/math/min.rb` in the module.
9
+ #
10
+ # A function is implemented by calling {Puppet::Functions.create_function}, and
11
+ # passing it a block that defines the implementation of the function.
12
+ #
13
+ # Functions are namespaced inside the module that contains them. The name of
14
+ # the function is prefixed with the name of the module. For example,
15
+ # `math::min`.
16
+ #
17
+ # @example A simple function
18
+ # Puppet::Functions.create_function('math::min') do
19
+ # def min(a, b)
20
+ # a <= b ? a : b
21
+ # end
22
+ # end
23
+ #
24
+ # Anatomy of a function
25
+ # ---
26
+ #
27
+ # Functions are composed of four parts: the name, the implementation methods,
28
+ # the signatures, and the dispatches.
29
+ #
30
+ # The name is the string given to the {Puppet::Functions.create_function}
31
+ # method. It specifies the name to use when calling the function in the puppet
32
+ # language, or from other functions.
33
+ #
34
+ # The implementation methods are ruby methods (there can be one or more) that
35
+ # provide that actual implementation of the function's behavior. In the
36
+ # simplest case the name of the function (excluding any namespace) and the name
37
+ # of the method are the same. When that is done no other parts (signatures and
38
+ # dispatches) need to be used.
39
+ #
40
+ # Signatures are a way of specifying the types of the function's parameters.
41
+ # The types of any arguments will be checked against the types declared in the
42
+ # signature and an error will be produced if they don't match. The types are
43
+ # defined by using the same syntax for types as in the puppet language.
44
+ #
45
+ # Dispatches are how signatures and implementation methods are tied together.
46
+ # When the function is called, puppet searches the signatures for one that
47
+ # matches the supplied arguments. Each signature is part of a dispatch, which
48
+ # specifies the method that should be called for that signature. When a
49
+ # matching signature is found, the corrosponding method is called.
50
+ #
51
+ # Documentation for the function should be placed as comments to the
52
+ # implementation method(s).
53
+ #
54
+ # @todo Documentation for individual instances of these new functions is not
55
+ # yet tied into the puppet doc system.
56
+ #
57
+ # @example Dispatching to different methods by type
58
+ # Puppet::Functions.create_function('math::min') do
59
+ # dispatch :numeric_min do
60
+ # param 'Numeric', 'a'
61
+ # param 'Numeric', 'b'
62
+ # end
63
+ #
64
+ # dispatch :string_min do
65
+ # param 'String', 'a'
66
+ # param 'String', 'b'
67
+ # end
68
+ #
69
+ # def numeric_min(a, b)
70
+ # a <= b ? a : b
71
+ # end
72
+ #
73
+ # def string_min(a, b)
74
+ # a.downcase <= b.downcase ? a : b
75
+ # end
76
+ # end
77
+ #
78
+ # Specifying Signatures
79
+ # ---
80
+ #
81
+ # If nothing is specified, the number of arguments given to the function must
82
+ # be the same as the number of parameters, and all of the parameters are of
83
+ # type 'Object'.
84
+ #
85
+ # To express that the last parameter captures the rest, the method
86
+ # `last_captures_rest` can be called. This indicates that the last parameter is
87
+ # a varargs parameter and will be passed to the implementing method as an array
88
+ # of the given type.
89
+ #
90
+ # When defining a dispatch for a function, the resulting dispatch matches
91
+ # against the specified argument types and min/max occurrence of optional
92
+ # entries. When the dispatch makes the call to the implementation method the
93
+ # arguments are simply passed and it is the responsibility of the method's
94
+ # implementor to ensure it can handle those arguments (i.e. there is no check
95
+ # that what was declared as optional actually has a default value, and that
96
+ # a "captures rest" is declared using a `*`).
97
+ #
98
+ # @example Varargs
99
+ # Puppet::Functions.create_function('foo') do
100
+ # dispatch :foo do
101
+ # param 'Numeric', 'first'
102
+ # param 'Numeric', 'values'
103
+ # last_captures_rest
104
+ # end
105
+ #
106
+ # def foo(first, *values)
107
+ # # do something
108
+ # end
109
+ # end
110
+ #
111
+ # Access to Scope
112
+ # ---
113
+ # In general, functions should not need access to scope; they should be
114
+ # written to act on their given input only. If they absolutely must look up
115
+ # variable values, they should do so via the closure scope (the scope where
116
+ # they are defined) - this is done by calling `closure_scope()`.
117
+ #
118
+ # Calling other Functions
119
+ # ---
120
+ # Calling other functions by name is directly supported via
121
+ # {Puppet::Pops::Functions::Function#call_function}. This allows a function to
122
+ # call other functions visible from its loader.
123
+ #
124
+ # @api public
125
+ module Puppet::Functions
126
+ # @param func_name [String, Symbol] a simple or qualified function name
127
+ # @param block [Proc] the block that defines the methods and dispatch of the
128
+ # Function to create
129
+ # @return [Class<Function>] the newly created Function class
130
+ #
131
+ # @api public
132
+ def self.create_function(func_name, function_base = Function, &block)
133
+ if function_base.ancestors.none? { |s| s == Puppet::Pops::Functions::Function }
134
+ raise ArgumentError, "Functions must be based on Puppet::Pops::Functions::Function. Got #{function_base}"
135
+ end
136
+
137
+ func_name = func_name.to_s
138
+ # Creates an anonymous class to represent the function
139
+ # The idea being that it is garbage collected when there are no more
140
+ # references to it.
141
+ #
142
+ the_class = Class.new(function_base, &block)
143
+
144
+ # Make the anonymous class appear to have the class-name <func_name>
145
+ # Even if this class is not bound to such a symbol in a global ruby scope and
146
+ # must be resolved via the loader.
147
+ # This also overrides any attempt to define a name method in the given block
148
+ # (Since it redefines it)
149
+ #
150
+ # TODO, enforce name in lower case (to further make it stand out since Ruby
151
+ # class names are upper case)
152
+ #
153
+ the_class.instance_eval do
154
+ @func_name = func_name
155
+ def name
156
+ @func_name
157
+ end
158
+ end
159
+
160
+ # Automatically create an object dispatcher based on introspection if the
161
+ # loaded user code did not define any dispatchers. Fail if function name
162
+ # does not match a given method name in user code.
163
+ #
164
+ if the_class.dispatcher.empty?
165
+ simple_name = func_name.split(/::/)[-1]
166
+ type, names = default_dispatcher(the_class, simple_name)
167
+ last_captures_rest = (type.size_range[1] == Puppet::Pops::Types::INFINITY)
168
+ the_class.dispatcher.add_dispatch(type, simple_name, names, nil, nil, nil, last_captures_rest)
169
+ end
170
+
171
+ # The function class is returned as the result of the create function method
172
+ the_class
173
+ end
174
+
175
+ # Creates a default dispatcher configured from a method with the same name as the function
176
+ #
177
+ # @api private
178
+ def self.default_dispatcher(the_class, func_name)
179
+ unless the_class.method_defined?(func_name)
180
+ raise ArgumentError, "Function Creation Error, cannot create a default dispatcher for function '#{func_name}', no method with this name found"
181
+ end
182
+ object_signature(*min_max_param(the_class.instance_method(func_name)))
183
+ end
184
+
185
+ # @api private
186
+ def self.min_max_param(method)
187
+ # Ruby 1.8.7 does not have support for details about parameters
188
+ if method.respond_to?(:parameters)
189
+ result = {:req => 0, :opt => 0, :rest => 0 }
190
+ # TODO: Optimize into one map iteration that produces names map, and sets
191
+ # count as side effect
192
+ method.parameters.each { |p| result[p[0]] += 1 }
193
+ from = result[:req]
194
+ to = result[:rest] > 0 ? :default : from + result[:opt]
195
+ names = method.parameters.map {|p| p[1].to_s }
196
+ else
197
+ # Cannot correctly compute the signature in Ruby 1.8.7 because arity for
198
+ # optional values is screwed up (there is no way to get the upper limit),
199
+ # an optional looks the same as a varargs In this case - the failure will
200
+ # simply come later when the call fails
201
+ #
202
+ arity = method.arity
203
+ from = arity >= 0 ? arity : -arity -1
204
+ to = arity >= 0 ? arity : :default # i.e. infinite (which is wrong when there are optional - flaw in 1.8.7)
205
+ names = [] # no names available
206
+ end
207
+ [from, to, names]
208
+ end
209
+
210
+ # Construct a signature consisting of Object type, with min, and max, and given names.
211
+ # (there is only one type entry). Note that this signature is Object, not Optional[Object].
212
+ #
213
+ # @api private
214
+ def self.object_signature(from, to, names)
215
+ # Construct the type for the signature
216
+ # Tuple[Object, from, to]
217
+ factory = Puppet::Pops::Types::TypeFactory
218
+ [factory.callable(factory.object, from, to), names]
219
+ end
220
+
221
+ # Function
222
+ # ===
223
+ # This class is the base class for all Puppet 4x Function API functions. A
224
+ # specialized class is created for each puppet function.
225
+ #
226
+ # @api public
227
+ class Function < Puppet::Pops::Functions::Function
228
+
229
+ # @api private
230
+ def self.builder
231
+ @type_parser ||= Puppet::Pops::Types::TypeParser.new
232
+ @all_callables ||= Puppet::Pops::Types::TypeFactory.all_callables
233
+ DispatcherBuilder.new(dispatcher, @type_parser, @all_callables)
234
+ end
235
+
236
+ # Dispatch any calls that match the signature to the provided method name.
237
+ #
238
+ # @param meth_name [Symbol] The name of the implementation method to call
239
+ # when the signature defined in the block matches the arguments to a call
240
+ # to the function.
241
+ # @return [Void]
242
+ #
243
+ # @api public
244
+ def self.dispatch(meth_name, &block)
245
+ builder().instance_eval do
246
+ dispatch(meth_name, &block)
247
+ end
248
+ end
249
+ end
250
+
251
+ # Public api methods of the DispatcherBuilder are available within dispatch()
252
+ # blocks declared in a Puppet::Function.create_function() call.
253
+ #
254
+ # @api public
255
+ class DispatcherBuilder
256
+ # @api private
257
+ def initialize(dispatcher, type_parser, all_callables)
258
+ @type_parser = type_parser
259
+ @all_callables = all_callables
260
+ @dispatcher = dispatcher
261
+ end
262
+
263
+ # Defines a positional parameter with type and name
264
+ #
265
+ # @param type [String] The type specification for the parameter.
266
+ # @param name [String] The name of the parameter. This is primarily used
267
+ # for error message output and does not have to match the name of the
268
+ # parameter on the implementation method.
269
+ # @return [Void]
270
+ #
271
+ # @api public
272
+ def param(type, name)
273
+ if type.is_a?(String)
274
+ @types << type
275
+ @names << name
276
+ # mark what should be picked for this position when dispatching
277
+ @weaving << @names.size()-1
278
+ else
279
+ raise ArgumentError, "Type signature argument must be a String reference to a Puppet Data Type. Got #{type.class}"
280
+ end
281
+ end
282
+
283
+ # Defines one required block parameter that may appear last. If type and name is missing the
284
+ # default type is "Callable", and the name is "block". If only one
285
+ # parameter is given, then that is the name and the type is "Callable".
286
+ #
287
+ # @api public
288
+ def required_block_param(*type_and_name)
289
+ case type_and_name.size
290
+ when 0
291
+ type = @all_callables
292
+ name = 'block'
293
+ when 1
294
+ type = @all_callables
295
+ name = type_and_name[0]
296
+ when 2
297
+ type_string, name = type_and_name
298
+ type = @type_parser.parse(type_string)
299
+ else
300
+ raise ArgumentError, "block_param accepts max 2 arguments (type, name), got #{type_and_name.size}."
301
+ end
302
+
303
+ unless type.is_a?(Puppet::Pops::Types::PCallableType)
304
+ raise ArgumentError, "Expected PCallableType, got #{type.class}"
305
+ end
306
+
307
+ unless name.is_a?(String)
308
+ raise ArgumentError, "Expected block_param name to be a String, got #{name.class}"
309
+ end
310
+
311
+ if @block_type.nil?
312
+ @block_type = type
313
+ @block_name = name
314
+ else
315
+ raise ArgumentError, "Attempt to redefine block"
316
+ end
317
+ end
318
+
319
+ # Defines one optional block parameter that may appear last. If type or name is missing the
320
+ # defaults are "any callable", and the name is "block". The implementor of the dispatch target
321
+ # must use block = nil when it is optional (or an error is raised when the call is made).
322
+ #
323
+ # @api public
324
+ def optional_block_param(*type_and_name)
325
+ # same as required, only wrap the result in an optional type
326
+ required_block_param(*type_and_name)
327
+ @block_type = Puppet::Pops::Types::TypeFactory.optional(@block_type)
328
+ end
329
+
330
+ # Specifies the min and max occurance of arguments (of the specified types)
331
+ # if something other than the exact count from the number of specified
332
+ # types). The max value may be specified as -1 if an infinite number of
333
+ # arguments are supported. When max is > than the number of specified
334
+ # types, the last specified type repeats.
335
+ #
336
+ # @api public
337
+ def arg_count(min_occurs, max_occurs)
338
+ @min = min_occurs
339
+ @max = max_occurs
340
+ unless min_occurs.is_a?(Integer) && min_occurs >= 0
341
+ raise ArgumentError, "min arg_count of function parameter must be an Integer >=0, got #{min_occurs.class} '#{min_occurs}'"
342
+ end
343
+ unless max_occurs == :default || (max_occurs.is_a?(Integer) && max_occurs >= 0)
344
+ raise ArgumentError, "max arg_count of function parameter must be an Integer >= 0, or :default, got #{max_occurs.class} '#{max_occurs}'"
345
+ end
346
+ unless max_occurs == :default || (max_occurs.is_a?(Integer) && max_occurs >= min_occurs)
347
+ raise ArgumentError, "max arg_count must be :default (infinite) or >= min arg_count, got min: '#{min_occurs}, max: '#{max_occurs}'"
348
+ end
349
+ end
350
+
351
+ # Specifies that the last argument captures the rest.
352
+ #
353
+ # @api public
354
+ def last_captures_rest
355
+ @last_captures = true
356
+ end
357
+
358
+ private
359
+
360
+ # @api private
361
+ def dispatch(meth_name, &block)
362
+ # an array of either an index into names/types, or an array with
363
+ # injection information [type, name, injection_name] used when the call
364
+ # is being made to weave injections into the given arguments.
365
+ #
366
+ @types = []
367
+ @names = []
368
+ @weaving = []
369
+ @injections = []
370
+ @min = nil
371
+ @max = nil
372
+ @last_captures = false
373
+ @block_type = nil
374
+ @block_name = nil
375
+ self.instance_eval &block
376
+ callable_t = create_callable(@types, @block_type, @min, @max)
377
+ @dispatcher.add_dispatch(callable_t, meth_name, @names, @block_name, @injections, @weaving, @last_captures)
378
+ end
379
+
380
+ # Handles creation of a callable type from strings specifications of puppet
381
+ # types and allows the min/max occurs of the given types to be given as one
382
+ # or two integer values at the end. The given block_type should be
383
+ # Optional[Callable], Callable, or nil.
384
+ #
385
+ # @api private
386
+ def create_callable(types, block_type, from, to)
387
+ mapped_types = types.map do |t|
388
+ @type_parser.parse(t)
389
+ end
390
+
391
+ if !(from.nil? && to.nil?)
392
+ mapped_types << from
393
+ mapped_types << to
394
+ end
395
+
396
+ if block_type
397
+ mapped_types << block_type
398
+ end
399
+
400
+ Puppet::Pops::Types::TypeFactory.callable(*mapped_types)
401
+ end
402
+ end
403
+
404
+ private
405
+
406
+ # @note WARNING: This style of creating functions is not public. It is a system
407
+ # under development that will be used for creating "system" functions.
408
+ #
409
+ # This is a private, internal, system for creating functions. It supports
410
+ # everything that the public function definition system supports as well as a
411
+ # few extra features.
412
+ #
413
+ # Injection Support
414
+ # ===
415
+ # The Function API supports injection of data and services. It is possible to
416
+ # make injection that takes effect when the function is loaded (for services
417
+ # and runtime configuration that does not change depending on how/from where
418
+ # in what context the function is called. It is also possible to inject and
419
+ # weave argument values into a call.
420
+ #
421
+ # Injection of attributes
422
+ # ---
423
+ # Injection of attributes is performed by one of the methods `attr_injected`,
424
+ # and `attr_injected_producer`. The injected attributes are available via
425
+ # accessor method calls.
426
+ #
427
+ # @example using injected attributes
428
+ # Puppet::Functions.create_function('test') do
429
+ # attr_injected String, :larger, 'message_larger'
430
+ # attr_injected String, :smaller, 'message_smaller'
431
+ # def test(a, b)
432
+ # a > b ? larger() : smaller()
433
+ # end
434
+ # end
435
+ #
436
+ # @api private
437
+ class InternalFunction < Function
438
+ # @api private
439
+ def self.builder
440
+ @type_parser ||= Puppet::Pops::Types::TypeParser.new
441
+ @all_callables ||= Puppet::Pops::Types::TypeFactory.all_callables
442
+ InternalDispatchBuilder.new(dispatcher, @type_parser, @all_callables)
443
+ end
444
+
445
+ # Defines class level injected attribute with reader method
446
+ #
447
+ # @api private
448
+ def self.attr_injected(type, attribute_name, injection_name = nil)
449
+ define_method(attribute_name) do
450
+ ivar = :"@#{attribute_name.to_s}"
451
+ unless instance_variable_defined?(ivar)
452
+ injector = Puppet.lookup(:injector)
453
+ instance_variable_set(ivar, injector.lookup(closure_scope, type, injection_name))
454
+ end
455
+ instance_variable_get(ivar)
456
+ end
457
+ end
458
+
459
+ # Defines class level injected producer attribute with reader method
460
+ #
461
+ # @api private
462
+ def self.attr_injected_producer(type, attribute_name, injection_name = nil)
463
+ define_method(attribute_name) do
464
+ ivar = :"@#{attribute_name.to_s}"
465
+ unless instance_variable_defined?(ivar)
466
+ injector = Puppet.lookup(:injector)
467
+ instance_variable_set(ivar, injector.lookup_producer(closure_scope, type, injection_name))
468
+ end
469
+ instance_variable_get(ivar)
470
+ end
471
+ end
472
+ end
473
+
474
+ # @note WARNING: This style of creating functions is not public. It is a system
475
+ # under development that will be used for creating "system" functions.
476
+ #
477
+ # Injection and Weaving of parameters
478
+ # ---
479
+ # It is possible to inject and weave parameters into a call. These extra
480
+ # parameters are not part of the parameters passed from the Puppet logic, and
481
+ # they can not be overridden by parameters given as arguments in the call.
482
+ # They are invisible to the Puppet Language.
483
+ #
484
+ # @example using injected parameters
485
+ # Puppet::Functions.create_function('test') do
486
+ # dispatch :test do
487
+ # param 'Scalar', 'a'
488
+ # param 'Scalar', 'b'
489
+ # injected_param 'String', 'larger', 'message_larger'
490
+ # injected_param 'String', 'smaller', 'message_smaller'
491
+ # end
492
+ # def test(a, b, larger, smaller)
493
+ # a > b ? larger : smaller
494
+ # end
495
+ # end
496
+ #
497
+ # The function in the example above is called like this:
498
+ #
499
+ # test(10, 20)
500
+ #
501
+ # Using injected value as default
502
+ # ---
503
+ # Default value assignment is handled by using the regular Ruby mechanism (a
504
+ # value is assigned to the variable). The dispatch simply indicates that the
505
+ # value is optional. If the default value should be injected, it can be
506
+ # handled different ways depending on what is desired:
507
+ #
508
+ # * by calling the accessor method for an injected Function class attribute.
509
+ # This is suitable if the value is constant across all instantiations of the
510
+ # function, and across all calls.
511
+ # * by injecting a parameter into the call
512
+ # to the left of the parameter, and then assigning that as the default value.
513
+ # * One of the above forms, but using an injected producer instead of a
514
+ # directly injected value.
515
+ #
516
+ # @example method with injected default values
517
+ # Puppet::Functions.create_function('test') do
518
+ # dispatch :test do
519
+ # injected_param String, 'b_default', 'b_default_value_key'
520
+ # param 'Scalar', 'a'
521
+ # param 'Scalar', 'b'
522
+ # end
523
+ # def test(b_default, a, b = b_default)
524
+ # # ...
525
+ # end
526
+ # end
527
+ #
528
+ # @api private
529
+ class InternalDispatchBuilder < DispatcherBuilder
530
+ # TODO: is param name really needed? Perhaps for error messages? (it is unused now)
531
+ #
532
+ # @api private
533
+ def injected_param(type, name, injection_name = '')
534
+ @injections << [type, name, injection_name]
535
+ # mark what should be picked for this position when dispatching
536
+ @weaving << [@injections.size() -1]
537
+ end
538
+
539
+ # TODO: is param name really needed? Perhaps for error messages? (it is unused now)
540
+ #
541
+ # @api private
542
+ def injected_producer_param(type, name, injection_name = '')
543
+ @injections << [type, name, injection_name, :producer]
544
+ # mark what should be picked for this position when dispatching
545
+ @weaving << [@injections.size()-1]
546
+ end
547
+ end
548
+ end