puppet 3.4.3 → 3.5.0.rc1

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 (811) hide show
  1. data/CONTRIBUTING.md +6 -6
  2. data/Gemfile +22 -16
  3. data/LICENSE +1 -1
  4. data/README.md +33 -11
  5. data/Rakefile +1 -1
  6. data/conf/auth.conf +4 -0
  7. data/ext/build_defaults.yaml +1 -1
  8. data/ext/debian/control +6 -6
  9. data/ext/ips/transforms +1 -1
  10. data/ext/nagios/naggen +1 -1
  11. data/ext/project_data.yaml +21 -1
  12. data/ext/puppet-test +3 -3
  13. data/ext/redhat/puppet.spec.erb +28 -2
  14. data/ext/suse/puppet.spec +1 -1
  15. data/ext/upload_facts.rb +1 -1
  16. data/ext/windows/service/daemon.rb +99 -20
  17. data/lib/hiera_puppet.rb +2 -2
  18. data/lib/puppet.rb +68 -5
  19. data/lib/puppet/agent.rb +5 -1
  20. data/lib/puppet/application.rb +20 -11
  21. data/lib/puppet/application/agent.rb +1 -1
  22. data/lib/puppet/application/apply.rb +61 -41
  23. data/lib/puppet/application/cert.rb +3 -3
  24. data/lib/puppet/application/device.rb +7 -8
  25. data/lib/puppet/application/doc.rb +1 -1
  26. data/lib/puppet/application/filebucket.rb +3 -3
  27. data/lib/puppet/application/kick.rb +2 -2
  28. data/lib/puppet/application/master.rb +1 -1
  29. data/lib/puppet/application/queue.rb +9 -9
  30. data/lib/puppet/application/resource.rb +2 -2
  31. data/lib/puppet/bindings.rb +6 -6
  32. data/lib/puppet/configurer.rb +17 -14
  33. data/lib/puppet/configurer/fact_handler.rb +1 -1
  34. data/lib/puppet/confine/any.rb +26 -0
  35. data/lib/puppet/confine/exists.rb +1 -1
  36. data/lib/puppet/confiner.rb +1 -0
  37. data/lib/puppet/context.rb +55 -0
  38. data/lib/puppet/context/trusted_information.rb +56 -0
  39. data/lib/puppet/defaults.rb +97 -26
  40. data/lib/puppet/environments.rb +187 -0
  41. data/lib/puppet/error.rb +2 -1
  42. data/lib/puppet/external/pson/common.rb +1 -1
  43. data/lib/puppet/external/pson/pure/generator.rb +1 -1
  44. data/lib/puppet/external/pson/pure/parser.rb +1 -1
  45. data/lib/puppet/face/config.rb +73 -15
  46. data/lib/puppet/face/file/store.rb +1 -1
  47. data/lib/puppet/face/help.rb +2 -1
  48. data/lib/puppet/face/help/action.erb +1 -0
  49. data/lib/puppet/face/help/face.erb +1 -0
  50. data/lib/puppet/face/help/global.erb +1 -0
  51. data/lib/puppet/face/help/man.erb +9 -8
  52. data/lib/puppet/face/module/list.rb +13 -7
  53. data/lib/puppet/face/node/clean.rb +2 -2
  54. data/lib/puppet/face/parser.rb +11 -5
  55. data/lib/puppet/face/status.rb +1 -1
  56. data/lib/puppet/feature/external_facts.rb +2 -2
  57. data/lib/puppet/feature/libuser.rb +1 -1
  58. data/lib/puppet/feature/msgpack.rb +2 -0
  59. data/lib/puppet/feature/rails.rb +2 -2
  60. data/lib/puppet/file_bucket/dipper.rb +9 -9
  61. data/lib/puppet/file_bucket/file.rb +9 -5
  62. data/lib/puppet/file_serving/base.rb +1 -1
  63. data/lib/puppet/file_serving/configuration.rb +1 -1
  64. data/lib/puppet/file_serving/configuration/parser.rb +3 -3
  65. data/lib/puppet/file_serving/content.rb +2 -2
  66. data/lib/puppet/file_serving/fileset.rb +4 -4
  67. data/lib/puppet/file_serving/metadata.rb +69 -15
  68. data/lib/puppet/file_serving/mount/file.rb +1 -1
  69. data/lib/puppet/file_system.rb +361 -1
  70. data/lib/puppet/file_system/file18.rb +3 -3
  71. data/lib/puppet/file_system/file19.rb +3 -3
  72. data/lib/puppet/file_system/file19windows.rb +18 -23
  73. data/lib/puppet/file_system/file_impl.rb +145 -0
  74. data/lib/puppet/file_system/memory_file.rb +23 -9
  75. data/lib/puppet/file_system/memory_impl.rb +64 -0
  76. data/lib/puppet/forge.rb +4 -3
  77. data/lib/puppet/forge/repository.rb +0 -1
  78. data/lib/puppet/graph/relationship_graph.rb +7 -7
  79. data/lib/puppet/indirector.rb +1 -0
  80. data/lib/puppet/indirector/catalog/compiler.rb +3 -30
  81. data/lib/puppet/indirector/catalog/msgpack.rb +6 -0
  82. data/lib/puppet/indirector/catalog/static_compiler.rb +3 -7
  83. data/lib/puppet/indirector/data_binding/hiera.rb +1 -1
  84. data/lib/puppet/indirector/direct_file_server.rb +2 -2
  85. data/lib/puppet/indirector/exec.rb +1 -1
  86. data/lib/puppet/indirector/face.rb +3 -2
  87. data/lib/puppet/indirector/facts/facter.rb +1 -1
  88. data/lib/puppet/indirector/file_bucket_file/file.rb +25 -15
  89. data/lib/puppet/indirector/file_metadata/file.rb +1 -1
  90. data/lib/puppet/indirector/file_server.rb +1 -1
  91. data/lib/puppet/indirector/indirection.rb +1 -1
  92. data/lib/puppet/indirector/json.rb +4 -4
  93. data/lib/puppet/indirector/key/file.rb +8 -5
  94. data/lib/puppet/indirector/ldap.rb +1 -1
  95. data/lib/puppet/indirector/memory.rb +4 -0
  96. data/lib/puppet/indirector/msgpack.rb +82 -0
  97. data/lib/puppet/indirector/node/exec.rb +1 -1
  98. data/lib/puppet/indirector/node/ldap.rb +3 -3
  99. data/lib/puppet/indirector/node/msgpack.rb +7 -0
  100. data/lib/puppet/indirector/node/yaml.rb +15 -0
  101. data/lib/puppet/indirector/queue.rb +3 -2
  102. data/lib/puppet/indirector/report/msgpack.rb +11 -0
  103. data/lib/puppet/indirector/request.rb +17 -20
  104. data/lib/puppet/indirector/resource/rest.rb +1 -1
  105. data/lib/puppet/indirector/resource_type/parser.rb +3 -13
  106. data/lib/puppet/indirector/rest.rb +6 -7
  107. data/lib/puppet/indirector/ssl_file.rb +7 -7
  108. data/lib/puppet/indirector/yaml.rb +9 -13
  109. data/lib/puppet/metatype/manager.rb +12 -7
  110. data/lib/puppet/module.rb +14 -9
  111. data/lib/puppet/module_tool.rb +21 -26
  112. data/lib/puppet/module_tool/applications/application.rb +1 -1
  113. data/lib/puppet/module_tool/applications/generator.rb +2 -1
  114. data/lib/puppet/module_tool/applications/installer.rb +9 -4
  115. data/lib/puppet/module_tool/applications/uninstaller.rb +10 -7
  116. data/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  117. data/lib/puppet/module_tool/applications/upgrader.rb +11 -8
  118. data/lib/puppet/module_tool/checksums.rb +1 -1
  119. data/lib/puppet/module_tool/contents_description.rb +2 -0
  120. data/lib/puppet/module_tool/dependency.rb +4 -5
  121. data/lib/puppet/module_tool/errors.rb +2 -0
  122. data/lib/puppet/module_tool/install_directory.rb +3 -0
  123. data/lib/puppet/module_tool/metadata.rb +3 -5
  124. data/lib/puppet/module_tool/modulefile.rb +3 -0
  125. data/lib/puppet/module_tool/shared_behaviors.rb +6 -1
  126. data/lib/puppet/module_tool/skeleton.rb +3 -0
  127. data/lib/puppet/module_tool/tar.rb +3 -0
  128. data/lib/puppet/network/auth_config_parser.rb +1 -1
  129. data/lib/puppet/network/authconfig.rb +5 -2
  130. data/lib/puppet/network/authentication.rb +7 -2
  131. data/lib/puppet/network/authorization.rb +2 -2
  132. data/lib/puppet/network/format_support.rb +4 -0
  133. data/lib/puppet/network/formats.rb +9 -14
  134. data/lib/puppet/network/http.rb +11 -0
  135. data/lib/puppet/network/http/api.rb +0 -2
  136. data/lib/puppet/network/http/api/v1.rb +146 -11
  137. data/lib/puppet/network/http/api/v2.rb +32 -0
  138. data/lib/puppet/network/http/api/v2/authorization.rb +13 -0
  139. data/lib/puppet/network/http/api/v2/environments.rb +21 -0
  140. data/lib/puppet/network/http/connection.rb +94 -37
  141. data/lib/puppet/network/http/error.rb +69 -0
  142. data/lib/puppet/network/http/handler.rb +28 -196
  143. data/lib/puppet/network/http/issues.rb +9 -0
  144. data/lib/puppet/network/http/memory_response.rb +13 -0
  145. data/lib/puppet/network/http/rack/rest.rb +10 -18
  146. data/lib/puppet/network/http/request.rb +56 -0
  147. data/lib/puppet/network/http/response.rb +11 -0
  148. data/lib/puppet/network/http/route.rb +91 -0
  149. data/lib/puppet/network/http/webrick.rb +1 -1
  150. data/lib/puppet/network/http/webrick/rest.rb +7 -12
  151. data/lib/puppet/network/http_pool.rb +3 -3
  152. data/lib/puppet/network/rights.rb +4 -4
  153. data/lib/puppet/node.rb +23 -14
  154. data/lib/puppet/node/environment.rb +149 -125
  155. data/lib/puppet/node/facts.rb +6 -5
  156. data/lib/puppet/parameter.rb +1 -1
  157. data/lib/puppet/parser/ast.rb +1 -1
  158. data/lib/puppet/parser/ast/block_expression.rb +1 -6
  159. data/lib/puppet/parser/ast/collexpr.rb +54 -2
  160. data/lib/puppet/parser/ast/lambda.rb +9 -0
  161. data/lib/puppet/parser/ast/leaf.rb +15 -0
  162. data/lib/puppet/parser/ast/pops_bridge.rb +168 -0
  163. data/lib/puppet/parser/code_merger.rb +13 -0
  164. data/lib/puppet/parser/collector.rb +1 -1
  165. data/lib/puppet/parser/compiler.rb +28 -30
  166. data/lib/puppet/parser/e4_parser_adapter.rb +81 -0
  167. data/lib/puppet/parser/e_parser_adapter.rb +0 -1
  168. data/lib/puppet/parser/files.rb +12 -7
  169. data/lib/puppet/parser/functions.rb +36 -29
  170. data/lib/puppet/parser/functions/collect.rb +1 -1
  171. data/lib/puppet/parser/functions/defined.rb +40 -16
  172. data/lib/puppet/parser/functions/each.rb +55 -41
  173. data/lib/puppet/parser/functions/epp.rb +41 -0
  174. data/lib/puppet/parser/functions/extlookup.rb +2 -2
  175. data/lib/puppet/parser/functions/file.rb +1 -1
  176. data/lib/puppet/parser/functions/filter.rb +68 -16
  177. data/lib/puppet/parser/functions/generate.rb +1 -1
  178. data/lib/puppet/parser/functions/include.rb +3 -2
  179. data/lib/puppet/parser/functions/inline_epp.rb +79 -0
  180. data/lib/puppet/parser/functions/inline_template.rb +1 -1
  181. data/lib/puppet/parser/functions/lookup.rb +127 -27
  182. data/lib/puppet/parser/functions/map.rb +64 -12
  183. data/lib/puppet/parser/functions/reduce.rb +40 -16
  184. data/lib/puppet/parser/functions/select.rb +1 -1
  185. data/lib/puppet/parser/functions/slice.rb +42 -23
  186. data/lib/puppet/parser/grammar.ra +3 -0
  187. data/lib/puppet/parser/lexer.rb +10 -9
  188. data/lib/puppet/parser/parser.rb +15 -12
  189. data/lib/puppet/parser/parser_factory.rb +26 -1
  190. data/lib/puppet/parser/parser_support.rb +13 -4
  191. data/lib/puppet/parser/resource.rb +1 -1
  192. data/lib/puppet/parser/scope.rb +246 -97
  193. data/lib/puppet/parser/templatewrapper.rb +1 -1
  194. data/lib/puppet/parser/type_loader.rb +13 -2
  195. data/lib/puppet/pops.rb +15 -1
  196. data/lib/puppet/pops/adapters.rb +64 -32
  197. data/lib/puppet/pops/binder/binder.rb +122 -150
  198. data/lib/puppet/pops/binder/binder_issues.rb +1 -21
  199. data/lib/puppet/pops/binder/bindings_checker.rb +0 -20
  200. data/lib/puppet/pops/binder/bindings_composer.rb +4 -70
  201. data/lib/puppet/pops/binder/bindings_factory.rb +16 -58
  202. data/lib/puppet/pops/binder/bindings_label_provider.rb +0 -3
  203. data/lib/puppet/pops/binder/bindings_loader.rb +13 -4
  204. data/lib/puppet/pops/binder/bindings_model.rb +17 -31
  205. data/lib/puppet/pops/binder/bindings_model_dumper.rb +2 -20
  206. data/lib/puppet/pops/binder/config/binder_config.rb +8 -40
  207. data/lib/puppet/pops/binder/config/binder_config_checker.rb +2 -43
  208. data/lib/puppet/pops/binder/config/issues.rb +1 -21
  209. data/lib/puppet/pops/binder/injector.rb +86 -7
  210. data/lib/puppet/pops/binder/injector_entry.rb +6 -2
  211. data/lib/puppet/pops/binder/key_factory.rb +7 -1
  212. data/lib/puppet/pops/binder/lookup.rb +191 -0
  213. data/lib/puppet/pops/binder/producers.rb +5 -5
  214. data/lib/puppet/pops/binder/scheme_handler/symbolic_scheme.rb +2 -3
  215. data/lib/puppet/pops/binder/system_bindings.rb +4 -16
  216. data/lib/puppet/pops/containment.rb +72 -5
  217. data/lib/puppet/pops/evaluator/access_operator.rb +548 -0
  218. data/lib/puppet/pops/evaluator/closure.rb +57 -0
  219. data/lib/puppet/pops/evaluator/compare_operator.rb +168 -0
  220. data/lib/puppet/pops/evaluator/epp_evaluator.rb +87 -0
  221. data/lib/puppet/pops/evaluator/evaluator_impl.rb +1069 -0
  222. data/lib/puppet/pops/evaluator/external_syntax_support.rb +49 -0
  223. data/lib/puppet/pops/evaluator/relationship_operator.rb +156 -0
  224. data/lib/puppet/pops/evaluator/runtime3_support.rb +489 -0
  225. data/lib/puppet/pops/issue_reporter.rb +8 -4
  226. data/lib/puppet/pops/issues.rb +199 -4
  227. data/lib/puppet/pops/label_provider.rb +5 -0
  228. data/lib/puppet/pops/model/ast_transformer.rb +55 -31
  229. data/lib/puppet/pops/model/ast_tree_dumper.rb +9 -1
  230. data/lib/puppet/pops/model/factory.rb +265 -111
  231. data/lib/puppet/pops/model/model.rb +179 -140
  232. data/lib/puppet/pops/model/model_label_provider.rb +38 -9
  233. data/lib/puppet/pops/model/model_tree_dumper.rb +38 -13
  234. data/lib/puppet/pops/parser/code_merger.rb +17 -0
  235. data/lib/puppet/pops/parser/egrammar.ra +110 -61
  236. data/lib/puppet/pops/parser/eparser.rb +1415 -1092
  237. data/lib/puppet/pops/parser/epp_parser.rb +51 -0
  238. data/lib/puppet/pops/parser/epp_support.rb +247 -0
  239. data/lib/puppet/pops/parser/evaluating_parser.rb +53 -15
  240. data/lib/puppet/pops/parser/heredoc_support.rb +139 -0
  241. data/lib/puppet/pops/parser/interpolation_support.rb +227 -0
  242. data/lib/puppet/pops/parser/lexer.rb +83 -192
  243. data/lib/puppet/pops/parser/lexer2.rb +684 -0
  244. data/lib/puppet/pops/parser/lexer_support.rb +107 -0
  245. data/lib/puppet/pops/parser/locatable.rb +23 -0
  246. data/lib/puppet/pops/parser/locator.rb +291 -0
  247. data/lib/puppet/pops/parser/makefile +1 -8
  248. data/lib/puppet/pops/parser/parser_support.rb +76 -48
  249. data/lib/puppet/pops/parser/slurp_support.rb +95 -0
  250. data/lib/puppet/pops/patterns.rb +13 -4
  251. data/lib/puppet/pops/types/class_loader.rb +2 -2
  252. data/lib/puppet/pops/types/enumeration.rb +34 -0
  253. data/lib/puppet/pops/types/type_calculator.rb +983 -58
  254. data/lib/puppet/pops/types/type_factory.rb +203 -15
  255. data/lib/puppet/pops/types/type_parser.rb +355 -12
  256. data/lib/puppet/pops/types/types.rb +314 -24
  257. data/lib/puppet/pops/utils.rb +23 -7
  258. data/lib/puppet/pops/validation.rb +14 -8
  259. data/lib/puppet/pops/validation/checker3_1.rb +17 -12
  260. data/lib/puppet/pops/validation/checker4_0.rb +514 -0
  261. data/lib/puppet/pops/validation/validator_factory_4_0.rb +31 -0
  262. data/lib/puppet/pops/visitor.rb +146 -4
  263. data/lib/puppet/property.rb +1 -1
  264. data/lib/puppet/property/ensure.rb +1 -1
  265. data/lib/puppet/provider.rb +47 -26
  266. data/lib/puppet/provider/aixobject.rb +3 -3
  267. data/lib/puppet/provider/augeas/augeas.rb +11 -11
  268. data/lib/puppet/provider/cron/crontab.rb +10 -1
  269. data/lib/puppet/provider/exec.rb +1 -1
  270. data/lib/puppet/provider/exec/posix.rb +1 -1
  271. data/lib/puppet/provider/exec/windows.rb +1 -1
  272. data/lib/puppet/provider/file/posix.rb +2 -2
  273. data/lib/puppet/provider/file/windows.rb +15 -9
  274. data/lib/puppet/provider/group/aix.rb +2 -2
  275. data/lib/puppet/provider/macauthorization/macauthorization.rb +3 -3
  276. data/lib/puppet/provider/mount.rb +7 -0
  277. data/lib/puppet/provider/mount/parsed.rb +0 -1
  278. data/lib/puppet/provider/naginator.rb +1 -1
  279. data/lib/puppet/provider/nameservice.rb +3 -3
  280. data/lib/puppet/provider/nameservice/directoryservice.rb +3 -3
  281. data/lib/puppet/provider/package/aix.rb +1 -1
  282. data/lib/puppet/provider/package/appdmg.rb +1 -4
  283. data/lib/puppet/provider/package/apple.rb +1 -1
  284. data/lib/puppet/provider/package/apt.rb +1 -1
  285. data/lib/puppet/provider/package/blastwave.rb +1 -1
  286. data/lib/puppet/provider/package/fink.rb +1 -1
  287. data/lib/puppet/provider/package/gem.rb +3 -3
  288. data/lib/puppet/provider/package/openbsd.rb +6 -4
  289. data/lib/puppet/provider/package/pacman.rb +58 -5
  290. data/lib/puppet/provider/package/pip.rb +2 -2
  291. data/lib/puppet/provider/package/pkgdmg.rb +25 -10
  292. data/lib/puppet/provider/package/pkgin.rb +48 -23
  293. data/lib/puppet/provider/package/pkgutil.rb +1 -1
  294. data/lib/puppet/provider/package/ports.rb +1 -1
  295. data/lib/puppet/provider/package/portupgrade.rb +7 -7
  296. data/lib/puppet/provider/package/rpm.rb +16 -8
  297. data/lib/puppet/provider/package/windows.rb +1 -1
  298. data/lib/puppet/provider/package/windows/package.rb +1 -1
  299. data/lib/puppet/provider/parsedfile.rb +1 -1
  300. data/lib/puppet/provider/selboolean/getsetsebool.rb +1 -1
  301. data/lib/puppet/provider/selmodule/semodule.rb +5 -5
  302. data/lib/puppet/provider/service/base.rb +1 -1
  303. data/lib/puppet/provider/service/bsd.rb +3 -3
  304. data/lib/puppet/provider/service/daemontools.rb +20 -20
  305. data/lib/puppet/provider/service/debian.rb +1 -1
  306. data/lib/puppet/provider/service/freebsd.rb +3 -3
  307. data/lib/puppet/provider/service/gentoo.rb +2 -2
  308. data/lib/puppet/provider/service/init.rb +5 -5
  309. data/lib/puppet/provider/service/launchd.rb +4 -4
  310. data/lib/puppet/provider/service/redhat.rb +2 -2
  311. data/lib/puppet/provider/service/runit.rb +4 -4
  312. data/lib/puppet/provider/service/service.rb +3 -4
  313. data/lib/puppet/provider/service/smf.rb +1 -1
  314. data/lib/puppet/provider/service/src.rb +3 -3
  315. data/lib/puppet/provider/service/systemd.rb +4 -4
  316. data/lib/puppet/provider/service/upstart.rb +22 -7
  317. data/lib/puppet/provider/service/windows.rb +7 -7
  318. data/lib/puppet/provider/ssh_authorized_key/parsed.rb +3 -3
  319. data/lib/puppet/provider/user/aix.rb +5 -5
  320. data/lib/puppet/provider/user/directoryservice.rb +8 -5
  321. data/lib/puppet/provider/user/ldap.rb +1 -1
  322. data/lib/puppet/provider/user/pw.rb +1 -1
  323. data/lib/puppet/provider/user/user_role_add.rb +2 -2
  324. data/lib/puppet/provider/user/useradd.rb +19 -5
  325. data/lib/puppet/provider/yumrepo/inifile.rb +187 -0
  326. data/lib/puppet/provider/zone/solaris.rb +4 -4
  327. data/lib/puppet/rails.rb +16 -11
  328. data/lib/puppet/rails/benchmark.rb +1 -1
  329. data/lib/puppet/rails/resource.rb +5 -1
  330. data/lib/puppet/reference/configuration.rb +1 -1
  331. data/lib/puppet/reference/report.rb +1 -1
  332. data/lib/puppet/relationship.rb +10 -5
  333. data/lib/puppet/reports/http.rb +8 -2
  334. data/lib/puppet/reports/rrdgraph.rb +1 -1
  335. data/lib/puppet/reports/store.rb +3 -3
  336. data/lib/puppet/reports/tagmail.rb +4 -4
  337. data/lib/puppet/resource.rb +37 -44
  338. data/lib/puppet/resource/catalog.rb +18 -20
  339. data/lib/puppet/resource/status.rb +7 -6
  340. data/lib/puppet/resource/type.rb +6 -5
  341. data/lib/puppet/resource/type_collection.rb +2 -2
  342. data/lib/puppet/run.rb +9 -8
  343. data/lib/puppet/settings.rb +395 -244
  344. data/lib/puppet/settings/base_setting.rb +10 -4
  345. data/lib/puppet/settings/config_file.rb +81 -44
  346. data/lib/puppet/settings/directory_setting.rb +1 -2
  347. data/lib/puppet/settings/file_setting.rb +12 -5
  348. data/lib/puppet/settings/ini_file.rb +171 -0
  349. data/lib/puppet/ssl/base.rb +4 -0
  350. data/lib/puppet/ssl/certificate_authority.rb +16 -11
  351. data/lib/puppet/ssl/certificate_authority/interface.rb +3 -2
  352. data/lib/puppet/ssl/certificate_factory.rb +50 -5
  353. data/lib/puppet/ssl/certificate_request.rb +2 -2
  354. data/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
  355. data/lib/puppet/ssl/certificate_revocation_list.rb +3 -1
  356. data/lib/puppet/ssl/host.rb +9 -8
  357. data/lib/puppet/ssl/inventory.rb +1 -1
  358. data/lib/puppet/ssl/key.rb +1 -1
  359. data/lib/puppet/ssl/validator/default_validator.rb +1 -1
  360. data/lib/puppet/status.rb +8 -7
  361. data/lib/puppet/test/test_helper.rb +35 -4
  362. data/lib/puppet/transaction/event.rb +6 -5
  363. data/lib/puppet/transaction/report.rb +10 -10
  364. data/lib/puppet/type.rb +1 -3
  365. data/lib/puppet/type/augeas.rb +2 -1
  366. data/lib/puppet/type/cron.rb +41 -11
  367. data/lib/puppet/type/exec.rb +5 -5
  368. data/lib/puppet/type/file.rb +42 -4
  369. data/lib/puppet/type/file/content.rb +5 -6
  370. data/lib/puppet/type/file/ensure.rb +3 -3
  371. data/lib/puppet/type/file/source.rb +12 -6
  372. data/lib/puppet/type/file/target.rb +5 -5
  373. data/lib/puppet/type/k5login.rb +4 -4
  374. data/lib/puppet/type/mount.rb +1 -1
  375. data/lib/puppet/type/package.rb +79 -3
  376. data/lib/puppet/type/resources.rb +34 -5
  377. data/lib/puppet/type/selboolean.rb +1 -1
  378. data/lib/puppet/type/selmodule.rb +1 -1
  379. data/lib/puppet/type/ssh_authorized_key.rb +2 -1
  380. data/lib/puppet/type/sshkey.rb +2 -1
  381. data/lib/puppet/type/tidy.rb +1 -1
  382. data/lib/puppet/type/user.rb +4 -1
  383. data/lib/puppet/type/yumrepo.rb +219 -344
  384. data/lib/puppet/type/zone.rb +15 -5
  385. data/lib/puppet/util.rb +14 -13
  386. data/lib/puppet/util/adsi.rb +19 -3
  387. data/lib/puppet/util/autoload.rb +27 -24
  388. data/lib/puppet/util/backups.rb +6 -6
  389. data/lib/puppet/util/checksums.rb +2 -2
  390. data/lib/puppet/util/classgen.rb +1 -1
  391. data/lib/puppet/util/colors.rb +4 -12
  392. data/lib/puppet/util/command_line.rb +2 -2
  393. data/lib/puppet/util/command_line/trollop.rb +3 -3
  394. data/lib/puppet/util/docs.rb +2 -2
  395. data/lib/puppet/util/errors.rb +8 -1
  396. data/lib/puppet/util/execution.rb +12 -5
  397. data/lib/puppet/util/filetype.rb +5 -5
  398. data/lib/puppet/util/inifile.rb +19 -4
  399. data/lib/puppet/util/instrumentation/data.rb +5 -0
  400. data/lib/puppet/util/instrumentation/indirection_probe.rb +6 -1
  401. data/lib/puppet/util/instrumentation/listener.rb +6 -1
  402. data/lib/puppet/util/json_lockfile.rb +4 -1
  403. data/lib/puppet/util/ldap/connection.rb +1 -1
  404. data/lib/puppet/util/lockfile.rb +10 -6
  405. data/lib/puppet/util/log.rb +6 -1
  406. data/lib/puppet/util/log/destinations.rb +2 -2
  407. data/lib/puppet/util/metric.rb +9 -4
  408. data/lib/puppet/util/nagios_maker.rb +26 -1
  409. data/lib/puppet/util/network_device.rb +1 -1
  410. data/lib/puppet/util/network_device/config.rb +1 -1
  411. data/lib/puppet/util/network_device/transport/ssh.rb +3 -3
  412. data/lib/puppet/util/plugins.rb +1 -1
  413. data/lib/puppet/util/profiler.rb +13 -1
  414. data/lib/puppet/util/pson.rb +1 -1
  415. data/lib/puppet/util/queue/stomp.rb +2 -2
  416. data/lib/puppet/util/rdoc.rb +1 -1
  417. data/lib/puppet/util/rdoc/generators/puppet_generator.rb +1 -1
  418. data/lib/puppet/util/rdoc/parser/puppet_parser_core.rb +19 -19
  419. data/lib/puppet/util/reference.rb +1 -1
  420. data/lib/puppet/util/resource_template.rb +1 -1
  421. data/lib/puppet/util/retryaction.rb +1 -1
  422. data/lib/puppet/util/selinux.rb +2 -2
  423. data/lib/puppet/util/storage.rb +3 -3
  424. data/lib/puppet/util/symbolic_file_mode.rb +1 -1
  425. data/lib/puppet/util/tag_set.rb +15 -3
  426. data/lib/puppet/util/tagging.rb +12 -17
  427. data/lib/puppet/util/watched_file.rb +1 -1
  428. data/lib/puppet/util/watcher.rb +1 -1
  429. data/lib/puppet/util/windows/error.rb +2 -2
  430. data/lib/puppet/util/windows/file.rb +20 -4
  431. data/lib/puppet/util/windows/registry.rb +2 -2
  432. data/lib/puppet/vendor/safe_yaml/CHANGES.md +1 -1
  433. data/lib/puppet/version.rb +1 -1
  434. data/lib/puppetx.rb +1 -21
  435. data/lib/puppetx/puppet/syntax_checker.rb +1 -1
  436. data/lib/puppetx/puppetlabs/syntax_checkers/json.rb +9 -11
  437. data/spec/fixtures/integration/node/environment/sitedir/00_a.pp +2 -0
  438. data/spec/fixtures/integration/node/environment/sitedir/01_b.pp +6 -0
  439. data/spec/fixtures/{unit/pops/binder/hiera2/yaml_backend/empty/common.yaml → integration/node/environment/sitedir/03_empty.pp} +0 -0
  440. data/spec/fixtures/integration/node/environment/sitedir/04_include.pp +2 -0
  441. data/spec/fixtures/integration/provider/cron/crontab/purged +8 -0
  442. data/spec/fixtures/releases/jamtur01-apache/lib/puppet/provider/a2mod/debian.rb +1 -1
  443. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/binder_config.yaml +3 -12
  444. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/lib/puppet/bindings/confdirtest.rb +10 -0
  445. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome2/lib/puppet/bindings/awesome2/default.rb +20 -0
  446. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/{awesome/lib/puppetx/awesome → awesome2/lib/puppetx/awesome2}/echo_scheme_handler.rb +2 -2
  447. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/bad/lib/puppet/bindings/bad/default.rb +5 -0
  448. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/good/lib/puppet/bindings/good/default.rb +6 -0
  449. data/spec/fixtures/unit/pops/binder/config/binder_config/ok/binder_config.yaml +2 -2
  450. data/spec/fixtures/unit/provider/service/systemd/{list_units → list_units_services} +0 -1
  451. data/spec/integration/agent/logging_spec.rb +1 -1
  452. data/spec/integration/application/apply_spec.rb +78 -3
  453. data/spec/integration/application/doc_spec.rb +3 -2
  454. data/spec/integration/configurer_spec.rb +5 -3
  455. data/spec/integration/directory_environments_spec.rb +50 -0
  456. data/spec/integration/indirector/direct_file_server_spec.rb +1 -1
  457. data/spec/integration/indirector/file_content/file_server_spec.rb +4 -5
  458. data/spec/integration/network/authconfig_spec.rb +4 -4
  459. data/spec/integration/network/formats_spec.rb +1 -1
  460. data/spec/integration/node/environment_spec.rb +67 -15
  461. data/spec/integration/node/facts_spec.rb +1 -1
  462. data/spec/integration/node_spec.rb +1 -1
  463. data/spec/integration/parser/catalog_spec.rb +100 -60
  464. data/spec/integration/parser/compiler_spec.rb +102 -13
  465. data/spec/integration/parser/future_compiler_spec.rb +416 -0
  466. data/spec/integration/parser/parser_spec.rb +44 -105
  467. data/spec/integration/parser/scope_spec.rb +614 -528
  468. data/spec/integration/provider/cron/crontab_spec.rb +21 -0
  469. data/spec/integration/provider/mount_spec.rb +15 -2
  470. data/spec/integration/resource/catalog_spec.rb +1 -1
  471. data/spec/integration/resource/type_collection_spec.rb +3 -4
  472. data/spec/integration/ssl/autosign_spec.rb +1 -1
  473. data/spec/integration/ssl/certificate_revocation_list_spec.rb +1 -1
  474. data/spec/integration/ssl/host_spec.rb +1 -1
  475. data/spec/integration/transaction_spec.rb +13 -13
  476. data/spec/integration/type/exec_spec.rb +2 -2
  477. data/spec/integration/type/file_spec.rb +114 -41
  478. data/spec/integration/type/nagios_spec.rb +80 -0
  479. data/spec/integration/type/tidy_spec.rb +2 -2
  480. data/spec/integration/util/execution_spec.rb +17 -0
  481. data/spec/integration/util/rdoc/parser_spec.rb +1 -1
  482. data/spec/integration/util/settings_spec.rb +1 -1
  483. data/spec/integration/util/windows/security_spec.rb +27 -2
  484. data/spec/lib/matchers/include.rb +27 -0
  485. data/spec/lib/matchers/include_spec.rb +32 -0
  486. data/spec/lib/matchers/json.rb +135 -79
  487. data/spec/lib/matchers/match_tokens2.rb +74 -0
  488. data/spec/lib/matchers/resource.rb +35 -0
  489. data/spec/lib/puppet/indirector/indirector_testing/memory.rb +7 -0
  490. data/spec/lib/puppet/indirector/indirector_testing/msgpack.rb +6 -0
  491. data/spec/lib/puppet/indirector_testing.rb +12 -2
  492. data/spec/lib/puppet_spec/files.rb +1 -0
  493. data/spec/lib/puppet_spec/matchers.rb +5 -0
  494. data/spec/lib/puppet_spec/modules.rb +1 -1
  495. data/spec/lib/puppet_spec/scope.rb +14 -0
  496. data/spec/shared_behaviours/file_server_terminus.rb +2 -2
  497. data/spec/spec_helper.rb +47 -17
  498. data/spec/unit/agent_spec.rb +8 -1
  499. data/spec/unit/application/agent_spec.rb +5 -4
  500. data/spec/unit/application/apply_spec.rb +34 -15
  501. data/spec/unit/application/device_spec.rb +27 -32
  502. data/spec/unit/application/doc_spec.rb +4 -4
  503. data/spec/unit/application/filebucket_spec.rb +1 -1
  504. data/spec/unit/application/master_spec.rb +2 -2
  505. data/spec/unit/application_spec.rb +1 -1
  506. data/spec/unit/configurer/downloader_spec.rb +1 -1
  507. data/spec/unit/configurer/fact_handler_spec.rb +5 -16
  508. data/spec/unit/configurer_spec.rb +2 -2
  509. data/spec/unit/confine/exists_spec.rb +5 -5
  510. data/spec/unit/context/trusted_information_spec.rb +124 -0
  511. data/spec/unit/context_spec.rb +74 -0
  512. data/spec/unit/environments_spec.rb +126 -0
  513. data/spec/unit/face/config_spec.rb +31 -16
  514. data/spec/unit/face/module/build_spec.rb +1 -0
  515. data/spec/unit/face/module/install_spec.rb +21 -104
  516. data/spec/unit/face/module/list_spec.rb +52 -36
  517. data/spec/unit/face/module/uninstall_spec.rb +18 -25
  518. data/spec/unit/face/parser_spec.rb +39 -23
  519. data/spec/unit/file_bucket/dipper_spec.rb +2 -2
  520. data/spec/unit/file_serving/base_spec.rb +9 -13
  521. data/spec/unit/file_serving/configuration/parser_spec.rb +8 -2
  522. data/spec/unit/file_serving/configuration_spec.rb +7 -7
  523. data/spec/unit/file_serving/content_spec.rb +7 -12
  524. data/spec/unit/file_serving/fileset_spec.rb +49 -53
  525. data/spec/unit/file_serving/metadata_spec.rb +83 -32
  526. data/spec/unit/file_serving/mount/file_spec.rb +10 -10
  527. data/spec/unit/file_system/tempfile_spec.rb +3 -3
  528. data/spec/unit/file_system_spec.rb +508 -0
  529. data/spec/unit/forge/errors_spec.rb +1 -1
  530. data/spec/unit/forge/repository_spec.rb +1 -3
  531. data/spec/unit/hiera/scope_spec.rb +6 -2
  532. data/spec/unit/hiera_puppet_spec.rb +13 -6
  533. data/spec/unit/indirector/catalog/msgpack_spec.rb +12 -0
  534. data/spec/unit/indirector/catalog/static_compiler_spec.rb +42 -11
  535. data/spec/unit/indirector/direct_file_server_spec.rb +6 -6
  536. data/spec/unit/indirector/facts/facter_spec.rb +5 -5
  537. data/spec/unit/indirector/file_bucket_file/file_spec.rb +4 -4
  538. data/spec/unit/indirector/file_metadata/file_spec.rb +2 -2
  539. data/spec/unit/indirector/file_server_spec.rb +4 -4
  540. data/spec/unit/indirector/json_spec.rb +6 -6
  541. data/spec/unit/indirector/key/file_spec.rb +8 -8
  542. data/spec/unit/indirector/msgpack_spec.rb +191 -0
  543. data/spec/unit/indirector/node/active_record_spec.rb +1 -1
  544. data/spec/unit/indirector/node/ldap_spec.rb +16 -7
  545. data/spec/unit/indirector/node/msgpack_spec.rb +24 -0
  546. data/spec/unit/indirector/node/plain_spec.rb +1 -1
  547. data/spec/unit/indirector/queue_spec.rb +1 -1
  548. data/spec/unit/indirector/report/msgpack_spec.rb +28 -0
  549. data/spec/unit/indirector/request_spec.rb +16 -8
  550. data/spec/unit/indirector/rest_spec.rb +0 -4
  551. data/spec/unit/indirector/ssl_file_spec.rb +12 -11
  552. data/spec/unit/indirector/yaml_spec.rb +4 -4
  553. data/spec/unit/man_spec.rb +32 -0
  554. data/spec/unit/module_spec.rb +60 -46
  555. data/spec/unit/module_tool/applications/checksummer_spec.rb +1 -1
  556. data/spec/unit/module_tool/applications/installer_spec.rb +53 -16
  557. data/spec/unit/module_tool/applications/uninstaller_spec.rb +26 -25
  558. data/spec/unit/module_tool/tar_spec.rb +1 -1
  559. data/spec/unit/module_tool_spec.rb +17 -90
  560. data/spec/unit/network/authconfig_spec.rb +3 -4
  561. data/spec/unit/network/authentication_spec.rb +20 -6
  562. data/spec/unit/network/authorization_spec.rb +11 -1
  563. data/spec/unit/network/formats_spec.rb +32 -9
  564. data/spec/unit/network/http/api/v1_spec.rb +365 -62
  565. data/spec/unit/network/http/api/v2/authorization_spec.rb +57 -0
  566. data/spec/unit/network/http/api/v2/environments_spec.rb +42 -0
  567. data/spec/unit/network/http/api/v2_spec.rb +14 -0
  568. data/spec/unit/network/http/connection_spec.rb +39 -5
  569. data/spec/unit/network/http/error_spec.rb +30 -0
  570. data/spec/unit/network/http/handler_spec.rb +69 -419
  571. data/spec/unit/network/http/rack/rest_spec.rb +20 -28
  572. data/spec/unit/network/http/route_spec.rb +75 -0
  573. data/spec/unit/network/http/webrick/rest_spec.rb +21 -58
  574. data/spec/unit/network/http_pool_spec.rb +3 -3
  575. data/spec/unit/network/rights_spec.rb +2 -2
  576. data/spec/unit/node/environment_spec.rb +108 -89
  577. data/spec/unit/node/facts_spec.rb +5 -12
  578. data/spec/unit/node_spec.rb +22 -22
  579. data/spec/unit/parser/ast/collection_spec.rb +1 -1
  580. data/spec/unit/parser/ast/leaf_spec.rb +2 -0
  581. data/spec/unit/parser/ast/resource_spec.rb +1 -1
  582. data/spec/unit/parser/compiler_spec.rb +5 -3
  583. data/spec/unit/parser/files_spec.rb +40 -50
  584. data/spec/unit/parser/functions/defined_spec.rb +80 -18
  585. data/spec/unit/parser/functions/epp_spec.rb +88 -0
  586. data/spec/unit/parser/functions/fqdn_rand_spec.rb +4 -1
  587. data/spec/unit/parser/functions/generate_spec.rb +6 -2
  588. data/spec/unit/parser/functions/hiera_array_spec.rb +5 -2
  589. data/spec/unit/parser/functions/hiera_hash_spec.rb +4 -1
  590. data/spec/unit/parser/functions/hiera_include_spec.rb +6 -3
  591. data/spec/unit/parser/functions/hiera_spec.rb +5 -2
  592. data/spec/unit/parser/functions/include_spec.rb +0 -1
  593. data/spec/unit/parser/functions/inline_epp_spec.rb +82 -0
  594. data/spec/unit/parser/functions/lookup_spec.rb +66 -16
  595. data/spec/unit/parser/functions_spec.rb +25 -91
  596. data/spec/unit/parser/lexer_spec.rb +1 -1
  597. data/spec/unit/parser/methods/filter_spec.rb +56 -0
  598. data/spec/unit/parser/methods/map_spec.rb +94 -5
  599. data/spec/unit/parser/methods/reduce_spec.rb +10 -0
  600. data/spec/unit/parser/methods/shared.rb +2 -18
  601. data/spec/unit/parser/methods/slice_spec.rb +39 -1
  602. data/spec/unit/parser/parser_spec.rb +14 -10
  603. data/spec/unit/parser/resource_spec.rb +3 -9
  604. data/spec/unit/parser/scope_spec.rb +81 -78
  605. data/spec/unit/parser/type_loader_spec.rb +0 -4
  606. data/spec/unit/pops/benchmark_spec.rb +142 -0
  607. data/spec/unit/pops/binder/binder_spec.rb +15 -34
  608. data/spec/unit/pops/binder/bindings_checker_spec.rb +0 -41
  609. data/spec/unit/pops/binder/bindings_composer_spec.rb +6 -31
  610. data/spec/unit/pops/binder/config/binder_config_spec.rb +5 -18
  611. data/spec/unit/pops/binder/injector_spec.rb +76 -81
  612. data/spec/unit/pops/evaluator/access_ops_spec.rb +376 -0
  613. data/spec/unit/pops/evaluator/arithmetic_ops_spec.rb +77 -0
  614. data/spec/unit/pops/evaluator/basic_expressions_spec.rb +103 -0
  615. data/spec/unit/pops/evaluator/collections_ops_spec.rb +111 -0
  616. data/spec/unit/pops/evaluator/comparison_ops_spec.rb +256 -0
  617. data/spec/unit/pops/evaluator/conditionals_spec.rb +190 -0
  618. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +1045 -0
  619. data/spec/unit/pops/evaluator/evaluator_rspec_helper.rb +75 -0
  620. data/spec/unit/pops/evaluator/logical_ops_spec.rb +90 -0
  621. data/spec/unit/pops/evaluator/string_interpolation_spec.rb +44 -0
  622. data/spec/unit/pops/evaluator/variables_spec.rb +194 -0
  623. data/spec/unit/pops/factory_spec.rb +6 -29
  624. data/spec/unit/pops/issues_spec.rb +1 -1
  625. data/spec/unit/pops/model/ast_transformer_spec.rb +6 -9
  626. data/spec/unit/pops/model/model_spec.rb +2 -2
  627. data/spec/unit/pops/parser/epp_parser_spec.rb +86 -0
  628. data/spec/unit/pops/parser/evaluating_parser_spec.rb +4 -2
  629. data/spec/unit/pops/parser/lexer2_spec.rb +428 -0
  630. data/spec/unit/pops/parser/lexer_spec.rb +25 -86
  631. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +29 -4
  632. data/spec/unit/pops/parser/parse_calls_spec.rb +10 -6
  633. data/spec/unit/pops/parser/parse_conditionals_spec.rb +0 -9
  634. data/spec/unit/pops/parser/parse_containers_spec.rb +43 -12
  635. data/spec/unit/pops/parser/parse_heredoc_spec.rb +73 -0
  636. data/spec/unit/pops/parser/parse_resource_spec.rb +14 -0
  637. data/spec/unit/pops/parser/parser_spec.rb +3 -1
  638. data/spec/unit/pops/transformer/transform_basic_expressions_spec.rb +4 -4
  639. data/spec/unit/pops/transformer/transform_calls_spec.rb +41 -6
  640. data/spec/unit/pops/transformer/transform_conditionals_spec.rb +0 -9
  641. data/spec/unit/pops/transformer/transform_containers_spec.rb +12 -4
  642. data/spec/unit/pops/types/enumeration_spec.rb +50 -0
  643. data/spec/unit/pops/types/type_calculator_spec.rb +1171 -196
  644. data/spec/unit/pops/types/type_factory_spec.rb +108 -4
  645. data/spec/unit/pops/types/type_parser_spec.rb +114 -10
  646. data/spec/unit/pops/validator/validator_spec.rb +36 -1
  647. data/spec/unit/provider/augeas/augeas_spec.rb +39 -16
  648. data/spec/unit/provider/cron/parsed_spec.rb +27 -31
  649. data/spec/unit/provider/file/posix_spec.rb +2 -2
  650. data/spec/unit/provider/group/windows_adsi_spec.rb +1 -0
  651. data/spec/unit/provider/mount_spec.rb +12 -1
  652. data/spec/unit/provider/nameservice/directoryservice_spec.rb +3 -3
  653. data/spec/unit/provider/package/apt_spec.rb +1 -1
  654. data/spec/unit/provider/package/aptrpm_spec.rb +1 -1
  655. data/spec/unit/provider/package/gem_spec.rb +12 -0
  656. data/spec/unit/provider/package/msi_spec.rb +4 -0
  657. data/spec/unit/provider/package/openbsd_spec.rb +10 -10
  658. data/spec/unit/provider/package/pacman_spec.rb +36 -7
  659. data/spec/unit/provider/package/pkgin_spec.rb +57 -55
  660. data/spec/unit/provider/package/rpm_spec.rb +51 -6
  661. data/spec/unit/provider/service/base_spec.rb +4 -4
  662. data/spec/unit/provider/service/daemontools_spec.rb +8 -13
  663. data/spec/unit/provider/service/freebsd_spec.rb +3 -3
  664. data/spec/unit/provider/service/gentoo_spec.rb +24 -24
  665. data/spec/unit/provider/service/init_spec.rb +15 -15
  666. data/spec/unit/provider/service/openbsd_spec.rb +16 -16
  667. data/spec/unit/provider/service/openrc_spec.rb +20 -20
  668. data/spec/unit/provider/service/openwrt_spec.rb +1 -1
  669. data/spec/unit/provider/service/runit_spec.rb +5 -8
  670. data/spec/unit/provider/service/src_spec.rb +4 -4
  671. data/spec/unit/provider/service/systemd_spec.rb +24 -14
  672. data/spec/unit/provider/service/upstart_spec.rb +12 -4
  673. data/spec/unit/provider/service/windows_spec.rb +1 -1
  674. data/spec/unit/provider/ssh_authorized_key/parsed_spec.rb +21 -23
  675. data/spec/unit/provider/user/directoryservice_spec.rb +7 -7
  676. data/spec/unit/provider/user/useradd_spec.rb +43 -15
  677. data/spec/unit/provider/user/windows_adsi_spec.rb +1 -0
  678. data/spec/unit/provider/yumrepo/inifile_spec.rb +105 -0
  679. data/spec/unit/provider/zone/solaris_spec.rb +1 -1
  680. data/spec/unit/provider_spec.rb +120 -62
  681. data/spec/unit/rails/host_spec.rb +1 -1
  682. data/spec/unit/rails/param_value_spec.rb +4 -0
  683. data/spec/unit/relationship_spec.rb +4 -4
  684. data/spec/unit/reports/http_spec.rb +14 -3
  685. data/spec/unit/reports/rrdgraph_spec.rb +0 -1
  686. data/spec/unit/reports/store_spec.rb +2 -2
  687. data/spec/unit/resource/catalog_spec.rb +17 -29
  688. data/spec/unit/resource/status_spec.rb +1 -1
  689. data/spec/unit/resource/type_collection_spec.rb +28 -47
  690. data/spec/unit/resource/type_spec.rb +12 -23
  691. data/spec/unit/resource_spec.rb +54 -93
  692. data/spec/unit/run_spec.rb +3 -3
  693. data/spec/unit/settings/autosign_setting_spec.rb +1 -1
  694. data/spec/unit/settings/config_file_spec.rb +68 -15
  695. data/spec/unit/settings/file_setting_spec.rb +2 -2
  696. data/spec/unit/settings/ini_file_spec.rb +184 -0
  697. data/spec/unit/settings_spec.rb +137 -79
  698. data/spec/unit/ssl/certificate_authority/interface_spec.rb +3 -1
  699. data/spec/unit/ssl/certificate_authority_spec.rb +11 -9
  700. data/spec/unit/ssl/certificate_factory_spec.rb +19 -4
  701. data/spec/unit/ssl/certificate_request_attributes_spec.rb +1 -1
  702. data/spec/unit/ssl/certificate_revocation_list_spec.rb +101 -72
  703. data/spec/unit/ssl/host_spec.rb +8 -20
  704. data/spec/unit/ssl/inventory_spec.rb +2 -2
  705. data/spec/unit/ssl/key_spec.rb +4 -4
  706. data/spec/unit/status_spec.rb +6 -4
  707. data/spec/unit/transaction/additional_resource_generator_spec.rb +3 -11
  708. data/spec/unit/transaction/event_spec.rb +2 -2
  709. data/spec/unit/transaction/report_spec.rb +24 -15
  710. data/spec/unit/transaction/resource_harness_spec.rb +1 -1
  711. data/spec/unit/type/cron_spec.rb +39 -1
  712. data/spec/unit/type/file/content_spec.rb +4 -5
  713. data/spec/unit/type/file/ctime_spec.rb +1 -1
  714. data/spec/unit/type/file/mode_spec.rb +5 -4
  715. data/spec/unit/type/file/mtime_spec.rb +1 -1
  716. data/spec/unit/type/file/source_spec.rb +30 -7
  717. data/spec/unit/type/file_spec.rb +8 -8
  718. data/spec/unit/type/k5login_spec.rb +3 -3
  719. data/spec/unit/type/nagios_spec.rb +6 -0
  720. data/spec/unit/type/package/package_settings_spec.rb +135 -0
  721. data/spec/unit/type/package_spec.rb +13 -1
  722. data/spec/unit/type/resources_spec.rb +155 -0
  723. data/spec/unit/type/service_spec.rb +3 -3
  724. data/spec/unit/type/ssh_authorized_key_spec.rb +96 -93
  725. data/spec/unit/type/sshkey_spec.rb +39 -30
  726. data/spec/unit/type/tidy_spec.rb +19 -12
  727. data/spec/unit/type/user_spec.rb +47 -2
  728. data/spec/unit/type/whit_spec.rb +2 -2
  729. data/spec/unit/type/yumrepo_spec.rb +32 -177
  730. data/spec/unit/type/zone_spec.rb +2 -2
  731. data/spec/unit/type_spec.rb +11 -0
  732. data/spec/unit/util/adsi_spec.rb +48 -1
  733. data/spec/unit/util/autoload_spec.rb +24 -39
  734. data/spec/unit/util/backups_spec.rb +25 -28
  735. data/spec/unit/util/checksums_spec.rb +1 -3
  736. data/spec/unit/util/colors_spec.rb +14 -0
  737. data/spec/unit/util/docs_spec.rb +9 -0
  738. data/spec/unit/util/execution_spec.rb +1 -1
  739. data/spec/unit/util/filetype_spec.rb +7 -7
  740. data/spec/unit/util/instrumentation/data_spec.rb +3 -1
  741. data/spec/unit/util/instrumentation/indirection_probe_spec.rb +2 -0
  742. data/spec/unit/util/instrumentation/listener_spec.rb +3 -2
  743. data/spec/unit/util/json_lockfile_spec.rb +25 -4
  744. data/spec/unit/util/lockfile_spec.rb +49 -7
  745. data/spec/unit/util/log/destinations_spec.rb +1 -0
  746. data/spec/unit/util/log_spec.rb +1 -1
  747. data/spec/unit/util/metric_spec.rb +1 -1
  748. data/spec/unit/util/pidlock_spec.rb +6 -6
  749. data/spec/unit/util/pson_spec.rb +2 -2
  750. data/spec/unit/util/rdoc/parser_spec.rb +32 -29
  751. data/spec/unit/util/resource_template_spec.rb +3 -3
  752. data/spec/unit/util/selinux_spec.rb +5 -5
  753. data/spec/unit/util/storage_spec.rb +4 -4
  754. data/spec/unit/util/tag_set_spec.rb +1 -1
  755. data/spec/unit/util/watcher_spec.rb +1 -4
  756. data/spec/unit/util/yaml_spec.rb +2 -2
  757. data/spec/unit/util_spec.rb +7 -7
  758. data/tasks/benchmark.rake +0 -1
  759. data/tasks/parallel.rake +408 -0
  760. data/tasks/yard.rake +59 -0
  761. metadata +2889 -2782
  762. checksums.yaml +0 -7
  763. data/README_DEVELOPER.md +0 -809
  764. data/lib/puppet/file_system/file.rb +0 -271
  765. data/lib/puppet/network/http/rack/httphandler.rb +0 -13
  766. data/lib/puppet/pops/binder/hiera2.rb +0 -10
  767. data/lib/puppet/pops/binder/hiera2/bindings_provider.rb +0 -148
  768. data/lib/puppet/pops/binder/hiera2/config.rb +0 -69
  769. data/lib/puppet/pops/binder/hiera2/config_checker.rb +0 -68
  770. data/lib/puppet/pops/binder/hiera2/diagnostic_producer.rb +0 -36
  771. data/lib/puppet/pops/binder/hiera2/issues.rb +0 -67
  772. data/lib/puppet/pops/binder/hiera2/json_backend.rb +0 -18
  773. data/lib/puppet/pops/binder/hiera2/yaml_backend.rb +0 -21
  774. data/lib/puppet/pops/binder/scheme_handler/confdir_hiera_scheme.rb +0 -67
  775. data/lib/puppet/pops/binder/scheme_handler/module_hiera_scheme.rb +0 -92
  776. data/lib/puppet/pops/parser/grammar.ra +0 -746
  777. data/lib/puppet/provider/port/parsed.rb +0 -173
  778. data/lib/puppet/type/port.rb +0 -119
  779. data/lib/puppetx/puppet/hiera2_backend.rb +0 -31
  780. data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/binder_config.yaml +0 -18
  781. data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/hiera.yaml +0 -8
  782. data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/modules/good/common.yaml +0 -1
  783. data/spec/fixtures/unit/pops/binder/bindings_composer/hiera1config/modules/good/hiera.yaml +0 -10
  784. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/common.yaml +0 -1
  785. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/hiera.yaml +0 -11
  786. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/localhost.yaml +0 -1
  787. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/common.yaml +0 -3
  788. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/hiera.yaml +0 -13
  789. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/lib/puppet/bindings/awesome/default.rb +0 -4
  790. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/lib/puppetx/awesome/echo_backend.rb +0 -11
  791. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/awesome/localhost.yaml +0 -1
  792. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/bad/common.yaml +0 -3
  793. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/bad/hiera_config.yaml +0 -9
  794. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/good/common.yaml +0 -2
  795. data/spec/fixtures/unit/pops/binder/bindings_composer/ok/modules/good/hiera.yaml +0 -11
  796. data/spec/fixtures/unit/pops/binder/hiera2/bindings_provider/ok/hiera.yaml +0 -9
  797. data/spec/fixtures/unit/pops/binder/hiera2/bindings_provider/ok/node.example.com.json +0 -9
  798. data/spec/fixtures/unit/pops/binder/hiera2/bindings_provider/ok/node.example.com.yaml +0 -5
  799. data/spec/fixtures/unit/pops/binder/hiera2/config/bad_syntax/hiera.yaml +0 -10
  800. data/spec/fixtures/unit/pops/binder/hiera2/config/malformed_hierarchy/hiera.yaml +0 -8
  801. data/spec/fixtures/unit/pops/binder/hiera2/config/missing/foo.txt +0 -1
  802. data/spec/fixtures/unit/pops/binder/hiera2/config/no_backends/hiera.yaml +0 -7
  803. data/spec/fixtures/unit/pops/binder/hiera2/config/no_hierarchy/hiera.yaml +0 -4
  804. data/spec/fixtures/unit/pops/binder/hiera2/config/not_a_hash/hiera.yaml +0 -2
  805. data/spec/fixtures/unit/pops/binder/hiera2/config/ok/hiera.yaml +0 -8
  806. data/spec/fixtures/unit/pops/binder/hiera2/yaml_backend/invalid/common.yaml +0 -1
  807. data/spec/fixtures/unit/pops/binder/hiera2/yaml_backend/ok/common.yaml +0 -2
  808. data/spec/unit/file_system/file_spec.rb +0 -486
  809. data/spec/unit/pops/binder/hiera2/bindings_provider_spec.rb +0 -74
  810. data/spec/unit/pops/binder/hiera2/config_spec.rb +0 -61
  811. data/spec/unit/pops/binder/hiera2/yaml_backend_spec.rb +0 -33
@@ -0,0 +1,57 @@
1
+
2
+ # A Closure represents logic bound to a particular scope.
3
+ # As long as the runtime (basically the scope implementation) has the behaviour of Puppet 3x it is not
4
+ # safe to use this closure when the scope given to it when initialized goes "out of scope".
5
+ #
6
+ # Note that the implementation is backwards compatible in that the call method accepts a scope, but this
7
+ # scope is not used.
8
+ #
9
+ class Puppet::Pops::Evaluator::Closure
10
+ attr_reader :evaluator
11
+ attr_reader :model
12
+ attr_reader :enclosing_scope
13
+
14
+ def initialize(evaluator, model, scope)
15
+ @evaluator = evaluator
16
+ @model = model
17
+ @enclosing_scope = scope
18
+ end
19
+
20
+ # marker method checked with respond_to :puppet_lambda
21
+ def puppet_lambda()
22
+ true
23
+ end
24
+
25
+ # compatible with 3x AST::Lambda
26
+ def call(scope, *args)
27
+ @evaluator.call(self, args, @enclosing_scope)
28
+ end
29
+
30
+ # Call closure with argument assignment by name
31
+ def call_by_name(scope, args_hash, spill_over = false)
32
+ @evaluator.call_by_name(self, args_hash, @enclosing_scope, spill_over)
33
+ end
34
+
35
+ # incompatible with 3x except that it is an array of the same size
36
+ def parameters()
37
+ @model.parameters || []
38
+ end
39
+
40
+ # Returns the number of parameters (required and optional)
41
+ # @return [Integer] the total number of accepted parameters
42
+ def parameter_count
43
+ # yes, this is duplication of code, but it saves a method call
44
+ (@model.parameters || []).size
45
+ end
46
+
47
+ # Returns the number of optional parameters.
48
+ # @return [Integer] the number of optional accepted parameters
49
+ def optional_parameter_count
50
+ @model.parameters.count { |p| !p.value.nil? }
51
+ end
52
+
53
+ def parameter_names
54
+ @model.parameters.collect {|p| p.name }
55
+ end
56
+
57
+ end
@@ -0,0 +1,168 @@
1
+ # Compares the puppet DSL way
2
+ #
3
+ # ==Equality
4
+ # All string vs. numeric equalities check for numeric equality first, then string equality
5
+ # Arrays are equal to arrays if they have the same length, and each element #equals
6
+ # Hashes are equal to hashes if they have the same size and keys and values #equals.
7
+ # All other objects are equal if they are ruby #== equal
8
+ #
9
+ class Puppet::Pops::Evaluator::CompareOperator
10
+ include Puppet::Pops::Utils
11
+
12
+ def initialize
13
+ @@equals_visitor ||= Puppet::Pops::Visitor.new(self, "equals", 1, 1)
14
+ @@compare_visitor ||= Puppet::Pops::Visitor.new(self, "cmp", 1, 1)
15
+ @@include_visitor ||= Puppet::Pops::Visitor.new(self, "include", 1, 1)
16
+ @type_calculator = Puppet::Pops::Types::TypeCalculator.new()
17
+ end
18
+
19
+ def equals (a, b)
20
+ @@equals_visitor.visit_this_1(self, a, b)
21
+ end
22
+
23
+ # Performs a comparison of a and b, and return > 0 if a is bigger, 0 if equal, and < 0 if b is bigger.
24
+ # Comparison of String vs. Numeric always compares using numeric.
25
+ def compare(a, b)
26
+ @@compare_visitor.visit_this_1(self, a, b)
27
+ end
28
+
29
+ # Answers is b included in a
30
+ def include?(a, b)
31
+ @@include_visitor.visit_this_1(self, a, b)
32
+ end
33
+
34
+ protected
35
+
36
+ def cmp_String(a, b)
37
+ # if both are numerics in string form, compare as number
38
+ n1 = Puppet::Pops::Utils.to_n(a)
39
+ n2 = Puppet::Pops::Utils.to_n(b)
40
+
41
+ # Numeric is always lexically smaller than a string, even if the string is empty.
42
+ return n1 <=> n2 if n1 && n2
43
+ return -1 if n1 && b.is_a?(String)
44
+ return 1 if n2
45
+ return a.casecmp(b) if b.is_a?(String)
46
+
47
+ raise ArgumentError.new("A String is not comparable to a non String or Number")
48
+ end
49
+
50
+ # Equality is case independent.
51
+ def equals_String(a, b)
52
+ if n1 = Puppet::Pops::Utils.to_n(a)
53
+ if n2 = Puppet::Pops::Utils.to_n(b)
54
+ n1 == n2
55
+ else
56
+ false
57
+ end
58
+ else
59
+ return false unless b.is_a?(String)
60
+ a.casecmp(b) == 0
61
+ end
62
+ end
63
+
64
+ def cmp_Numeric(a, b)
65
+ if n2 = Puppet::Pops::Utils.to_n(b)
66
+ a <=> n2
67
+ elsif b.kind_of(String)
68
+ # Numeric is always lexiographically smaller than a string, even if the string is empty.
69
+ -1
70
+ else
71
+ raise ArgumentError.new("A Numeric is not comparable to non Numeric or String")
72
+ end
73
+ end
74
+
75
+ def equals_Numeric(a, b)
76
+ if n2 = Puppet::Pops::Utils.to_n(b)
77
+ a == n2
78
+ else
79
+ false
80
+ end
81
+ end
82
+
83
+ def equals_Array(a, b)
84
+ return false unless b.is_a?(Array) && a.size == b.size
85
+ a.each_index {|i| return false unless equals(a.slice(i), b.slice(i)) }
86
+ true
87
+ end
88
+
89
+ def equals_Hash(a, b)
90
+ return false unless b.is_a?(Hash) && a.size == b.size
91
+ a.each {|ak, av| return false unless equals(b[ak], av)}
92
+ true
93
+ end
94
+
95
+ def cmp_Symbol(a, b)
96
+ if b.is_a?(Symbol)
97
+ a <=> b
98
+ else
99
+ raise ArgumentError.new("Symbol not comparable to non Symbol")
100
+ end
101
+ end
102
+
103
+ def cmp_Object(a, b)
104
+ raise ArgumentError.new("Only Strings and Numbers are comparable")
105
+ end
106
+
107
+
108
+ def equals_Object(a, b)
109
+ a == b
110
+ end
111
+
112
+ def equals_NilClass(a, b)
113
+ b.nil? || b == :undef
114
+ end
115
+
116
+ def equals_Symbol(a, b)
117
+ a == b || a == :undef && b.nil?
118
+ end
119
+
120
+ def include_Object(a, b)
121
+ false
122
+ end
123
+
124
+ def include_String(a, b)
125
+ case b
126
+ when String
127
+ # subsstring search downcased
128
+ a.downcase.include?(b.downcase)
129
+ when Regexp
130
+ # match (convert to boolean)
131
+ !!(a =~ b)
132
+ when Numeric
133
+ # convert string to number, true if ==
134
+ equals(a, b)
135
+ when Puppet::Pops::Types::PStringType
136
+ # is there a string in a string? (yes, each char is a string, and an empty string contains an empty string)
137
+ true
138
+ else
139
+ if b == Puppet::Pops::Types::PDataType || b == Puppet::Pops::Types::PObjectType
140
+ # A String is Data and Object (but not of all subtypes of those types).
141
+ true
142
+ else
143
+ false
144
+ end
145
+ end
146
+ end
147
+
148
+ def include_Array(a, b)
149
+ case b
150
+ when Regexp
151
+ a.each do |element|
152
+ next unless element.is_a? String
153
+ return true if element =~ b
154
+ end
155
+ return false
156
+ when Puppet::Pops::Types::PAbstractType
157
+ a.each {|element| return true if @type_calculator.instance?(b, element) }
158
+ return false
159
+ else
160
+ a.each {|element| return true if equals(element, b) }
161
+ return false
162
+ end
163
+ end
164
+
165
+ def include_Hash(a, b)
166
+ include?(a.keys, b)
167
+ end
168
+ end
@@ -0,0 +1,87 @@
1
+ # Handler of Epp call/evaluation from the epp and inline_epp functions
2
+ #
3
+ class Puppet::Pops::Evaluator::EppEvaluator
4
+
5
+ def self.inline_epp(scope, epp_source, template_args = nil)
6
+ unless epp_source.is_a? String
7
+ raise ArgumentError, "inline_epp(): the first argument must be a String with the epp source text, got a #{epp_source.class}"
8
+ end
9
+
10
+ # Parse and validate the source
11
+ parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new
12
+ begin
13
+ result = parser.parse_string(epp_source, 'inlined-epp-text')
14
+ rescue Puppet::ParseError => e
15
+ raise ArgumentError, "inline_epp(): Invalid EPP: #{e.message}"
16
+ end
17
+
18
+ # Evaluate (and check template_args)
19
+ evaluate(parser, 'inline_epp', scope, false, result, template_args)
20
+ end
21
+
22
+ def self.epp(scope, file, env_name, template_args = nil)
23
+ unless file.is_a? String
24
+ raise ArgumentError, "epp(): the first argument must be a String with the filename, got a #{file.class}"
25
+ end
26
+
27
+ file = file + ".epp" unless file =~ /\.epp$/
28
+ scope.debug "Retrieving epp template #{file}"
29
+ template_file = Puppet::Parser::Files.find_template(file, env_name)
30
+ unless template_file
31
+ raise Puppet::ParseError, "Could not find template '#{file}'"
32
+ end
33
+
34
+ # Parse and validate the source
35
+ parser = Puppet::Pops::Parser::EvaluatingParser::EvaluatingEppParser.new
36
+ begin
37
+ result = parser.parse_file(template_file)
38
+ rescue Puppet::ParseError => e
39
+ raise ArgumentError, "epp(): Invalid EPP: #{e.message}"
40
+ end
41
+
42
+ # Evaluate (and check template_args)
43
+ evaluate(parser, 'epp', scope, true, result, template_args)
44
+ end
45
+
46
+ private
47
+
48
+ def self.evaluate(parser, func_name, scope, use_global_scope_only, parse_result, template_args)
49
+ template_args, template_args_set = handle_template_args(func_name, template_args)
50
+
51
+ body = parse_result.body
52
+ unless body.is_a?(Puppet::Pops::Model::LambdaExpression)
53
+ raise ArgumentError, "#{func_name}(): the parser did not produce a LambdaExpression, got '#{body.class}'"
54
+ end
55
+ unless body.body.is_a?(Puppet::Pops::Model::EppExpression)
56
+ raise ArgumentError, "#{func_name}(): the parser did not produce an EppExpression, got '#{body.body.class}'"
57
+ end
58
+ unless parse_result.definitions.empty?
59
+ raise ArgumentError, "#{func_name}(): The EPP template contains illegal expressions (definitions)"
60
+ end
61
+
62
+ see_scope = body.body.see_scope
63
+ if see_scope && !template_args_set
64
+ # no epp params and no arguments were given => inline_epp logic sees all local variables, epp all global
65
+ closure_scope = use_global_scope_only ? scope.find_global_scope : scope
66
+ spill_over = false
67
+ else
68
+ # no epp params or user provided arguments in a hash, epp logic only sees global + what was given
69
+ closure_scope = scope.find_global_scope
70
+ # given spill over if there are no params (e.g. replace closure scope by a new scope with the given args)
71
+ spill_over = see_scope
72
+ end
73
+ evaluated_result = parser.closure(body, closure_scope).call_by_name(scope, template_args, spill_over)
74
+ evaluated_result
75
+ end
76
+
77
+ def self.handle_template_args(func_name, template_args)
78
+ if template_args.nil?
79
+ [{}, false]
80
+ else
81
+ unless template_args.is_a?(Hash)
82
+ raise ArgumentError, "#{func_name}(): the template_args must be a Hash, got a #{template_args.class}"
83
+ end
84
+ [template_args, true]
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,1069 @@
1
+ require 'rgen/ecore/ecore'
2
+ require 'puppet/pops/evaluator/compare_operator'
3
+ require 'puppet/pops/evaluator/relationship_operator'
4
+ require 'puppet/pops/evaluator/access_operator'
5
+ require 'puppet/pops/evaluator/closure'
6
+ require 'puppet/pops/evaluator/external_syntax_support'
7
+
8
+ # This implementation of {Puppet::Pops::Evaluator} performs evaluation using the puppet 3.x runtime system
9
+ # in a manner largely compatible with Puppet 3.x, but adds new features and introduces constraints.
10
+ #
11
+ # The evaluation uses _polymorphic dispatch_ which works by dispatching to the first found method named after
12
+ # the class or one of its super-classes. The EvaluatorImpl itself mainly deals with evaluation (it currently
13
+ # also handles assignment), and it uses a delegation pattern to more specialized handlers of some operators
14
+ # that in turn use polymorphic dispatch; this to not clutter EvaluatorImpl with too much responsibility).
15
+ #
16
+ # Since a pattern is used, only the main entry points are fully documented. The parameters _o_ and _scope_ are
17
+ # the same in all the polymorphic methods, (the type of the parameter _o_ is reflected in the method's name;
18
+ # either the actual class, or one of its super classes). The _scope_ parameter is always the scope in which
19
+ # the evaluation takes place. If nothing else is mentioned, the return is always the result of evaluation.
20
+ #
21
+ # See {Puppet::Pops::Visitable} and {Puppet::Pops::Visitor} for more information about
22
+ # polymorphic calling.
23
+ #
24
+ class Puppet::Pops::Evaluator::EvaluatorImpl
25
+ include Puppet::Pops::Utils
26
+
27
+ # Provides access to the Puppet 3.x runtime (scope, etc.)
28
+ # This separation has been made to make it easier to later migrate the evaluator to an improved runtime.
29
+ #
30
+ include Puppet::Pops::Evaluator::Runtime3Support
31
+ include Puppet::Pops::Evaluator::ExternalSyntaxSupport
32
+
33
+ # This constant is not defined as Float::INFINITY in Ruby 1.8.7 (but is available in later version
34
+ # Refactor when support is dropped for Ruby 1.8.7.
35
+ #
36
+ INFINITY = 1.0 / 0.0
37
+
38
+ # Reference to Issues name space makes it easier to refer to issues
39
+ # (Issues are shared with the validator).
40
+ #
41
+ Issues = Puppet::Pops::Issues
42
+
43
+ def initialize
44
+ @@eval_visitor ||= Puppet::Pops::Visitor.new(self, "eval", 1, 1)
45
+ @@lvalue_visitor ||= Puppet::Pops::Visitor.new(self, "lvalue", 1, 1)
46
+ @@assign_visitor ||= Puppet::Pops::Visitor.new(self, "assign", 3, 3)
47
+ @@string_visitor ||= Puppet::Pops::Visitor.new(self, "string", 1, 1)
48
+
49
+ @@type_calculator ||= Puppet::Pops::Types::TypeCalculator.new()
50
+ @@type_parser ||= Puppet::Pops::Types::TypeParser.new()
51
+
52
+ @@compare_operator ||= Puppet::Pops::Evaluator::CompareOperator.new()
53
+ @@relationship_operator ||= Puppet::Pops::Evaluator::RelationshipOperator.new()
54
+
55
+ # Initialize the runtime module
56
+ Puppet::Pops::Evaluator::Runtime3Support.instance_method(:initialize).bind(self).call()
57
+ end
58
+
59
+ # @api private
60
+ def type_calculator
61
+ @@type_calculator
62
+ end
63
+
64
+ # Polymorphic evaluate - calls eval_TYPE
65
+ #
66
+ # ## Polymorphic evaluate
67
+ # Polymorphic evaluate calls a method on the format eval_TYPE where classname is the last
68
+ # part of the class of the given _target_. A search is performed starting with the actual class, continuing
69
+ # with each of the _target_ class's super classes until a matching method is found.
70
+ #
71
+ # # Description
72
+ # Evaluates the given _target_ object in the given scope, optionally passing a block which will be
73
+ # called with the result of the evaluation.
74
+ #
75
+ # @overload evaluate(target, scope, {|result| block})
76
+ # @param target [Object] evaluation target - see methods on the pattern assign_TYPE for actual supported types.
77
+ # @param scope [Object] the runtime specific scope class where evaluation should take place
78
+ # @return [Object] the result of the evaluation
79
+ #
80
+ # @api
81
+ #
82
+ def evaluate(target, scope)
83
+ begin
84
+ @@eval_visitor.visit_this_1(self, target, scope)
85
+ rescue StandardError => e
86
+ if e.is_a? Puppet::ParseError
87
+ raise e
88
+ end
89
+ fail(Issues::RUNTIME_ERROR, target, {:detail => e.message}, e)
90
+ end
91
+ end
92
+
93
+ # Polymorphic assign - calls assign_TYPE
94
+ #
95
+ # ## Polymorphic assign
96
+ # Polymorphic assign calls a method on the format assign_TYPE where TYPE is the last
97
+ # part of the class of the given _target_. A search is performed starting with the actual class, continuing
98
+ # with each of the _target_ class's super classes until a matching method is found.
99
+ #
100
+ # # Description
101
+ # Assigns the given _value_ to the given _target_. The additional argument _o_ is the instruction that
102
+ # produced the target/value tuple and it is used to set the origin of the result.
103
+ # @param target [Object] assignment target - see methods on the pattern assign_TYPE for actual supported types.
104
+ # @param value [Object] the value to assign to `target`
105
+ # @param o [Puppet::Pops::Model::PopsObject] originating instruction
106
+ # @param scope [Object] the runtime specific scope where evaluation should take place
107
+ #
108
+ # @api
109
+ #
110
+ def assign(target, value, o, scope)
111
+ @@assign_visitor.visit_this_3(self, target, value, o, scope)
112
+ end
113
+
114
+ def lvalue(o, scope)
115
+ @@lvalue_visitor.visit_this_1(self, o, scope)
116
+ end
117
+
118
+ def string(o, scope)
119
+ @@string_visitor.visit_this_1(self, o, scope)
120
+ end
121
+
122
+ # Call a closure matching arguments by name - Can only be called with a Closure (for now), may be refactored later
123
+ # to also handle other types of calls (function calls are also handled by CallNamedFunction and CallMethod, they
124
+ # could create similar objects to Closure, wait until other types of defines are instantiated - they may behave
125
+ # as special cases of calls - i.e. 'new').
126
+ #
127
+ # Call by name supports a "spill_over" mode where extra arguments in the given args_hash are introduced
128
+ # as variables in the resulting scope.
129
+ #
130
+ # @raise ArgumentError, if there are to many or too few arguments
131
+ # @raise ArgumentError, if given closure is not a Puppet::Pops::Evaluator::Closure
132
+ #
133
+ def call_by_name(closure, args_hash, scope, spill_over = false)
134
+ raise ArgumentError, "Can only call a Lambda" unless closure.is_a?(Puppet::Pops::Evaluator::Closure)
135
+ pblock = closure.model
136
+ parameters = pblock.parameters || []
137
+
138
+ if !spill_over && args_hash.size > parameters.size
139
+ raise ArgumentError, "Too many arguments: #{args_hash.size} for #{parameters.size}"
140
+ end
141
+
142
+ # associate values with parameters
143
+ scope_hash = {}
144
+ parameters.each do |p|
145
+ scope_hash[p.name] = args_hash[p.name] || evaluate(p.value, scope)
146
+ end
147
+ missing = scope_hash.reduce([]) {|memo, entry| memo << entry[0] if entry[1].nil?; memo }
148
+ unless missing.empty?
149
+ optional = parameters.count { |p| !p.value.nil? }
150
+ raise ArgumentError, "Too few arguments; no value given for required parameters #{missing.join(" ,")}"
151
+ end
152
+ if spill_over
153
+ # all args from given hash should be used, nil entries replaced by default values should win
154
+ scope_hash = args_hash.merge(scope_hash)
155
+ end
156
+
157
+ # Store the evaluated name => value associations in a new inner/local/ephemeral scope
158
+ # (This is made complicated due to the fact that the implementation of scope is overloaded with
159
+ # functionality and an inner ephemeral scope must be used (as opposed to just pushing a local scope
160
+ # on a scope "stack").
161
+
162
+ # Ensure variable exists with nil value if error occurs.
163
+ # Some ruby implementations does not like creating variable on return
164
+ result = nil
165
+ begin
166
+ scope_memo = get_scope_nesting_level(scope)
167
+ # change to create local scope_from - cannot give it file and line - that is the place of the call, not
168
+ # "here"
169
+ create_local_scope_from(scope_hash, scope)
170
+ result = evaluate(pblock.body, scope)
171
+ ensure
172
+ set_scope_nesting_level(scope, scope_memo)
173
+ end
174
+ result
175
+ end
176
+
177
+ # Call a closure - Can only be called with a Closure (for now), may be refactored later
178
+ # to also handle other types of calls (function calls are also handled by CallNamedFunction and CallMethod, they
179
+ # could create similar objects to Closure, wait until other types of defines are instantiated - they may behave
180
+ # as special cases of calls - i.e. 'new')
181
+ #
182
+ # @raise ArgumentError, if there are to many or too few arguments
183
+ # @raise ArgumentError, if given closure is not a Puppet::Pops::Evaluator::Closure
184
+ #
185
+ def call(closure, args, scope)
186
+ raise ArgumentError, "Can only call a Lambda" unless closure.is_a?(Puppet::Pops::Evaluator::Closure)
187
+ pblock = closure.model
188
+ parameters = pblock.parameters || []
189
+
190
+ raise ArgumentError, "Too many arguments: #{args.size} for #{parameters.size}" unless args.size <= parameters.size
191
+
192
+ # associate values with parameters
193
+ merged = parameters.zip(args)
194
+ # calculate missing arguments
195
+ missing = parameters.slice(args.size, parameters.size - args.size).select {|p| p.value.nil? }
196
+ unless missing.empty?
197
+ optional = parameters.count { |p| !p.value.nil? }
198
+ raise ArgumentError, "Too few arguments; #{args.size} for #{optional > 0 ? ' min ' : ''}#{parameters.size - optional}"
199
+ end
200
+
201
+ evaluated = merged.collect do |m|
202
+ # m can be one of
203
+ # m = [Parameter{name => "name", value => nil], "given"]
204
+ # | [Parameter{name => "name", value => Expression}, "given"]
205
+ #
206
+ # "given" is always an optional entry. If a parameter was provided then
207
+ # the entry will be in the array, otherwise the m array will be a
208
+ # single element.a = []
209
+ given_argument = m[1]
210
+ argument_name = m[0].name
211
+ default_expression = m[0].value
212
+
213
+ value = if default_expression
214
+ evaluate(default_expression, scope)
215
+ else
216
+ given_argument
217
+ end
218
+ [argument_name, value]
219
+ end
220
+
221
+ # Store the evaluated name => value associations in a new inner/local/ephemeral scope
222
+ # (This is made complicated due to the fact that the implementation of scope is overloaded with
223
+ # functionality and an inner ephemeral scope must be used (as opposed to just pushing a local scope
224
+ # on a scope "stack").
225
+
226
+ # Ensure variable exists with nil value if error occurs.
227
+ # Some ruby implementations does not like creating variable on return
228
+ result = nil
229
+ begin
230
+ scope_memo = get_scope_nesting_level(scope)
231
+ # change to create local scope_from - cannot give it file and line - that is the place of the call, not
232
+ # "here"
233
+ create_local_scope_from(Hash[evaluated], scope)
234
+ result = evaluate(pblock.body, scope)
235
+ ensure
236
+ set_scope_nesting_level(scope, scope_memo)
237
+ end
238
+ result
239
+ end
240
+
241
+ protected
242
+
243
+ def lvalue_VariableExpression(o, scope)
244
+ # evaluate the name
245
+ evaluate(o.expr, scope)
246
+ end
247
+
248
+ # Catches all illegal lvalues
249
+ #
250
+ def lvalue_Object(o, scope)
251
+ fail(Issues::ILLEGAL_ASSIGNMENT, o)
252
+ end
253
+
254
+ # Assign value to named variable.
255
+ # The '$' sign is never part of the name.
256
+ # @example In Puppet DSL
257
+ # $name = value
258
+ # @param name [String] name of variable without $
259
+ # @param value [Object] value to assign to the variable
260
+ # @param o [Puppet::Pops::Model::PopsObject] originating instruction
261
+ # @param scope [Object] the runtime specific scope where evaluation should take place
262
+ # @return [value<Object>]
263
+ #
264
+ def assign_String(name, value, o, scope)
265
+ if name =~ /::/
266
+ fail(Issues::CROSS_SCOPE_ASSIGNMENT, o.left_expr, {:name => name})
267
+ end
268
+ set_variable(name, value, o, scope)
269
+ value
270
+ end
271
+
272
+ def assign_Numeric(n, value, o, scope)
273
+ fail(Issues::ILLEGAL_NUMERIC_ASSIGNMENT, o.left_expr, {:varname => n.to_s})
274
+ end
275
+
276
+ # Catches all illegal assignment (e.g. 1 = 2, {'a'=>1} = 2, etc)
277
+ #
278
+ def assign_Object(name, value, o, scope)
279
+ fail(Issues::ILLEGAL_ASSIGNMENT, o)
280
+ end
281
+
282
+ def eval_Factory(o, scope)
283
+ evaluate(o.current, scope)
284
+ end
285
+
286
+ # Evaluates any object not evaluated to something else to itself.
287
+ def eval_Object o, scope
288
+ o
289
+ end
290
+
291
+ # Allows nil to be used as a Nop.
292
+ # Evaluates to nil
293
+ # TODO: What is the difference between literal undef, nil, and nop?
294
+ #
295
+ def eval_NilClass(o, scope)
296
+ nil
297
+ end
298
+
299
+ # Evaluates Nop to nil.
300
+ # TODO: or is this the same as :undef
301
+ # TODO: is this even needed as a separate instruction when there is a literal undef?
302
+ def eval_Nop(o, scope)
303
+ nil
304
+ end
305
+
306
+ # Captures all LiteralValues not handled elsewhere.
307
+ #
308
+ def eval_LiteralValue(o, scope)
309
+ o.value
310
+ end
311
+
312
+ def eval_LiteralDefault(o, scope)
313
+ :default
314
+ end
315
+
316
+ def eval_LiteralUndef(o, scope)
317
+ :undef # TODO: or just use nil for this?
318
+ end
319
+
320
+ # A QualifiedReference (i.e. a capitalized qualified name such as Foo, or Foo::Bar) evaluates to a PType
321
+ #
322
+ def eval_QualifiedReference(o, scope)
323
+ @@type_parser.interpret(o)
324
+ end
325
+
326
+ def eval_NotExpression(o, scope)
327
+ ! is_true?(evaluate(o.expr, scope))
328
+ end
329
+
330
+ def eval_UnaryMinusExpression(o, scope)
331
+ - coerce_numeric(evaluate(o.expr, scope), o, scope)
332
+ end
333
+
334
+ # Abstract evaluation, returns array [left, right] with the evaluated result of left_expr and
335
+ # right_expr
336
+ # @return <Array<Object, Object>> array with result of evaluating left and right expressions
337
+ #
338
+ def eval_BinaryExpression o, scope
339
+ [ evaluate(o.left_expr, scope), evaluate(o.right_expr, scope) ]
340
+ end
341
+
342
+ # Evaluates assignment with operators =, +=, -= and
343
+ #
344
+ # @example Puppet DSL
345
+ # $a = 1
346
+ # $a += 1
347
+ # $a -= 1
348
+ #
349
+ def eval_AssignmentExpression(o, scope)
350
+ name = lvalue(o.left_expr, scope)
351
+ value = evaluate(o.right_expr, scope)
352
+
353
+ case o.operator
354
+ when :'=' # regular assignment
355
+ assign(name, value, o, scope)
356
+
357
+ when :'+='
358
+ # if value does not exist and strict is on, looking it up fails, else it is nil or :undef
359
+ existing_value = get_variable_value(name, o, scope)
360
+ begin
361
+ if existing_value.nil? || existing_value == :undef
362
+ assign(name, value, o, scope)
363
+ else
364
+ # Delegate to calculate function to deal with check of LHS, and perform ´+´ as arithmetic or concatenation the
365
+ # same way as ArithmeticExpression performs `+`.
366
+ assign(name, calculate(existing_value, value, :'+', o.left_expr, o.right_expr, scope), o, scope)
367
+ end
368
+ rescue ArgumentError => e
369
+ fail(Issues::APPEND_FAILED, o, {:message => e.message})
370
+ end
371
+
372
+ when :'-='
373
+ # If an attempt is made to delete values from something that does not exists, the value is :undef (it is guaranteed to not
374
+ # include any values the user wants deleted anyway :-)
375
+ #
376
+ # if value does not exist and strict is on, looking it up fails, else it is nil or :undef
377
+ existing_value = get_variable_value(name, o, scope)
378
+ begin
379
+ if existing_value.nil? || existing_value == :undef
380
+ assign(name, :undef, o, scope)
381
+ else
382
+ # Delegate to delete function to deal with check of LHS, and perform deletion
383
+ assign(name, delete(get_variable_value(name, o, scope), value), o, scope)
384
+ end
385
+ rescue ArgumentError => e
386
+ fail(Issues::APPEND_FAILED, o, {:message => e.message}, e)
387
+ end
388
+ else
389
+ fail(Issues::UNSUPPORTED_OPERATOR, o, {:operator => o.operator})
390
+ end
391
+ value
392
+ end
393
+
394
+ ARITHMETIC_OPERATORS = [:'+', :'-', :'*', :'/', :'%', :'<<', :'>>']
395
+ COLLECTION_OPERATORS = [:'+', :'-', :'<<']
396
+
397
+ # Handles binary expression where lhs and rhs are array/hash or numeric and operator is +, - , *, % / << >>
398
+ #
399
+ def eval_ArithmeticExpression(o, scope)
400
+ left, right = eval_BinaryExpression(o, scope)
401
+ begin
402
+ result = calculate(left, right, o.operator, o.left_expr, o.right_expr, scope)
403
+ rescue ArgumentError => e
404
+ fail(Issues::RUNTIME_ERROR, o, {:detail => e.message}, e)
405
+ end
406
+ result
407
+ end
408
+
409
+
410
+ # Handles binary expression where lhs and rhs are array/hash or numeric and operator is +, - , *, % / << >>
411
+ #
412
+ def calculate(left, right, operator, left_o, right_o, scope)
413
+ unless ARITHMETIC_OPERATORS.include?(operator)
414
+ fail(Issues::UNSUPPORTED_OPERATOR, left_o.eContainer, {:operator => o.operator})
415
+ end
416
+
417
+ if (left.is_a?(Array) || left.is_a?(Hash)) && COLLECTION_OPERATORS.include?(operator)
418
+ # Handle operation on collections
419
+ case operator
420
+ when :'+'
421
+ concatenate(left, right)
422
+ when :'-'
423
+ delete(left, right)
424
+ when :'<<'
425
+ unless left.is_a?(Array)
426
+ fail(Issues::OPERATOR_NOT_APPLICABLE, left_o, {:operator => operator, :left_value => left})
427
+ end
428
+ left + [right]
429
+ end
430
+ else
431
+ # Handle operation on numeric
432
+ left = coerce_numeric(left, left_o, scope)
433
+ right = coerce_numeric(right, right_o, scope)
434
+ begin
435
+ if operator == :'%' && (left.is_a?(Float) || right.is_a?(Float))
436
+ # Deny users the fun of seeing severe rounding errors and confusing results
437
+ fail(Issues::OPERATOR_NOT_APPLICABLE, left_o, {:operator => operator, :left_value => left})
438
+ end
439
+ result = left.send(operator, right)
440
+ rescue NoMethodError => e
441
+ fail(Issues::OPERATOR_NOT_APPLICABLE, left_o, {:operator => operator, :left_value => left})
442
+ rescue ZeroDivisionError => e
443
+ fail(Issues::DIV_BY_ZERO, right_o)
444
+ end
445
+ if result == INFINITY || result == -INFINITY
446
+ fail(Issues::RESULT_IS_INFINITY, left_o, {:operator => operator})
447
+ end
448
+ result
449
+ end
450
+ end
451
+
452
+ def eval_EppExpression(o, scope)
453
+ scope["@epp"] = []
454
+ evaluate(o.body, scope)
455
+ result = scope["@epp"].join('')
456
+ result
457
+ end
458
+
459
+ def eval_RenderStringExpression(o, scope)
460
+ scope["@epp"] << o.value.dup
461
+ nil
462
+ end
463
+
464
+ def eval_RenderExpression(o, scope)
465
+ scope["@epp"] << string(evaluate(o.expr, scope), scope)
466
+ nil
467
+ end
468
+
469
+ # Evaluates Puppet DSL ->, ~>, <-, and <~
470
+ def eval_RelationshipExpression(o, scope)
471
+ # First level evaluation, reduction to basic data types or puppet types, the relationship operator then translates this
472
+ # to the final set of references (turning strings into references, which can not naturally be done by the main evaluator since
473
+ # all strings should not be turned into references.
474
+ #
475
+ real = eval_BinaryExpression(o, scope)
476
+ @@relationship_operator.evaluate(real, o, scope)
477
+ end
478
+
479
+ # Evaluates x[key, key, ...]
480
+ #
481
+ def eval_AccessExpression(o, scope)
482
+ left = evaluate(o.left_expr, scope)
483
+ keys = o.keys.nil? ? [] : o.keys.collect {|key| evaluate(key, scope) }
484
+ Puppet::Pops::Evaluator::AccessOperator.new(o).access(left, scope, *keys)
485
+ end
486
+
487
+ # Evaluates <, <=, >, >=, and ==
488
+ #
489
+ def eval_ComparisonExpression o, scope
490
+ left, right = eval_BinaryExpression o, scope
491
+
492
+ begin
493
+ # Left is a type
494
+ if left.is_a?(Puppet::Pops::Types::PAbstractType)
495
+ case o.operator
496
+ when :'=='
497
+ @@type_calculator.equals(left,right)
498
+
499
+ when :'!='
500
+ !@@type_calculator.equals(left,right)
501
+
502
+ when :'<'
503
+ # left can be assigned to right, but they are not equal
504
+ @@type_calculator.assignable?(right, left) && ! @@type_calculator.equals(left,right)
505
+ when :'<='
506
+ # left can be assigned to right
507
+ @@type_calculator.assignable?(right, left)
508
+ when :'>'
509
+ # right can be assigned to left, but they are not equal
510
+ @@type_calculator.assignable?(left,right) && ! @@type_calculator.equals(left,right)
511
+ when :'>='
512
+ # right can be assigned to left
513
+ @@type_calculator.assignable?(left, right)
514
+ else
515
+ fail(Issues::UNSUPPORTED_OPERATOR, o, {:operator => o.operator})
516
+ end
517
+ else
518
+ case o.operator
519
+ when :'=='
520
+ @@compare_operator.equals(left,right)
521
+ when :'!='
522
+ ! @@compare_operator.equals(left,right)
523
+ when :'<'
524
+ @@compare_operator.compare(left,right) < 0
525
+ when :'<='
526
+ @@compare_operator.compare(left,right) <= 0
527
+ when :'>'
528
+ @@compare_operator.compare(left,right) > 0
529
+ when :'>='
530
+ @@compare_operator.compare(left,right) >= 0
531
+ else
532
+ fail(Issues::UNSUPPORTED_OPERATOR, o, {:operator => o.operator})
533
+ end
534
+ end
535
+ rescue ArgumentError => e
536
+ fail(Issues::COMPARISON_NOT_POSSIBLE, o, {
537
+ :operator => o.operator,
538
+ :left_value => left,
539
+ :right_value => right,
540
+ :detail => e.message}, e)
541
+ end
542
+ end
543
+
544
+ # Evaluates matching expressions with type, string or regexp rhs expression.
545
+ # If RHS is a type, the =~ matches compatible (assignable?) type.
546
+ #
547
+ # @example
548
+ # x =~ /abc.*/
549
+ # @example
550
+ # x =~ "abc.*/"
551
+ # @example
552
+ # y = "abc"
553
+ # x =~ "${y}.*"
554
+ # @example
555
+ # [1,2,3] =~ Array[Integer[1,10]]
556
+ # @return [Boolean] if a match was made or not. Also sets $0..$n to matchdata in current scope.
557
+ #
558
+ def eval_MatchExpression o, scope
559
+ left, pattern = eval_BinaryExpression o, scope
560
+ # matches RHS types as instance of for all types except a parameterized Regexp[R]
561
+ if pattern.is_a?(Puppet::Pops::Types::PAbstractType)
562
+ if pattern.is_a?(Puppet::Pops::Types::PRegexpType) && pattern.pattern
563
+ # A qualified PRegexpType, get its ruby regexp
564
+ pattern = pattern.regexp
565
+ else
566
+ # evaluate as instance?
567
+ matched = @@type_calculator.instance?(pattern, left)
568
+ # convert match result to Boolean true, or false
569
+ return o.operator == :'=~' ? !!matched : !matched
570
+ end
571
+ end
572
+
573
+ begin
574
+ pattern = Regexp.new(pattern) unless pattern.is_a?(Regexp)
575
+ rescue StandardError => e
576
+ fail(Issues::MATCH_NOT_REGEXP, o.right_expr, {:detail => e.message}, e)
577
+ end
578
+ unless left.is_a?(String)
579
+ fail(Issues::MATCH_NOT_STRING, o.left_expr, {:left_value => left})
580
+ end
581
+
582
+ matched = pattern.match(left) # nil, or MatchData
583
+ set_match_data(matched, o, scope) # creates ephemeral
584
+
585
+ # convert match result to Boolean true, or false
586
+ o.operator == :'=~' ? !!matched : !matched
587
+ end
588
+
589
+ # Evaluates Puppet DSL `in` expression
590
+ #
591
+ def eval_InExpression o, scope
592
+ left, right = eval_BinaryExpression o, scope
593
+ @@compare_operator.include?(right, left)
594
+ end
595
+
596
+ # @example
597
+ # $a and $b
598
+ # b is only evaluated if a is true
599
+ #
600
+ def eval_AndExpression o, scope
601
+ is_true?(evaluate(o.left_expr, scope)) ? is_true?(evaluate(o.right_expr, scope)) : false
602
+ end
603
+
604
+ # @example
605
+ # a or b
606
+ # b is only evaluated if a is false
607
+ #
608
+ def eval_OrExpression o, scope
609
+ is_true?(evaluate(o.left_expr, scope)) ? true : is_true?(evaluate(o.right_expr, scope))
610
+ end
611
+
612
+ # Evaluates each entry of the literal list and creates a new Array
613
+ # @return [Array] with the evaluated content
614
+ #
615
+ def eval_LiteralList o, scope
616
+ o.values.collect {|expr| evaluate(expr, scope)}
617
+ end
618
+
619
+ # Evaluates each entry of the literal hash and creates a new Hash.
620
+ # @return [Hash] with the evaluated content
621
+ #
622
+ def eval_LiteralHash o, scope
623
+ h = Hash.new
624
+ o.entries.each {|entry| h[ evaluate(entry.key, scope)]= evaluate(entry.value, scope)}
625
+ h
626
+ end
627
+
628
+ # Evaluates all statements and produces the last evaluated value
629
+ #
630
+ def eval_BlockExpression o, scope
631
+ r = nil
632
+ o.statements.each {|s| r = evaluate(s, scope)}
633
+ r
634
+ end
635
+
636
+ # Performs optimized search over case option values, lazily evaluating each
637
+ # until there is a match. If no match is found, the case expression's default expression
638
+ # is evaluated (it may be nil or Nop if there is no default, thus producing nil).
639
+ # If an option matches, the result of evaluating that option is returned.
640
+ # @return [Object, nil] what a matched option returns, or nil if nothing matched.
641
+ #
642
+ def eval_CaseExpression(o, scope)
643
+ # memo scope level before evaluating test - don't want a match in the case test to leak $n match vars
644
+ # to expressions after the case expression.
645
+ #
646
+ with_guarded_scope(scope) do
647
+ test = evaluate(o.test, scope)
648
+ result = nil
649
+ the_default = nil
650
+ if o.options.find do |co|
651
+ # the first case option that matches
652
+ if co.values.find do |c|
653
+ the_default = co.then_expr if c.is_a? Puppet::Pops::Model::LiteralDefault
654
+ is_match?(test, evaluate(c, scope), c, scope)
655
+ end
656
+ result = evaluate(co.then_expr, scope)
657
+ true # the option was picked
658
+ end
659
+ end
660
+ result # an option was picked, and produced a result
661
+ else
662
+ evaluate(the_default, scope) # evaluate the default (should be a nop/nil) if there is no default).
663
+ end
664
+ end
665
+ end
666
+
667
+ # Evaluates a CollectExpression by transforming it into a 3x AST::Collection and then evaluating that.
668
+ # This is done because of the complex API between compiler, indirector, backends, and difference between
669
+ # collecting virtual resources and exported resources.
670
+ #
671
+ def eval_CollectExpression o, scope
672
+ # The Collect Expression and its contained query expressions are implemented in such a way in
673
+ # 3x that it is almost impossible to do anything about them (the AST objects are lazily evaluated,
674
+ # and the built structure consists of both higher order functions and arrays with query expressions
675
+ # that are either used as a predicate filter, or given to an indirection terminus (such as the Puppet DB
676
+ # resource terminus). Unfortunately, the 3x implementation has many inconsistencies that the implementation
677
+ # below carries forward.
678
+ #
679
+ collect_3x = Puppet::Pops::Model::AstTransformer.new().transform(o)
680
+ collected = collect_3x.evaluate(scope)
681
+ # the 3x returns an instance of Parser::Collector (but it is only registered with the compiler at this
682
+ # point and does not contain any valuable information (like the result)
683
+ # Dilemma: If this object is returned, it is a first class value in the Puppet Language and we
684
+ # need to be able to perform operations on it. We can forbid it from leaking by making CollectExpression
685
+ # a non R-value. This makes it possible for the evaluator logic to make use of the Collector.
686
+ collected
687
+ end
688
+
689
+ def eval_ParenthesizedExpression(o, scope)
690
+ evaluate(o.expr, scope)
691
+ end
692
+
693
+ # This evaluates classes, nodes and resource type definitions to nil, since 3x:
694
+ # instantiates them, and evaluates their parameters and body. This is achieved by
695
+ # providing bridge AST classes in Puppet::Parser::AST::PopsBridge that bridges a
696
+ # Pops Program and a Pops Expression.
697
+ #
698
+ # Since all Definitions are handled "out of band", they are treated as a no-op when
699
+ # evaluated.
700
+ #
701
+ def eval_Definition(o, scope)
702
+ nil
703
+ end
704
+
705
+ def eval_Program(o, scope)
706
+ evaluate(o.body, scope)
707
+ end
708
+
709
+ # Produces Array[PObjectType], an array of resource references
710
+ #
711
+ def eval_ResourceExpression(o, scope)
712
+ exported = o.exported
713
+ virtual = o.virtual
714
+ type_name = evaluate(o.type_name, scope)
715
+ o.bodies.map do |body|
716
+ titles = [evaluate(body.title, scope)].flatten
717
+ evaluated_parameters = body.operations.map {|op| evaluate(op, scope) }
718
+ create_resources(o, scope, virtual, exported, type_name, titles, evaluated_parameters)
719
+ end.flatten.compact
720
+ end
721
+
722
+ def eval_ResourceOverrideExpression(o, scope)
723
+ evaluated_resources = evaluate(o.resources, scope)
724
+ evaluated_parameters = o.operations.map { |op| evaluate(op, scope) }
725
+ create_resource_overrides(o, scope, [evaluated_resources].flatten, evaluated_parameters)
726
+ evaluated_resources
727
+ end
728
+
729
+ # Produces 3x array of parameters
730
+ def eval_AttributeOperation(o, scope)
731
+ create_resource_parameter(o, scope, o.attribute_name, evaluate(o.value_expr, scope), o.operator)
732
+ end
733
+
734
+ # Sets default parameter values for a type, produces the type
735
+ #
736
+ def eval_ResourceDefaultsExpression(o, scope)
737
+ type_name = o.type_ref.value # a QualifiedName's string value
738
+ evaluated_parameters = o.operations.map {|op| evaluate(op, scope) }
739
+ create_resource_defaults(o, scope, type_name, evaluated_parameters)
740
+ # Produce the type
741
+ evaluate(o.type_ref, scope)
742
+ end
743
+
744
+ # Evaluates function call by name.
745
+ #
746
+ def eval_CallNamedFunctionExpression(o, scope)
747
+ # The functor expression is not evaluated, it is not possible to select the function to call
748
+ # via an expression like $a()
749
+ case o.functor_expr
750
+ when Puppet::Pops::Model::QualifiedName
751
+ # ok
752
+ when Puppet::Pops::Model::RenderStringExpression
753
+ # helpful to point out this easy to make Epp error
754
+ fail(Issues::ILLEGAL_EPP_PARAMETERS, o)
755
+ else
756
+ fail(Issues::ILLEGAL_EXPRESSION, o.functor_expr, {:feature=>'function name', :container => o})
757
+ end
758
+ name = o.functor_expr.value
759
+ assert_function_available(name, o, scope)
760
+ evaluated_arguments = o.arguments.collect {|arg| evaluate(arg, scope) }
761
+ # wrap lambda in a callable block if it is present
762
+ evaluated_arguments << Puppet::Pops::Evaluator::Closure.new(self, o.lambda, scope) if o.lambda
763
+ call_function(name, evaluated_arguments, o, scope) do |result|
764
+ # prevent functions that are not r-value from leaking its return value
765
+ rvalue_function?(name, o, scope) ? result : nil
766
+ end
767
+ end
768
+
769
+ # Evaluation of CallMethodExpression handles a NamedAccessExpression functor (receiver.function_name)
770
+ #
771
+ def eval_CallMethodExpression(o, scope)
772
+ unless o.functor_expr.is_a? Puppet::Pops::Model::NamedAccessExpression
773
+ fail(Issues::ILLEGAL_EXPRESSION, o.functor_expr, {:feature=>'function accessor', :container => o})
774
+ end
775
+ receiver = evaluate(o.functor_expr.left_expr, scope)
776
+ name = o.functor_expr.right_expr
777
+ unless name.is_a? Puppet::Pops::Model::QualifiedName
778
+ fail(Issues::ILLEGAL_EXPRESSION, o.functor_expr, {:feature=>'function name', :container => o})
779
+ end
780
+ name = name.value # the string function name
781
+ assert_function_available(name, o, scope)
782
+ evaluated_arguments = [receiver] + (o.arguments || []).collect {|arg| evaluate(arg, scope) }
783
+ evaluated_arguments << Puppet::Pops::Evaluator::Closure.new(self, o.lambda, scope) if o.lambda
784
+ call_function(name, evaluated_arguments, o, scope) do |result|
785
+ # prevent functions that are not r-value from leaking its return value
786
+ rvalue_function?(name, o, scope) ? result : nil
787
+ end
788
+ end
789
+
790
+ # @example
791
+ # $x ? { 10 => true, 20 => false, default => 0 }
792
+ #
793
+ def eval_SelectorExpression o, scope
794
+ # memo scope level before evaluating test - don't want a match in the case test to leak $n match vars
795
+ # to expressions after the selector expression.
796
+ #
797
+ with_guarded_scope(scope) do
798
+ test = evaluate(o.left_expr, scope)
799
+ selected = o.selectors.find do |s|
800
+ candidate = evaluate(s.matching_expr, scope)
801
+ candidate == :default || is_match?(test, candidate, s.matching_expr, scope)
802
+ end
803
+ if selected
804
+ evaluate(selected.value_expr, scope)
805
+ else
806
+ nil
807
+ end
808
+ end
809
+ end
810
+
811
+ # SubLocatable is simply an expression that holds location information
812
+ def eval_SubLocatedExpression o, scope
813
+ evaluate(o.expr, scope)
814
+ end
815
+
816
+ # Evaluates Puppet DSL Heredoc
817
+ def eval_HeredocExpression o, scope
818
+ result = evaluate(o.text_expr, scope)
819
+ assert_external_syntax(scope, result, o.syntax, o.text_expr)
820
+ result
821
+ end
822
+
823
+ # Evaluates Puppet DSL `if`
824
+ def eval_IfExpression o, scope
825
+ with_guarded_scope(scope) do
826
+ if is_true?(evaluate(o.test, scope))
827
+ evaluate(o.then_expr, scope)
828
+ else
829
+ evaluate(o.else_expr, scope)
830
+ end
831
+ end
832
+ end
833
+
834
+ # Evaluates Puppet DSL `unless`
835
+ def eval_UnlessExpression o, scope
836
+ with_guarded_scope(scope) do
837
+ unless is_true?(evaluate(o.test, scope))
838
+ evaluate(o.then_expr, scope)
839
+ else
840
+ evaluate(o.else_expr, scope)
841
+ end
842
+ end
843
+ end
844
+
845
+ # Evaluates a variable (getting its value)
846
+ # The evaluator is lenient; any expression producing a String is used as a name
847
+ # of a variable.
848
+ #
849
+ def eval_VariableExpression o, scope
850
+ # Evaluator is not too fussy about what constitutes a name as long as the result
851
+ # is a String and a valid variable name
852
+ #
853
+ name = evaluate(o.expr, scope)
854
+
855
+ # Should be caught by validation, but make this explicit here as well, or mysterious evaluation issues
856
+ # may occur.
857
+ case name
858
+ when String
859
+ when Numeric
860
+ else
861
+ fail(Issues::ILLEGAL_VARIABLE_EXPRESSION, o.expr)
862
+ end
863
+ # TODO: Check for valid variable name (Task for validator)
864
+ # TODO: semantics of undefined variable in scope, this just returns what scope does == value or nil
865
+ get_variable_value(name, o, scope)
866
+ end
867
+
868
+ # Evaluates double quoted strings that may contain interpolation
869
+ #
870
+ def eval_ConcatenatedString o, scope
871
+ o.segments.collect {|expr| string(evaluate(expr, scope), scope)}.join
872
+ end
873
+
874
+
875
+ # If the wrapped expression is a QualifiedName, it is taken as the name of a variable in scope.
876
+ # Note that this is different from the 3.x implementation, where an initial qualified name
877
+ # is accepted. (e.g. `"---${var + 1}---"` is legal. This implementation requires such concrete
878
+ # syntax to be expressed in a model as `(TextExpression (+ (Variable var) 1)` - i.e. moving the decision to
879
+ # the parser.
880
+ #
881
+ # Semantics; the result of an expression is turned into a string, nil is silently transformed to empty
882
+ # string.
883
+ # @return [String] the interpolated result
884
+ #
885
+ def eval_TextExpression o, scope
886
+ if o.expr.is_a?(Puppet::Pops::Model::QualifiedName)
887
+ # TODO: formalize, when scope returns nil, vs error
888
+ string(get_variable_value(o.expr.value, o, scope), scope)
889
+ else
890
+ string(evaluate(o.expr, scope), scope)
891
+ end
892
+ end
893
+
894
+ def string_Object(o, scope)
895
+ o.to_s
896
+ end
897
+
898
+ def string_Symbol(o, scope)
899
+ case o
900
+ when :undef
901
+ ''
902
+ else
903
+ o.to_s
904
+ end
905
+ end
906
+
907
+ def string_Array(o, scope)
908
+ ['[', o.map {|e| string(e, scope)}.join(', '), ']'].join()
909
+ end
910
+
911
+ def string_Hash(o, scope)
912
+ ['{', o.map {|k,v| string(k, scope) + " => " + string(v, scope)}.join(', '), '}'].join()
913
+ end
914
+
915
+ def string_Regexp(o, scope)
916
+ ['/', o.source, '/'].join()
917
+ end
918
+
919
+ def string_PAbstractType(o, scope)
920
+ @@type_calculator.string(o)
921
+ end
922
+
923
+ # Produces concatenation / merge of x and y.
924
+ #
925
+ # When x is an Array, y of type produces:
926
+ #
927
+ # * Array => concatenation `[1,2], [3,4] => [1,2,3,4]`
928
+ # * Hash => concatenation of hash as array `[key, value, key, value, ...]`
929
+ # * any other => concatenation of single value
930
+ #
931
+ # When x is a Hash, y of type produces:
932
+ #
933
+ # * Array => merge of array interpreted as `[key, value, key, value,...]`
934
+ # * Hash => a merge, where entries in `y` overrides
935
+ # * any other => error
936
+ #
937
+ # When x is something else, wrap it in an array first.
938
+ #
939
+ # When x is nil, an empty array is used instead.
940
+ #
941
+ # @note to concatenate an Array, nest the array - i.e. `[1,2], [[2,3]]`
942
+ #
943
+ # @overload concatenate(obj_x, obj_y)
944
+ # @param obj_x [Object] object to wrap in an array and concatenate to; see other overloaded methods for return type
945
+ # @param ary_y [Object] array to concatenate at end of `ary_x`
946
+ # @return [Object] wraps obj_x in array before using other overloaded option based on type of obj_y
947
+ # @overload concatenate(ary_x, ary_y)
948
+ # @param ary_x [Array] array to concatenate to
949
+ # @param ary_y [Array] array to concatenate at end of `ary_x`
950
+ # @return [Array] new array with `ary_x` + `ary_y`
951
+ # @overload concatenate(ary_x, hsh_y)
952
+ # @param ary_x [Array] array to concatenate to
953
+ # @param hsh_y [Hash] converted to array form, and concatenated to array
954
+ # @return [Array] new array with `ary_x` + `hsh_y` converted to array
955
+ # @overload concatenate (ary_x, obj_y)
956
+ # @param ary_x [Array] array to concatenate to
957
+ # @param obj_y [Object] non array or hash object to add to array
958
+ # @return [Array] new array with `ary_x` + `obj_y` added as last entry
959
+ # @overload concatenate(hsh_x, ary_y)
960
+ # @param hsh_x [Hash] the hash to merge with
961
+ # @param ary_y [Array] array interpreted as even numbered sequence of key, value merged with `hsh_x`
962
+ # @return [Hash] new hash with `hsh_x` merged with `ary_y` interpreted as hash in array form
963
+ # @overload concatenate(hsh_x, hsh_y)
964
+ # @param hsh_x [Hash] the hash to merge to
965
+ # @param hsh_y [Hash] hash merged with `hsh_x`
966
+ # @return [Hash] new hash with `hsh_x` merged with `hsh_y`
967
+ # @raise [ArgumentError] when `xxx_x` is neither an Array nor a Hash
968
+ # @raise [ArgumentError] when `xxx_x` is a Hash, and `xxx_y` is neither Array nor Hash.
969
+ #
970
+ def concatenate(x, y)
971
+ x = [x] unless x.is_a?(Array) || x.is_a?(Hash)
972
+ case x
973
+ when Array
974
+ y = case y
975
+ when Array then y
976
+ when Hash then y.to_a
977
+ else
978
+ [y]
979
+ end
980
+ x + y # new array with concatenation
981
+ when Hash
982
+ y = case y
983
+ when Hash then y
984
+ when Array
985
+ # Hash[[a, 1, b, 2]] => {}
986
+ # Hash[a,1,b,2] => {a => 1, b => 2}
987
+ # Hash[[a,1], [b,2]] => {[a,1] => [b,2]}
988
+ # Hash[[[a,1], [b,2]]] => {a => 1, b => 2}
989
+ # Use type calcultor to determine if array is Array[Array[?]], and if so use second form
990
+ # of call
991
+ t = @@type_calculator.infer(y)
992
+ if t.element_type.is_a? Puppet::Pops::Types::PArrayType
993
+ Hash[y]
994
+ else
995
+ Hash[*y]
996
+ end
997
+ else
998
+ raise ArgumentError.new("Can only append Array or Hash to a Hash")
999
+ end
1000
+ x.merge y # new hash with overwrite
1001
+ else
1002
+ raise ArgumentError.new("Can only append to an Array or a Hash.")
1003
+ end
1004
+ end
1005
+
1006
+ # Produces the result x \ y (set difference)
1007
+ # When `x` is an Array, `y` is transformed to an array and then all matching elements removed from x.
1008
+ # When `x` is a Hash, all contained keys are removed from x as listed in `y` if it is an Array, or all its keys if it is a Hash.
1009
+ # The difference is returned. The given `x` and `y` are not modified by this operation.
1010
+ # @raise [ArgumentError] when `x` is neither an Array nor a Hash
1011
+ #
1012
+ def delete(x, y)
1013
+ result = x.dup
1014
+ case x
1015
+ when Array
1016
+ y = case y
1017
+ when Array then y
1018
+ when Hash then y.to_a
1019
+ else
1020
+ [y]
1021
+ end
1022
+ y.each {|e| result.delete(e) }
1023
+ when Hash
1024
+ y = case y
1025
+ when Array then y
1026
+ when Hash then y.keys
1027
+ else
1028
+ [y]
1029
+ end
1030
+ y.each {|e| result.delete(e) }
1031
+ else
1032
+ raise ArgumentError.new("Can only delete from an Array or Hash.")
1033
+ end
1034
+ result
1035
+ end
1036
+
1037
+ # Implementation of case option matching.
1038
+ #
1039
+ # This is the type of matching performed in a case option, using == for every type
1040
+ # of value except regular expression where a match is performed.
1041
+ #
1042
+ def is_match? left, right, o, scope
1043
+ if right.is_a?(Regexp)
1044
+ return false unless left.is_a? String
1045
+ matched = right.match(left)
1046
+ set_match_data(matched, o, scope) # creates or clears ephemeral
1047
+ !!matched # convert to boolean
1048
+ elsif right.is_a?(Puppet::Pops::Types::PAbstractType)
1049
+ # right is a type and left is not - check if left is an instance of the given type
1050
+ # (The reverse is not terribly meaningful - computing which of the case options that first produces
1051
+ # an instance of a given type).
1052
+ #
1053
+ @@type_calculator.instance?(right, left)
1054
+ else
1055
+ # Handle equality the same way as the language '==' operator (case insensitive etc.)
1056
+ @@compare_operator.equals(left,right)
1057
+ end
1058
+ end
1059
+
1060
+ def with_guarded_scope(scope)
1061
+ scope_memo = get_scope_nesting_level(scope)
1062
+ begin
1063
+ yield
1064
+ ensure
1065
+ set_scope_nesting_level(scope, scope_memo)
1066
+ end
1067
+ end
1068
+
1069
+ end