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,95 @@
1
+ # This module is an integral part of the Lexer.
2
+ # It defines the string slurping behavior - finding the string and non string parts in interpolated
3
+ # strings, translating escape sequences in strings to their single character equivalence.
4
+ #
5
+ # PERFORMANCE NOTE: The various kinds of slurping could be made even more generic, but requires
6
+ # additional parameter passing and evaluation of conditional logic.
7
+ # TODO: More detailed performance analysis of excessive character escaping and interpolation.
8
+ #
9
+ module Puppet::Pops::Parser::SlurpSupport
10
+
11
+ SLURP_SQ_PATTERN = /(?:[^\\]|^|[^\\])(?:[\\]{2})*[']/
12
+ SLURP_DQ_PATTERN = /(?:[^\\]|^|[^\\])(?:[\\]{2})*(["]|[$]\{?)/
13
+ SLURP_UQ_PATTERN = /(?:[^\\]|^|[^\\])(?:[\\]{2})*([$]\{?|\z)/
14
+ SLURP_ALL_PATTERN = /.*(\z)/m
15
+ SQ_ESCAPES = %w{ \\ ' }
16
+ DQ_ESCAPES = %w{ \\ $ ' " r n t s u}+["\r\n", "\n"]
17
+ UQ_ESCAPES = %w{ \\ $ r n t s u}+["\r\n", "\n"]
18
+
19
+ def slurp_sqstring
20
+ # skip the leading '
21
+ @scanner.pos += 1
22
+ str = slurp(@scanner, SLURP_SQ_PATTERN, SQ_ESCAPES, :ignore_invalid_escapes) || lex_error("Unclosed quote after \"'\" followed by '#{followed_by}'")
23
+ str[0..-2] # strip closing "'" from result
24
+ end
25
+
26
+ def slurp_dqstring
27
+ scn = @scanner
28
+ last = scn.matched
29
+ str = slurp(scn, SLURP_DQ_PATTERN, DQ_ESCAPES, false)
30
+ unless str
31
+ lex_error("Unclosed quote after #{format_quote(last)} followed by '#{followed_by}'")
32
+ end
33
+
34
+ # Terminator may be a single char '"', '$', or two characters '${' group match 1 (scn[1]) from the last slurp holds this
35
+ terminator = scn[1]
36
+ [str[0..(-1 - terminator.length)], terminator]
37
+ end
38
+
39
+ # Copy from old lexer - can do much better
40
+ def slurp_uqstring
41
+ scn = @scanner
42
+ last = scn.matched
43
+ ignore = true
44
+ str = slurp(scn, @lexing_context[:uq_slurp_pattern], @lexing_context[:escapes], :ignore_invalid_escapes)
45
+
46
+ # Terminator may be a single char '$', two characters '${', or empty string '' at the end of intput.
47
+ # Group match 1 holds this.
48
+ # The exceptional case is found by looking at the subgroup 1 of the most recent match made by the scanner (i.e. @scanner[1]).
49
+ # This is the last match made by the slurp method (having called scan_until on the scanner).
50
+ # If there is a terminating character is must be stripped and returned separately.
51
+ #
52
+ terminator = scn[1]
53
+ [str[0..(-1 - terminator.length)], terminator]
54
+ end
55
+
56
+ # Slurps a string from the given scanner until the given pattern and then replaces any escaped
57
+ # characters given by escapes into their control-character equivalent or in case of line breaks, replaces the
58
+ # pattern \r?\n with an empty string.
59
+ # The returned string contains the terminating character. Returns nil if the scanner can not scan until the given
60
+ # pattern.
61
+ #
62
+ def slurp(scanner, pattern, escapes, ignore_invalid_escapes)
63
+ str = scanner.scan_until(pattern) || return
64
+
65
+ # Process unicode escapes first as they require getting 4 hex digits
66
+ # If later a \u is found it is warned not to be a unicode escape
67
+ if escapes.include?('u')
68
+ str.gsub!(/\\u([\da-fA-F]{4})/m) {
69
+ [$1.hex].pack("U")
70
+ }
71
+ end
72
+
73
+ str.gsub!(/\\([^\r\n]|(?:\r?\n))/m) {
74
+ ch = $1
75
+ if escapes.include? ch
76
+ case ch
77
+ when 'r' ; "\r"
78
+ when 'n' ; "\n"
79
+ when 't' ; "\t"
80
+ when 's' ; " "
81
+ when 'u'
82
+ Puppet.warning(positioned_message("Unicode escape '\\u' was not followed by 4 hex digits"))
83
+ "\\u"
84
+ when "\n" ; ''
85
+ when "\r\n"; ''
86
+ else ch
87
+ end
88
+ else
89
+ Puppet.warning(positioned_message("Unrecognized escape sequence '\\#{ch}'")) unless ignore_invalid_escapes
90
+ "\\#{ch}"
91
+ end
92
+ }
93
+ str
94
+ end
95
+ end
@@ -17,19 +17,28 @@ module Puppet::Pops::Patterns
17
17
  ILLEGAL_HOSTNAME_CHARS = %r{[^-\w.]}
18
18
 
19
19
  # NAME matches a name the same way as the lexer.
20
- # This name includes hyphen, which may be illegal in variables, and names in general.
21
- NAME = %r{\A((::)?[a-z0-9]\w*)(::[a-z0-9]\w*)*\z}
20
+ NAME = %r{\A((::)?[a-z]\w*)(::[a-z]\w*)*\z}
22
21
 
23
22
  # CLASSREF_EXT matches a class reference the same way as the lexer - i.e. the external source form
24
23
  # where each part must start with a capital letter A-Z.
25
24
  # This name includes hyphen, which may be illegal in some cases.
26
25
  #
27
- CLASSREF_EXT = %r{\A((::){0,1}[A-Z][-\w]*)+\z}
26
+ CLASSREF_EXT = %r{\A((::){0,1}[A-Z][\w]*)+\z}
28
27
 
29
28
  # CLASSREF matches a class reference the way it is represented internally in the
30
29
  # model (i.e. in lower case).
31
30
  # This name includes hyphen, which may be illegal in some cases.
32
31
  #
33
- CLASSREF = %r{\A((::){0,1}[a-z][-\w]*)+\z}
32
+ CLASSREF = %r{\A((::){0,1}[a-z][\w]*)+\z}
33
+
34
+ # DOLLAR_VAR matches a variable name including the initial $ character
35
+ DOLLAR_VAR = %r{\$(::)?(\w+::)*\w+}
36
+
37
+ # VAR_NAME matches the name part of a variable (The $ character is not included)
38
+ # Note, that only the final segment may start with an underscore.
39
+ VAR_NAME = %r{\A(:?(::)?[a-z]\w*)*(:?(::)?[a-z_]\w*)\z}
40
+
41
+ # A Numeric var name must be the decimal number 0, or a decimal number not starting with 0
42
+ NUMERIC_VAR_NAME = %r{\A(?:0|(?:[1-9][0-9]*))\z}
34
43
 
35
44
  end
@@ -52,7 +52,7 @@ class Puppet::Pops::Types::ClassLoader
52
52
  #
53
53
  when Puppet::Pops::Types::PArrayType ; Array
54
54
  when Puppet::Pops::Types::PHashType ; Hash
55
- when Puppet::Pops::Types::PPatternType ; Regexp
55
+ when Puppet::Pops::Types::PRegexpType ; Regexp
56
56
  when Puppet::Pops::Types::PIntegerType ; Integer
57
57
  when Puppet::Pops::Types::PStringType ; String
58
58
  when Puppet::Pops::Types::PFloatType ; Float
@@ -115,4 +115,4 @@ class Puppet::Pops::Types::ClassLoader
115
115
  downcase
116
116
  end
117
117
 
118
- end
118
+ end
@@ -0,0 +1,34 @@
1
+ # The Enumeration class provides default Enumerable::Enumerator creation for Puppet Programming Language
2
+ # runtime objects that supports the concept of enumeration.
3
+ #
4
+ class Puppet::Pops::Types::Enumeration
5
+ # Produces an Enumerable::Enumerator for Array, Hash, Integer, Integer Range, and String.
6
+ #
7
+ def self.enumerator(o)
8
+ @@singleton ||= new
9
+ @@singleton.enumerator(o)
10
+ end
11
+
12
+ # Produces an Enumerator for Array, Hash, Integer, Integer Range, and String.
13
+ #
14
+ def enumerator(o)
15
+ case o
16
+ when String
17
+ x = o.chars
18
+ # Ruby 1.8.7 returns Enumerable::Enumerator, Ruby 1.8.9 Enumerator, and 2.0.0 an Array
19
+ x.is_a?(Array) ? x.each : x
20
+ when Integer
21
+ o.times
22
+ when Array
23
+ o.each
24
+ when Hash
25
+ o.each
26
+ when Puppet::Pops::Types::PIntegerType
27
+ # Not enumerable if representing an infinite range
28
+ return nil if o.to.nil? || o.from.nil?
29
+ o.each
30
+ else
31
+ nil
32
+ end
33
+ end
34
+ end
@@ -3,13 +3,28 @@
3
3
  # The Puppet type system is primarily based on sub-classing. When asking the type calculator to infer types from Ruby in general, it
4
4
  # may not provide the wanted answer; it does not for instance take module inclusions and extensions into account. In general the type
5
5
  # system should be unsurprising for anyone being exposed to the notion of type. The type `Data` may require a bit more explanation; this
6
- # is an abstract type that includes all literal types, as well as Array with an element type compatible with Data, and Hash with key
7
- # compatible with Literal and elements compatible with Data. Expressed differently; Data is what you typically express using JSON (with
8
- # the exception that the Puppet type system also includes Pattern (regular expression) as a literal.
6
+ # is an abstract type that includes all scalar types, as well as Array with an element type compatible with Data, and Hash with key
7
+ # compatible with scalar and elements compatible with Data. Expressed differently; Data is what you typically express using JSON (with
8
+ # the exception that the Puppet type system also includes Pattern (regular expression) as a scalar.
9
9
  #
10
10
  # Inference
11
11
  # ---------
12
- # The `infer(o)` method infers a Puppet type for literal Ruby objects, and for Arrays and Hashes.
12
+ # The `infer(o)` method infers a Puppet type for scalar Ruby objects, and for Arrays and Hashes.
13
+ # The inference result is instance specific for single typed collections
14
+ # and allows answering questions about its embedded type. It does not however preserve multiple types in
15
+ # a collection, and can thus not answer questions like `[1,a].infer() =~ Array[Integer, String]` since the inference
16
+ # computes the common type Scalar when combining Integer and String.
17
+ #
18
+ # The `infer_generic(o)` method infers a generic Puppet type for scalar Ruby object, Arrays and Hashes.
19
+ # This inference result does not contain instance specific information; e.g. Array[Integer] where the integer
20
+ # range is the generic default. Just `infer` it also combines types into a common type.
21
+ #
22
+ # The `infer_set(o)` method works like `infer` but preserves all type information. It does not do any
23
+ # reduction into common types or ranges. This method of inference is best suited for answering questions
24
+ # about an object being an instance of a type. It correctly answers: `[1,a].infer_set() =~ Array[Integer, String]`
25
+ #
26
+ # The `generalize!(t)` method modifies an instance specific inference result to a generic. The method mutates
27
+ # the given argument. Basically, this removes string instances from String, and range from Integer and Float.
13
28
  #
14
29
  # Assignability
15
30
  # -------------
@@ -35,6 +50,9 @@
35
50
  # instance, such as if it may be nil, be empty, contain a certain count etc. Or put differently, the puppet types are not
36
51
  # singletons.
37
52
  #
53
+ # All types support `copy` which should be used when assigning a type where it is unknown if it is bound or not
54
+ # to a parent type. A check can be made with `t.eContainer().nil?`
55
+ #
38
56
  # Equality and Hash
39
57
  # -----------------
40
58
  # Type instances are equal in terms of Ruby eql? and `==` if they describe the same type, but they are not `equal?` if they are not
@@ -45,7 +63,7 @@
45
63
  # In general, the type calculator should be used to answer questions if a type is a subtype of another (using {#assignable?}, or
46
64
  # {#instance?} if the question is if a given object is an instance of a given type (or is a subtype thereof).
47
65
  # Many of the types also have a Ruby subtype relationship; e.g. PHashType and PArrayType are both subtypes of PCollectionType, and
48
- # PIntegerType, PFloatType, PStringType,... are subtypes of PLiteralType. Even if it is possible to answer certain questions about
66
+ # PIntegerType, PFloatType, PStringType,... are subtypes of PScalarType. Even if it is possible to answer certain questions about
49
67
  # type by looking at the Ruby class of the types this is considered an implementation detail, and such checks should in general
50
68
  # be performed by the type_calculator which implements the type system semantics.
51
69
  #
@@ -64,18 +82,73 @@
64
82
  # @see Puppet::Pops::Types::TypeParser TypeParser how to construct a type instance from a String
65
83
  # @see Puppet::Pops::Types Types for details about the type model
66
84
  #
85
+ # Using the Type Calculator
86
+ # -----
87
+ # The type calculator can be directly used via its class methods. If doing time critical work and doing many
88
+ # calls to the type calculator, it is more performant to create an instance and invoke the corresponding
89
+ # instance methods. Note that inference is an expensive operation, rather than infering the same thing
90
+ # several times, it is in general better to infer once and then copy the result if mutation to a more generic form is
91
+ # required.
92
+ #
67
93
  # @api public
68
94
  #
69
95
  class Puppet::Pops::Types::TypeCalculator
70
96
 
71
97
  Types = Puppet::Pops::Types
98
+ TheInfinity = 1.0 / 0.0 # because the Infinity symbol is not defined
99
+
100
+ # @api public
101
+ def self.assignable?(t1, t2)
102
+ singleton.assignable?(t1,t2)
103
+ end
104
+
105
+ # @api public
106
+ def self.string(t)
107
+ singleton.string(t)
108
+ end
109
+
110
+ # @api public
111
+ def self.infer(o)
112
+ singleton.infer(o)
113
+ end
114
+
115
+ # @api public
116
+ def self.generalize!(o)
117
+ singleton.generalize!(o)
118
+ end
119
+
120
+ # @api public
121
+ def self.infer_set(o)
122
+ singleton.infer_set(o)
123
+ end
124
+
125
+ # @api public
126
+ def self.debug_string(t)
127
+ singleton.debug_string(t)
128
+ end
129
+
130
+ # @api public
131
+ def self.enumerable(t)
132
+ singleton.enumerable(t)
133
+ end
134
+
135
+ # @api private
136
+ def self.singleton()
137
+ @tc_instance ||= new
138
+ end
72
139
 
73
140
  # @api public
74
141
  #
75
142
  def initialize
76
143
  @@assignable_visitor ||= Puppet::Pops::Visitor.new(nil,"assignable",1,1)
77
144
  @@infer_visitor ||= Puppet::Pops::Visitor.new(nil,"infer",0,0)
145
+ @@infer_set_visitor ||= Puppet::Pops::Visitor.new(nil,"infer_set",0,0)
146
+ @@instance_of_visitor ||= Puppet::Pops::Visitor.new(nil,"instance_of",1,1)
78
147
  @@string_visitor ||= Puppet::Pops::Visitor.new(nil,"string",0,0)
148
+ @@inspect_visitor ||= Puppet::Pops::Visitor.new(nil,"debug_string",0,0)
149
+ @@enumerable_visitor ||= Puppet::Pops::Visitor.new(nil,"enumerable",0,0)
150
+ @@extract_visitor ||= Puppet::Pops::Visitor.new(nil,"extract",0,0)
151
+ @@generalize_visitor ||= Puppet::Pops::Visitor.new(nil,"generalize",0,0)
79
152
 
80
153
  da = Types::PArrayType.new()
81
154
  da.element_type = Types::PDataType.new()
@@ -83,13 +156,41 @@ class Puppet::Pops::Types::TypeCalculator
83
156
 
84
157
  h = Types::PHashType.new()
85
158
  h.element_type = Types::PDataType.new()
86
- h.key_type = Types::PLiteralType.new()
159
+ h.key_type = Types::PScalarType.new()
87
160
  @data_hash = h
88
161
 
89
162
  @data_t = Types::PDataType.new()
90
- @literal_t = Types::PLiteralType.new()
163
+ @scalar_t = Types::PScalarType.new()
91
164
  @numeric_t = Types::PNumericType.new()
92
165
  @t = Types::PObjectType.new()
166
+
167
+ # Data accepts a Tuple that has 0-infinity Data compatible entries (e.g. a Tuple equivalent to Array).
168
+ data_tuple = Types::PTupleType.new()
169
+ data_tuple.addTypes(Types::PDataType.new())
170
+ data_tuple.size_type = Types::PIntegerType.new()
171
+ data_tuple.size_type.from = 0
172
+ data_tuple.size_type.to = nil # infinity
173
+ @data_tuple_t = data_tuple
174
+
175
+ # Variant type compatible with Data
176
+ data_variant = Types::PVariantType.new()
177
+ data_variant.addTypes(@data_hash.copy)
178
+ data_variant.addTypes(@data_array.copy)
179
+ data_variant.addTypes(Types::PScalarType.new)
180
+ data_variant.addTypes(Types::PNilType.new)
181
+ data_variant.addTypes(@data_tuple_t.copy)
182
+ @data_variant_t = data_variant
183
+
184
+ collection_default_size = Types::PIntegerType.new()
185
+ collection_default_size.from = 0
186
+ collection_default_size.to = nil # infinity
187
+ @collection_default_size_t = collection_default_size
188
+
189
+ non_empty_string = Types::PStringType.new
190
+ non_empty_string.size_type = Types::PIntegerType.new()
191
+ non_empty_string.size_type.from = 1
192
+ non_empty_string.size_type.to = nil # infinity
193
+ @non_empty_string_t = non_empty_string
93
194
  end
94
195
 
95
196
  # Convenience method to get a data type for comparisons
@@ -99,6 +200,17 @@ class Puppet::Pops::Types::TypeCalculator
99
200
  @data_t
100
201
  end
101
202
 
203
+ # Convenience method to get a variant compatible with the Data type.
204
+ # @api private the returned value may not be contained in another element
205
+ #
206
+ def data_variant
207
+ @data_variant_t
208
+ end
209
+
210
+ def self.data_variant
211
+ singleton.data_variant
212
+ end
213
+
102
214
  # Answers the question 'is it possible to inject an instance of the given class'
103
215
  # A class is injectable if it has a special *assisted inject* class method called `inject` taking
104
216
  # an injector and a scope as argument, or if it has a zero args `initialize` method.
@@ -126,10 +238,8 @@ class Puppet::Pops::Types::TypeCalculator
126
238
  # @api public
127
239
  #
128
240
  def assignable?(t, t2)
129
- # nil is assignable to anything
130
- if is_pnil?(t2)
131
- return true
132
- end
241
+ # nil is assignable to anything except to required types
242
+ return true if is_pnil?(t2)
133
243
 
134
244
  if t.is_a?(Class)
135
245
  t = type(t)
@@ -139,11 +249,25 @@ class Puppet::Pops::Types::TypeCalculator
139
249
  t2 = type(t2)
140
250
  end
141
251
 
142
- @@assignable_visitor.visit_this(self, t, t2)
252
+ @@assignable_visitor.visit_this_1(self, t, t2)
143
253
  end
144
254
 
255
+ # Returns an enumerable if the t represents something that can be iterated
256
+ def enumerable(t)
257
+ @@enumerable_visitor.visit_this_0(self, t)
258
+ end
259
+
260
+ # Answers if the two given types describe the same type
261
+ def equals(left, right)
262
+ return false unless left.is_a?(Types::PAbstractType) && right.is_a?(Types::PAbstractType)
263
+ # Types compare per class only - an extra test must be made if the are mutually assignable
264
+ # to find all types that represent the same type of instance
265
+ #
266
+ left == right || (assignable?(right, left) && assignable?(left, right))
267
+ end
268
+
145
269
  # Answers 'what is the Puppet Type corresponding to the given Ruby class'
146
- # @param c [Class] the class for which a puppet type is wanted
270
+ # @param c [Class] the class for which a puppet type is wanted
147
271
  # @api public
148
272
  #
149
273
  def type(c)
@@ -160,7 +284,7 @@ class Puppet::Pops::Types::TypeCalculator
160
284
  when c == String
161
285
  type = Types::PStringType.new()
162
286
  when c == Regexp
163
- type = Types::PPatternType.new()
287
+ type = Types::PRegexpType.new()
164
288
  when c == NilClass
165
289
  type = Types::PNilType.new()
166
290
  when c == FalseClass, c == TrueClass
@@ -172,9 +296,9 @@ class Puppet::Pops::Types::TypeCalculator
172
296
  type = Types::PArrayType.new()
173
297
  type.element_type = Types::PDataType.new()
174
298
  when c == Hash
175
- # Assume hash with literal keys and data values
299
+ # Assume hash with scalar keys and data values
176
300
  type = Types::PHashType.new()
177
- type.key_type = Types::PLiteralType.new()
301
+ type.key_type = Types::PScalarType.new()
178
302
  type.element_type = Types::PDataType.new()
179
303
  else
180
304
  type = Types::PRubyType.new()
@@ -183,25 +307,149 @@ class Puppet::Pops::Types::TypeCalculator
183
307
  type
184
308
  end
185
309
 
186
- # Answers 'what is the Puppet Type of o'
310
+ # Generalizes value specific types. The given type is mutated and returned.
311
+ # @api public
312
+ def generalize!(o)
313
+ @@generalize_visitor.visit_this_0(self, o)
314
+ o.eAllContents.each { |x| @@generalize_visitor.visit_this_0(self, x) }
315
+ o
316
+ end
317
+
318
+ def generalize_Object(o)
319
+ # do nothing, there is nothing to change for most types
320
+ end
321
+
322
+ def generalize_PStringType(o)
323
+ o.values = []
324
+ o.size_type = nil
325
+ []
326
+ end
327
+
328
+ def generalize_PCollectionType(o)
329
+ # erase the size constraint from Array and Hash (if one exists, it is transformed to -Infinity - + Infinity, which is
330
+ # not desirable.
331
+ o.size_type = nil
332
+ end
333
+
334
+ def generalize_PFloatType(o)
335
+ o.to = nil
336
+ o.from = nil
337
+ end
338
+
339
+ def generalize_PIntegerType(o)
340
+ o.to = nil
341
+ o.from = nil
342
+ end
343
+
344
+ # Answers 'what is the single common Puppet Type describing o', or if o is an Array or Hash, what is the
345
+ # single common type of the elements (or keys and elements for a Hash).
187
346
  # @api public
188
347
  #
189
348
  def infer(o)
190
- @@infer_visitor.visit_this(self, o)
349
+ @@infer_visitor.visit_this_0(self, o)
350
+ end
351
+
352
+ def infer_generic(o)
353
+ result = generalize!(infer(o))
354
+ result
355
+ end
356
+
357
+ # Answers 'what is the set of Puppet Types of o'
358
+ # @api public
359
+ #
360
+ def infer_set(o)
361
+ @@infer_set_visitor.visit_this_0(self, o)
362
+ end
363
+
364
+ def instance_of(t, o)
365
+ # return true if o.nil? && !t.is_a?(Types::PRequiredType)
366
+ @@instance_of_visitor.visit_this_1(self, t, o)
367
+ end
368
+
369
+ def instance_of_Object(t, o)
370
+ # Undef is Undef and Object, but nothing else when checking instance?
371
+ return false if (o.nil? || o == :undef) && t.class != Types::PObjectType
372
+ assignable?(t, infer(o))
373
+ end
374
+
375
+ def instance_of_PArrayType(t, o)
376
+ return false unless o.is_a?(Array)
377
+ return false unless o.all? {|element| instance_of(t.element_type, element) }
378
+ size_t = t.size_type || @collection_default_size_t
379
+ size_t2 = size_as_type(o)
380
+ assignable?(size_t, size_t2)
381
+ end
382
+
383
+ def instance_of_PTupleType(t, o)
384
+ return false unless o.is_a?(Array)
385
+ # compute the tuple's min/max size, and check if that size matches
386
+ from, to = size_range(t.size_type)
387
+ size_t = Types::PIntegerType.new()
388
+ size_t.from = t.types.size - 1 + from
389
+ size_t.to = t.types.size - 1 + to
390
+ # compute the array's size as type
391
+ size_t2 = size_as_type(o)
392
+ return false unless assignable?(size_t, size_t2)
393
+ o.each_with_index do |element, index|
394
+ return false unless instance_of(t.types[index] || t.types[-1], element)
395
+ end
396
+ true
397
+ end
398
+
399
+ def instance_of_PStructType(t, o)
400
+ return false unless o.is_a?(Hash)
401
+ h = t.hashed_elements
402
+ # all keys must be present and have a value (even if nil/undef)
403
+ (o.keys - h.keys).empty? && h.all? { |k,v| instance_of(v, o[k]) }
404
+ end
405
+
406
+ def instance_of_PHashType(t, o)
407
+ return false unless o.is_a?(Hash)
408
+ key_t = t.key_type
409
+ element_t = t.element_type
410
+ return false unless o.keys.all? {|key| instance_of(key_t, key) } && o.values.all? {|value| instance_of(element_t, value) }
411
+ size_t = t.size_type || @collection_default_size_t
412
+ size_t2 = size_as_type(o)
413
+ assignable?(size_t, size_t2)
414
+ end
415
+
416
+ def instance_of_PDataType(t, o)
417
+ instance_of(@data_variant_t, o)
418
+ end
419
+
420
+ def instance_of_PNilType(t, o)
421
+ return o.nil? || o == :undef
422
+ end
423
+
424
+ def instance_of_POptionalType(t, o)
425
+ return true if (o.nil? || o == :undef)
426
+ instance_of(t.optional_type, o)
427
+ end
428
+
429
+ def instance_of_PVariantType(t, o)
430
+ # instance of variant if o is instance? of any of variant's types
431
+ t.types.any? { |option_t| instance_of(option_t, o) }
432
+ end
433
+
434
+ # Answers 'is o an instance of type t'
435
+ # @api public
436
+ #
437
+ def self.instance?(t, o)
438
+ singleton.instance_of(t,o)
191
439
  end
192
440
 
193
441
  # Answers 'is o an instance of type t'
194
442
  # @api public
195
443
  #
196
444
  def instance?(t, o)
197
- assignable?(t, infer(o))
445
+ instance_of(t,o)
198
446
  end
199
447
 
200
448
  # Answers if t is a puppet type
201
449
  # @api public
202
450
  #
203
451
  def is_ptype?(t)
204
- return t.is_a?(Types::PObjectType)
452
+ return t.is_a?(Types::PAbstractType)
205
453
  end
206
454
 
207
455
  # Answers if t represents the puppet type PNilType
@@ -212,6 +460,9 @@ class Puppet::Pops::Types::TypeCalculator
212
460
  end
213
461
 
214
462
  # Answers, 'What is the common type of t1 and t2?'
463
+ #
464
+ # TODO: The current implementation should be optimized for performance
465
+ #
215
466
  # @api public
216
467
  #
217
468
  def common_type(t1, t2)
@@ -246,19 +497,97 @@ class Puppet::Pops::Types::TypeCalculator
246
497
  return type
247
498
  end
248
499
 
500
+ # when both are host-classes, reduce to PHostClass[] (since one was not assignable to the other)
501
+ if t1.is_a?(Types::PHostClassType) && t2.is_a?(Types::PHostClassType)
502
+ return Types::PHostClassType.new()
503
+ end
504
+
505
+ # when both are resources, reduce to Resource[T] or Resource[] (since one was not assignable to the other)
506
+ if t1.is_a?(Types::PResourceType) && t2.is_a?(Types::PResourceType)
507
+ result = Types::PResourceType.new()
508
+ # only Resource[] unless the type name is the same
509
+ if t1.type_name == t2.type_name then result.type_name = t1.type_name end
510
+ # the cross assignability test above has already determined that they do not have the same type and title
511
+ return result
512
+ end
513
+
514
+ # Integers have range, expand the range to the common range
515
+ if t1.is_a?(Types::PIntegerType) && t2.is_a?(Types::PIntegerType)
516
+ t1range = from_to_ordered(t1.from, t1.to)
517
+ t2range = from_to_ordered(t2.from, t2.to)
518
+ t = Types::PIntegerType.new()
519
+ from = [t1range[0], t2range[0]].min
520
+ to = [t1range[1], t2range[1]].max
521
+ t.from = from unless from == TheInfinity
522
+ t.to = to unless to == TheInfinity
523
+ return t
524
+ end
525
+
526
+ # Floats have range, expand the range to the common range
527
+ if t1.is_a?(Types::PFloatType) && t2.is_a?(Types::PFloatType)
528
+ t1range = from_to_ordered(t1.from, t1.to)
529
+ t2range = from_to_ordered(t2.from, t2.to)
530
+ t = Types::PFloatType.new()
531
+ from = [t1range[0], t2range[0]].min
532
+ to = [t1range[1], t2range[1]].max
533
+ t.from = from unless from == TheInfinity
534
+ t.to = to unless to == TheInfinity
535
+ return t
536
+ end
537
+
538
+ if t1.is_a?(Types::PStringType) && t2.is_a?(Types::PStringType)
539
+ t = Types::PStringType.new()
540
+ t.values = t1.values | t2.values
541
+ return t
542
+ end
543
+
544
+ if t1.is_a?(Types::PPatternType) && t2.is_a?(Types::PPatternType)
545
+ t = Types::PPatternType.new()
546
+ # must make copies since patterns are contained types, not data-types
547
+ t.patterns = (t1.patterns | t2.patterns).map {|p| p.copy }
548
+ return t
549
+ end
550
+
551
+ if t1.is_a?(Types::PEnumType) && t2.is_a?(Types::PEnumType)
552
+ # The common type is one that complies with either set
553
+ t = Types::PEnumType.new
554
+ t.values = t1.values | t2.values
555
+ return t
556
+ end
557
+
558
+ if t1.is_a?(Types::PVariantType) && t2.is_a?(Types::PVariantType)
559
+ # The common type is one that complies with either set
560
+ t = Types::PVariantType.new
561
+ t.types = (t1.types | t2.types).map {|opt_t| opt_t.copy }
562
+ return t
563
+ end
564
+
565
+ if t1.is_a?(Types::PRegexpType) && t2.is_a?(Types::PRegexpType)
566
+ # if they were identical, the general rule would return a parameterized regexp
567
+ # since they were not, the result is a generic regexp type
568
+ return Types::PPatternType.new()
569
+ end
570
+
249
571
  # Common abstract types, from most specific to most general
250
572
  if common_numeric?(t1, t2)
251
573
  return Types::PNumericType.new()
252
574
  end
253
575
 
254
- if common_literal?(t1, t2)
255
- return Types::PLiteralType.new()
576
+ if common_scalar?(t1, t2)
577
+ return Types::PScalarType.new()
256
578
  end
257
579
 
258
580
  if common_data?(t1,t2)
259
581
  return Types::PDataType.new()
260
582
  end
261
583
 
584
+ # Meta types Type[Integer] + Type[String] => Type[Data]
585
+ if t1.is_a?(Types::PType) && t2.is_a?(Types::PType)
586
+ type = Types::PType.new()
587
+ type.type = common_type(t1.type, t2.type)
588
+ return type
589
+ end
590
+
262
591
  if t1.is_a?(Types::PRubyType) && t2.is_a?(Types::PRubyType)
263
592
  if t1.ruby_class == t2.ruby_class
264
593
  return t1
@@ -295,11 +624,19 @@ class Puppet::Pops::Types::TypeCalculator
295
624
  end
296
625
  result
297
626
  end
627
+
298
628
  # Produces a string representing the type
299
629
  # @api public
300
630
  #
301
631
  def string(t)
302
- @@string_visitor.visit_this(self, t)
632
+ @@string_visitor.visit_this_0(self, t)
633
+ end
634
+
635
+ # Produces a debug string representing the type (possibly with more information that the regular string format)
636
+ # @api public
637
+ #
638
+ def debug_string(t)
639
+ @@inspect_visitor.visit_this_0(self, t)
303
640
  end
304
641
 
305
642
 
@@ -335,7 +672,9 @@ class Puppet::Pops::Types::TypeCalculator
335
672
  # @api private
336
673
  #
337
674
  def infer_PObjectType(o)
338
- Types::PType.new()
675
+ type = Types::PType.new()
676
+ type.type = o.copy
677
+ type
339
678
  end
340
679
 
341
680
  # The type of all types is PType
@@ -343,27 +682,40 @@ class Puppet::Pops::Types::TypeCalculator
343
682
  # @api private
344
683
  #
345
684
  def infer_PType(o)
346
- Types::PType.new()
685
+ type = Types::PType.new()
686
+ type.type = o.copy
687
+ type
347
688
  end
348
689
 
349
690
  # @api private
350
691
  def infer_String(o)
351
- Types::PStringType.new()
692
+ t = Types::PStringType.new()
693
+ t.addValues(o)
694
+ t.size_type = size_as_type(o)
695
+ t
352
696
  end
353
697
 
354
698
  # @api private
355
699
  def infer_Float(o)
356
- Types::PFloatType.new()
700
+ t = Types::PFloatType.new()
701
+ t.from = o
702
+ t.to = o
703
+ t
357
704
  end
358
705
 
359
706
  # @api private
360
707
  def infer_Integer(o)
361
- Types::PIntegerType.new()
708
+ t = Types::PIntegerType.new()
709
+ t.from = o
710
+ t.to = o
711
+ t
362
712
  end
363
713
 
364
714
  # @api private
365
715
  def infer_Regexp(o)
366
- Types::PPatternType.new()
716
+ t = Types::PRegexpType.new()
717
+ t.pattern = o.source
718
+ t
367
719
  end
368
720
 
369
721
  # @api private
@@ -371,6 +723,12 @@ class Puppet::Pops::Types::TypeCalculator
371
723
  Types::PNilType.new()
372
724
  end
373
725
 
726
+ # Inference of :undef as PNilType, all other are Ruby[Symbol]
727
+ # @api private
728
+ def infer_Symbol(o)
729
+ o == :undef ? infer_NilClass(o) : infer_Object(o)
730
+ end
731
+
374
732
  # @api private
375
733
  def infer_TrueClass(o)
376
734
  Types::PBooleanType.new()
@@ -381,14 +739,26 @@ class Puppet::Pops::Types::TypeCalculator
381
739
  Types::PBooleanType.new()
382
740
  end
383
741
 
742
+ # @api private
743
+ # A Puppet::Parser::Resource, or Puppet::Resource
744
+ #
745
+ def infer_Resource(o)
746
+ t = Types::PResourceType.new()
747
+ t.type_name = o.type.to_s
748
+ t.title = o.title
749
+ t
750
+ end
751
+
384
752
  # @api private
385
753
  def infer_Array(o)
386
754
  type = Types::PArrayType.new()
387
- type.element_type = if o.empty?
755
+ type.element_type =
756
+ if o.empty?
388
757
  Types::PNilType.new()
389
758
  else
390
759
  infer_and_reduce_type(o)
391
760
  end
761
+ type.size_type = size_as_type(o)
392
762
  type
393
763
  end
394
764
 
@@ -404,9 +774,60 @@ class Puppet::Pops::Types::TypeCalculator
404
774
  end
405
775
  type.key_type = ktype
406
776
  type.element_type = etype
777
+ type.size_type = size_as_type(o)
407
778
  type
408
779
  end
409
780
 
781
+ def size_as_type(collection)
782
+ size = collection.size
783
+ t = Types::PIntegerType.new()
784
+ t.from = size
785
+ t.to = size
786
+ t
787
+ end
788
+
789
+ # Common case for everything that intrinsically only has a single type
790
+ def infer_set_Object(o)
791
+ infer(o)
792
+ end
793
+
794
+ def infer_set_Array(o)
795
+ type = Types::PArrayType.new()
796
+ type.element_type = if o.empty?
797
+ Types::PNilType.new()
798
+ else
799
+ t = Types::PVariantType.new()
800
+ t.types = o.map() {|x| infer_set(x) }
801
+ t.types.size == 1 ? t.types[0] : t
802
+ end
803
+ type.size_type = size_as_type(o)
804
+ type
805
+ end
806
+
807
+ def infer_set_Hash(o)
808
+ type = Types::PHashType.new()
809
+ if o.empty?
810
+ ktype = Types::PNilType.new()
811
+ etype = Types::PNilType.new()
812
+ else
813
+ ktype = Types::PVariantType.new()
814
+ ktype.types = o.keys.map() {|k| infer_set(k) }
815
+ etype = Types::PVariantType.new()
816
+ etype.types = o.values.map() {|e| infer_set(e) }
817
+ end
818
+ type.key_type = unwrap_single_variant(ktype)
819
+ type.element_type = unwrap_single_variant(vtype)
820
+ type.size_type = size_as_type(o)
821
+ type
822
+ end
823
+
824
+ def unwrap_single_variant(possible_variant)
825
+ if possible_variant.is_a?(Types::PVariantType) && possible_variant.types.size == 1
826
+ possible_variant.types[0]
827
+ else
828
+ possible_variant
829
+ end
830
+ end
410
831
  # False in general type calculator
411
832
  # @api private
412
833
  def assignable_Object(t, t2)
@@ -419,8 +840,14 @@ class Puppet::Pops::Types::TypeCalculator
419
840
  end
420
841
 
421
842
  # @api private
422
- def assignable_PLiteralType(t, t2)
423
- t2.is_a?(Types::PLiteralType)
843
+ def assignable_PNilType(t, t2)
844
+ # Only undef/nil is assignable to nil type
845
+ t2.is_a?(Types::PNilType)
846
+ end
847
+
848
+ # @api private
849
+ def assignable_PScalarType(t, t2)
850
+ t2.is_a?(Types::PScalarType)
424
851
  end
425
852
 
426
853
  # @api private
@@ -430,17 +857,250 @@ class Puppet::Pops::Types::TypeCalculator
430
857
 
431
858
  # @api private
432
859
  def assignable_PIntegerType(t, t2)
433
- t2.is_a?(Types::PIntegerType)
860
+ return false unless t2.is_a?(Types::PIntegerType)
861
+ trange = from_to_ordered(t.from, t.to)
862
+ t2range = from_to_ordered(t2.from, t2.to)
863
+ # If t2 min and max are within the range of t
864
+ trange[0] <= t2range[0] && trange[1] >= t2range[1]
865
+ end
866
+
867
+ # Transform int range to a size constraint
868
+ # if range == nil the constraint is 1,1
869
+ # if range.from == nil min size = 1
870
+ # if range.to == nil max size == Infinity
871
+ #
872
+ def size_range(range)
873
+ return [1,1] if range.nil?
874
+ from = range.from
875
+ to = range.to
876
+ x = from.nil? ? 1 : from
877
+ y = to.nil? ? TheInfinity : to
878
+ if x < y
879
+ [x, y]
880
+ else
881
+ [y, x]
882
+ end
883
+ end
884
+
885
+ # @api private
886
+ def from_to_ordered(from, to)
887
+ x = (from.nil? || from == :default) ? -TheInfinity : from
888
+ y = (to.nil? || to == :default) ? TheInfinity : to
889
+ if x < y
890
+ [x, y]
891
+ else
892
+ [y, x]
893
+ end
894
+ end
895
+
896
+ # @api private
897
+ def assignable_PVariantType(t, t2)
898
+ # Data is a specific variant
899
+ t2 = @data_variant_t if t2.is_a?(Types::PDataType)
900
+ if t2.is_a?(Types::PVariantType)
901
+ # A variant is assignable if all of its options are assignable to one of this type's options
902
+ return true if t == t2
903
+ t2.types.all? do |other|
904
+ # if the other is a Variant, all if its options, but be assignable to one of this type's options
905
+ other = other.is_a?(Types::PDataType) ? @data_variant_t : other
906
+ if other.is_a?(Types::PVariantType)
907
+ assignable?(t, other)
908
+ else
909
+ t.types.any? {|option_t| assignable?(option_t, other) }
910
+ end
911
+ end
912
+ else
913
+ # A variant is assignable if t2 is assignable to any of its types
914
+ t.types.any? { |option_t| assignable?(option_t, t2) }
915
+ end
916
+ end
917
+
918
+ def assignable_PTupleType(t, t2)
919
+ return true if t == t2 || t.types.empty? && (t2.is_a?(Types::PArrayType))
920
+ t_regular = t.types[0..-2]
921
+ t_ranged = t.types[-1]
922
+ t_from, t_to = size_range(t.size_type)
923
+ t_required = t_regular.size + t_from
924
+
925
+ if t2.is_a?(Types::PTupleType)
926
+ t2_regular = t2.types[0..-2]
927
+ t2_ranged = t2.types[-1]
928
+ t2_from, t2_to = size_range(t2.size_type)
929
+ t2_required = t2_regular.size + t2_from
930
+
931
+ # tuples with fewer required entries can not be assigned
932
+ return false if t_required > t2_required
933
+ # tuples with more optionally available entries can not be assigned
934
+ return false if t_regular.size + t_to < t2_regular.size + t2_to
935
+
936
+ t_required.times do |index|
937
+ t_entry = tuple_entry_at(t, t_from, t_to, index)
938
+ t2_entry = tuple_entry_at(t2, t2_from, t2_to, index)
939
+ return false if t2_entry.nil? || !assignable?(t_entry, t2_entry)
940
+ end
941
+ # Handle remainder in t2's required
942
+ (t2_required - t_required).times do |index|
943
+ t_entry = tuple_entry_at(t, t_from, t_to, t_required + index)
944
+ t2_entry = tuple_entry_at(t2, t2_from, t2_to, t_required + index)
945
+ return false if t2_entry.nil? || !assignable?(t_entry, t2_entry)
946
+ end
947
+ # Now only a trailing optional type remains - the last type must always be compatible
948
+ # irrespective of optionality and count
949
+ #
950
+ return assignable?(t_ranged, t2_ranged)
951
+
952
+ elsif t2.is_a?(Types::PArrayType)
953
+ t2_entry = t2.element_type
954
+
955
+ # Array of anything can not be assigned (unless tuple is tuple of anything) - this case
956
+ # was handled at the top of this method.
957
+ #
958
+ return false if t2_entry.nil?
959
+
960
+ # array type may be size constrained
961
+ size_t = t2.size_type || @collection_default_size_t
962
+ min, max = size_t.range
963
+ # Array with fewer min entries can not be assigned
964
+ return false if t_required > min
965
+ # Array with more optionally available entries can not be assigned
966
+ return false if t_regular.size + t_to < max
967
+ # each tuple type must be assignable to the element type
968
+ t_required.times do |index|
969
+ t_entry = tuple_entry_at(t, t_from, t_to, index)
970
+ return false unless assignable?(t_entry, t2_entry)
971
+ end
972
+ # ... and so must the last, possibly optional (ranged) type
973
+ return assignable?(t_ranged, t2_entry)
974
+ end
975
+ end
976
+
977
+ # Produces the tuple entry at the given index given a tuple type, its from/to constraints on the last
978
+ # type, and an index.
979
+ # Produces nil if the index is out of bounds
980
+ # from must be less than to, and from may not be less than 0
981
+ #
982
+ # @api private
983
+ #
984
+ def tuple_entry_at(tuple_t, from, to, index)
985
+ regular = (tuple_t.types.size - 1)
986
+ if index < regular
987
+ tuple_t.types[index]
988
+ elsif index < regular + to
989
+ # in the varargs part
990
+ tuple_t.types[-1]
991
+ else
992
+ nil
993
+ end
994
+ end
995
+
996
+ # @api private
997
+ #
998
+ def assignable_PStructType(t, t2)
999
+ return true if t == t2 || t.elements.empty? && (t2.is_a?(Types::PHashType))
1000
+ h = t.hashed_elements
1001
+ if t2.is_a?(Types::PStructType)
1002
+ h2 = t2.hashed_elements
1003
+ h.size == h2.size && h.all? {|k, v| assignable?(v, h2[k]) }
1004
+ elsif t2.is_a?(Types::PHashType)
1005
+ size_t2 = t2.size_type || @collection_default_size_t
1006
+ size_t = Types::PIntegerType.new
1007
+ size_t.from = size_t.to = h.size
1008
+ # compatible size
1009
+ # hash key type must be string of min 1 size
1010
+ # hash value t must be assignable to each key
1011
+ element_type = t2.element_type
1012
+ assignable?(size_t, size_t2) &&
1013
+ assignable?(@non_empty_string_t, t2.key_type) &&
1014
+ h.all? {|k,v| assignable?(v, element_type) }
1015
+ else
1016
+ false
1017
+ end
1018
+ end
1019
+
1020
+ # @api private
1021
+ def assignable_POptionalType(t, t2)
1022
+ return true if t2.is_a?(Types::PNilType)
1023
+ if t2.is_a?(Types::POptionalType)
1024
+ assignable?(t.optional_type, t2.optional_type)
1025
+ else
1026
+ assignable?(t.optional_type, t2)
1027
+ end
1028
+ end
1029
+
1030
+ # @api private
1031
+ def assignable_PEnumType(t, t2)
1032
+ return true if t == t2 || (t.values.empty? && (t2.is_a?(Types::PStringType) || t2.is_a?(Types::PEnumType)))
1033
+ if t2.is_a?(Types::PStringType)
1034
+ # if the set of strings are all found in the set of enums
1035
+ t2.values.all? { |s| t.values.any? { |e| e == s }}
1036
+ else
1037
+ false
1038
+ end
434
1039
  end
435
1040
 
436
1041
  # @api private
437
1042
  def assignable_PStringType(t, t2)
438
- t2.is_a?(Types::PStringType)
1043
+ if t.values.empty?
1044
+ # A general string is assignable by any other string or pattern restricted string
1045
+ # if the string has a size constraint it does not match since there is no reasonable way
1046
+ # to compute the min/max length a pattern will match. For enum, it is possible to test that
1047
+ # each enumerator value is within range
1048
+ size_t = t.size_type || @collection_default_size_t
1049
+ case t2
1050
+ when Types::PStringType
1051
+ # true if size compliant
1052
+ size_t2 = t2.size_type || @collection_default_size_t
1053
+ assignable?(size_t, size_t2)
1054
+
1055
+ when Types::PPatternType
1056
+ # true if size constraint is at least 0 to +Infinity (which is the same as the default)
1057
+ assignable?(size_t, @collection_default_size_t)
1058
+
1059
+ when Types::PEnumType
1060
+ if t2.values
1061
+ # true if all enum values are within range
1062
+ min, max = t2.values.map(&:size).minmax
1063
+ trange = from_to_ordered(size_t.from, size_t.to)
1064
+ t2range = [min, max]
1065
+ # If t2 min and max are within the range of t
1066
+ trange[0] <= t2range[0] && trange[1] >= t2range[1]
1067
+ else
1068
+ # no string can match this enum anyway since it does not accept anything
1069
+ false
1070
+ end
1071
+ end
1072
+ elsif t2.is_a?(Types::PStringType)
1073
+ # A specific string acts as a set of strings - must have exactly the same strings
1074
+ # In this case, size does not matter since the definition is very precise anyway
1075
+ Set.new(t.values) == Set.new(t2.values)
1076
+ else
1077
+ # All others are false, since no other type describes the same set of specific strings
1078
+ false
1079
+ end
1080
+ end
1081
+
1082
+ # @api private
1083
+ def assignable_PPatternType(t, t2)
1084
+ return true if t == t2
1085
+ return false unless t2.is_a?(Types::PStringType) || t2.is_a?(Types::PEnumType)
1086
+
1087
+ if t2.values.empty?
1088
+ # Strings / Enums (unknown which ones) cannot all match a pattern, but if there is no pattern it is ok
1089
+ # (There should really always be a pattern, but better safe than sorry).
1090
+ return t.patterns.empty? ? true : false
1091
+ end
1092
+ # all strings in String/Enum type must match one of the patterns in Pattern type
1093
+ regexps = t.patterns.map {|p| p.regexp }
1094
+ t2.values.all? { |v| regexps.any? {|re| re.match(v) } }
439
1095
  end
440
1096
 
441
1097
  # @api private
442
1098
  def assignable_PFloatType(t, t2)
443
- t2.is_a?(Types::PFloatType)
1099
+ return false unless t2.is_a?(Types::PFloatType)
1100
+ trange = from_to_ordered(t.from, t.to)
1101
+ t2range = from_to_ordered(t2.from, t2.to)
1102
+ # If t2 min and max are within the range of t
1103
+ trange[0] <= t2range[0] && trange[1] >= t2range[1]
444
1104
  end
445
1105
 
446
1106
  # @api private
@@ -449,39 +1109,142 @@ class Puppet::Pops::Types::TypeCalculator
449
1109
  end
450
1110
 
451
1111
  # @api private
452
- def assignable_PPatternType(t, t2)
453
- t2.is_a?(Types::PPatternType)
1112
+ def assignable_PRegexpType(t, t2)
1113
+ t2.is_a?(Types::PRegexpType) && (t.pattern.nil? || t.pattern == t2.pattern)
454
1114
  end
455
1115
 
456
1116
  # @api private
457
1117
  def assignable_PCollectionType(t, t2)
458
- t2.is_a?(Types::PCollectionType)
1118
+ size_t = t.size_type || @collection_default_size_t
1119
+ case t2
1120
+ when Types::PCollectionType
1121
+ size_t2 = t2.size_type || @collection_default_size_t
1122
+ assignable?(size_t, size_t2)
1123
+ when Types::PTupleType
1124
+ # compute the tuple's min/max size, and check if that size matches
1125
+ from, to = size_range(t2.size_type)
1126
+ t2s = Types::PIntegerType.new()
1127
+ t2s.from = t2.types.size - 1 + from
1128
+ t2s.to = t2.types.size - 1 + to
1129
+ assignable?(size_t, t2s)
1130
+ when Types::PStructType
1131
+ from = to = t2.elements.size
1132
+ t2s = Types::PIntegerType.new()
1133
+ t2s.from = from
1134
+ t2s.to = to
1135
+ assignable?(size_t, t2s)
1136
+ else
1137
+ false
1138
+ end
1139
+ end
1140
+
1141
+ # @api private
1142
+ def assignable_PType(t, t2)
1143
+ return false unless t2.is_a?(Types::PType)
1144
+ return true if t.type.nil? # wide enough to handle all types
1145
+ return false if t2.type.nil? # wider than t
1146
+ assignable?(t.type, t2.type)
459
1147
  end
460
1148
 
461
- # Array is assignable if t2 is an Array and t2's element type is assignable
1149
+ # Array is assignable if t2 is an Array and t2's element type is assignable, or if t2 is a Tuple
1150
+ # where
462
1151
  # @api private
463
1152
  def assignable_PArrayType(t, t2)
464
- return false unless t2.is_a?(Types::PArrayType)
465
- assignable?(t.element_type, t2.element_type)
1153
+ if t2.is_a?(Types::PArrayType)
1154
+ return false unless assignable?(t.element_type, t2.element_type)
1155
+ assignable_PCollectionType(t, t2)
1156
+
1157
+ elsif t2.is_a?(Types::PTupleType)
1158
+ return false unless t2.types.all? {|t2_element| assignable?(t.element_type, t2_element) }
1159
+ t2_regular = t2.types[0..-2]
1160
+ t2_ranged = t2.types[-1]
1161
+ t2_from, t2_to = size_range(t2.size_type)
1162
+ t2_required = t2_regular.size + t2_from
1163
+
1164
+ t_entry = t.element_type
1165
+
1166
+ # Tuple of anything can not be assigned (unless array is tuple of anything) - this case
1167
+ # was handled at the top of this method.
1168
+ #
1169
+ return false if t_entry.nil?
1170
+
1171
+ # array type may be size constrained
1172
+ size_t = t.size_type || @collection_default_size_t
1173
+ min, max = size_t.range
1174
+ # Tuple with fewer min entries can not be assigned
1175
+ return false if t2_required < min
1176
+ # Tuple with more optionally available entries can not be assigned
1177
+ return false if t2_regular.size + t2_to > max
1178
+ # each tuple type must be assignable to the element type
1179
+ t2_required.times do |index|
1180
+ t2_entry = tuple_entry_at(t2, t2_from, t2_to, index)
1181
+ return false unless assignable?(t_entry, t2_entry)
1182
+ end
1183
+ # ... and so must the last, possibly optional (ranged) type
1184
+ return assignable?(t_entry, t2_ranged)
1185
+ else
1186
+ false
1187
+ end
466
1188
  end
467
1189
 
468
1190
  # Hash is assignable if t2 is a Hash and t2's key and element types are assignable
469
1191
  # @api private
470
1192
  def assignable_PHashType(t, t2)
471
- return false unless t2.is_a?(Types::PHashType)
472
- assignable?(t.key_type, t2.key_type) && assignable?(t.element_type, t2.element_type)
1193
+ case t2
1194
+ when Types::PHashType
1195
+ return false unless assignable?(t.key_type, t2.key_type) && assignable?(t.element_type, t2.element_type)
1196
+ assignable_PCollectionType(t, t2)
1197
+ when Types::PStructType
1198
+ # hash must accept String as key type
1199
+ # hash must accept all value types
1200
+ # hash must accept the size of the struct
1201
+ size_t = t.size_type || @collection_default_size_t
1202
+ min, max = size_t.range
1203
+ struct_size = t2.elements.size
1204
+ element_type = t.element_type
1205
+ ( struct_size >= min && struct_size <= max &&
1206
+ assignable?(t.key_type, @non_emptry_string_t) &&
1207
+ t2.hashed_elements.all? {|k,v| assignable?(element_type, v) })
1208
+ else
1209
+ false
1210
+ end
473
1211
  end
474
1212
 
475
- # Data is assignable by other Data and by Array[Data] and Hash[Literal, Data]
1213
+ # @api private
1214
+ def assignable_PCatalogEntryType(t1, t2)
1215
+ t2.is_a?(Types::PCatalogEntryType)
1216
+ end
1217
+
1218
+ # @api private
1219
+ def assignable_PHostClassType(t1, t2)
1220
+ return false unless t2.is_a?(Types::PHostClassType)
1221
+ # Class = Class[name}, Class[name] != Class
1222
+ return true if t1.class_name.nil?
1223
+ # Class[name] = Class[name]
1224
+ return t1.class_name == t2.class_name
1225
+ end
1226
+
1227
+ # @api private
1228
+ def assignable_PResourceType(t1, t2)
1229
+ return false unless t2.is_a?(Types::PResourceType)
1230
+ return true if t1.type_name.nil?
1231
+ return false if t1.type_name != t2.type_name
1232
+ return true if t1.title.nil?
1233
+ return t1.title == t2.title
1234
+ end
1235
+
1236
+ # Data is assignable by other Data and by Array[Data] and Hash[Scalar, Data]
476
1237
  # @api private
477
1238
  def assignable_PDataType(t, t2)
478
- t2.is_a?(Types::PDataType) || assignable?(@data_array, t2) || assignable?(@data_hash, t2)
1239
+ t2.is_a?(Types::PDataType) || assignable?(@data_variant_t, t2)
479
1240
  end
480
1241
 
481
1242
  # Assignable if t2's ruby class is same or subclass of t1's ruby class
482
1243
  # @api private
483
1244
  def assignable_PRubyType(t1, t2)
484
1245
  return false unless t2.is_a?(Types::PRubyType)
1246
+ return true if t1.ruby_class.nil? # t1 is wider
1247
+ return false if t2.ruby_class.nil? # t1 not nil, so t2 can not be wider
485
1248
  c1 = class_from_string(t1.ruby_class)
486
1249
  c2 = class_from_string(t2.ruby_class)
487
1250
  return false unless c1.is_a?(Class) && c2.is_a?(Class)
@@ -489,16 +1252,36 @@ class Puppet::Pops::Types::TypeCalculator
489
1252
  end
490
1253
 
491
1254
  # @api private
492
- def string_PType(t) ; "Type" ; end
1255
+ def debug_string_Object(t)
1256
+ string(t)
1257
+ end
1258
+
1259
+ # @api private
1260
+ def string_PType(t)
1261
+ if t.type.nil?
1262
+ "Type"
1263
+ else
1264
+ "Type[#{string(t.type)}]"
1265
+ end
1266
+ end
1267
+
1268
+ # @api private
1269
+ def string_NilClass(t) ; '?' ; end
1270
+
1271
+ # @api private
1272
+ def string_String(t) ; t ; end
493
1273
 
494
1274
  # @api private
495
1275
  def string_PObjectType(t) ; "Object" ; end
496
1276
 
1277
+ # @api private
1278
+ def string_PNilType(t) ; 'Undef' ; end
1279
+
497
1280
  # @api private
498
1281
  def string_PBooleanType(t) ; "Boolean" ; end
499
1282
 
500
1283
  # @api private
501
- def string_PLiteralType(t) ; "Literal" ; end
1284
+ def string_PScalarType(t) ; "Scalar" ; end
502
1285
 
503
1286
  # @api private
504
1287
  def string_PDataType(t) ; "Data" ; end
@@ -507,35 +1290,177 @@ class Puppet::Pops::Types::TypeCalculator
507
1290
  def string_PNumericType(t) ; "Numeric" ; end
508
1291
 
509
1292
  # @api private
510
- def string_PIntegerType(t) ; "Integer" ; end
1293
+ def string_PIntegerType(t)
1294
+ range = range_array_part(t)
1295
+ unless range.empty?
1296
+ "Integer[#{range.join(', ')}]"
1297
+ else
1298
+ "Integer"
1299
+ end
1300
+ end
511
1301
 
1302
+ # Produces a string from an Integer range type that is used inside other type strings
512
1303
  # @api private
513
- def string_PFloatType(t) ; "Float" ; end
1304
+ def range_array_part(t)
1305
+ return [] if t.nil? || (t.from.nil? && t.to.nil?)
1306
+ [t.from.nil? ? 'default' : t.from , t.to.nil? ? 'default' : t.to ]
1307
+ end
514
1308
 
515
1309
  # @api private
516
- def string_PPatternType(t) ; "Pattern" ; end
1310
+ def string_PFloatType(t)
1311
+ range = range_array_part(t)
1312
+ unless range.empty?
1313
+ "Float[#{range.join(', ')}]"
1314
+ else
1315
+ "Float"
1316
+ end
1317
+ end
517
1318
 
518
1319
  # @api private
519
- def string_PStringType(t) ; "String" ; end
1320
+ def string_PRegexpType(t)
1321
+ t.pattern.nil? ? "Regexp" : "Regexp[#{t.regexp.inspect}]"
1322
+ end
1323
+
1324
+ # @api private
1325
+ def string_PStringType(t)
1326
+ # skip values in regular output - see debug_string
1327
+ range = range_array_part(t.size_type)
1328
+ unless range.empty?
1329
+ "String[#{range.join(', ')}]"
1330
+ else
1331
+ "String"
1332
+ end
1333
+ end
520
1334
 
521
1335
  # @api private
522
- def string_PRubyType(t) ; "Ruby[#{t.ruby_class}]" ; end
1336
+ def debug_string_PStringType(t)
1337
+ range = range_array_part(t.size_type)
1338
+ range_part = range.empty? ? '' : '[' << range.join(' ,') << '], '
1339
+ "String[" << range_part << (t.values.map {|s| "'#{s}'" }).join(', ') << ']'
1340
+ end
1341
+
1342
+ # @api private
1343
+ def string_PEnumType(t)
1344
+ return "Enum" if t.values.empty?
1345
+ "Enum[" << t.values.map {|s| "'#{s}'" }.join(', ') << ']'
1346
+ end
1347
+
1348
+ # @api private
1349
+ def string_PVariantType(t)
1350
+ return "Variant" if t.types.empty?
1351
+ "Variant[" << t.types.map {|t2| string(t2) }.join(', ') << ']'
1352
+ end
1353
+
1354
+ # @api private
1355
+ def string_PTupleType(t)
1356
+ range = range_array_part(t.size_type)
1357
+ return "Tuple" if t.types.empty?
1358
+ s = "Tuple[" << t.types.map {|t2| string(t2) }.join(', ')
1359
+ unless range.empty?
1360
+ s << ", " << range.join(', ')
1361
+ end
1362
+ s << "]"
1363
+ s
1364
+ end
1365
+
1366
+ # @api private
1367
+ def string_PStructType(t)
1368
+ return "Struct" if t.elements.empty?
1369
+ "Struct[{" << t.elements.map {|element| string(element) }.join(', ') << "}]"
1370
+ end
1371
+
1372
+ def string_PStructElement(t)
1373
+ "'#{t.name}'=>#{string(t.type)}"
1374
+ end
1375
+
1376
+ # @api private
1377
+ def string_PPatternType(t)
1378
+ return "Pattern" if t.patterns.empty?
1379
+ "Pattern[" << t.patterns.map {|s| "#{s.regexp.inspect}" }.join(', ') << ']'
1380
+ end
1381
+
1382
+ # @api private
1383
+ def string_PCollectionType(t)
1384
+ range = range_array_part(t.size_type)
1385
+ unless range.empty?
1386
+ "Collection[#{range.join(', ')}]"
1387
+ else
1388
+ "Collection"
1389
+ end
1390
+ end
1391
+
1392
+ # @api private
1393
+ def string_PRubyType(t) ; "Ruby[#{string(t.ruby_class)}]" ; end
523
1394
 
524
1395
  # @api private
525
1396
  def string_PArrayType(t)
526
- "Array[#{string(t.element_type)}]"
1397
+ parts = [string(t.element_type)] + range_array_part(t.size_type)
1398
+ "Array[#{parts.join(', ')}]"
527
1399
  end
528
1400
 
529
1401
  # @api private
530
1402
  def string_PHashType(t)
531
- "Hash[#{string(t.key_type)}, #{string(t.element_type)}]"
1403
+ parts = [string(t.key_type), string(t.element_type)] + range_array_part(t.size_type)
1404
+ "Hash[#{parts.join(', ')}]"
1405
+ end
1406
+
1407
+ # @api private
1408
+ def string_PCatalogEntryType(t)
1409
+ "CatalogEntry"
1410
+ end
1411
+
1412
+ # @api private
1413
+ def string_PHostClassType(t)
1414
+ if t.class_name
1415
+ "Class[#{t.class_name}]"
1416
+ else
1417
+ "Class"
1418
+ end
1419
+ end
1420
+
1421
+ # @api private
1422
+ def string_PResourceType(t)
1423
+ if t.type_name
1424
+ if t.title
1425
+ "#{t.type_name.capitalize}['#{t.title}']"
1426
+ else
1427
+ "#{t.type_name.capitalize}"
1428
+ end
1429
+ else
1430
+ "Resource"
1431
+ end
1432
+ end
1433
+
1434
+ def string_POptionalType(t)
1435
+ if t.optional_type.nil?
1436
+ "Optional"
1437
+ else
1438
+ "Optional[#{string(t.optional_type)}]"
1439
+ end
1440
+ end
1441
+
1442
+ # Catches all non enumerable types
1443
+ # @api private
1444
+ def enumerable_Object(o)
1445
+ nil
1446
+ end
1447
+
1448
+ # @api private
1449
+ def enumerable_PIntegerType(t)
1450
+ # Not enumerable if representing an infinite range
1451
+ return nil if t.size == TheInfinity
1452
+ t
532
1453
  end
533
1454
 
534
1455
  private
535
1456
 
536
1457
  def class_from_string(str)
537
- str.split('::').inject(Object) do |memo, name_segment|
538
- memo.const_get(name_segment)
1458
+ begin
1459
+ str.split('::').inject(Object) do |memo, name_segment|
1460
+ memo.const_get(name_segment)
1461
+ end
1462
+ rescue NameError
1463
+ return nil
539
1464
  end
540
1465
  end
541
1466
 
@@ -543,8 +1468,8 @@ class Puppet::Pops::Types::TypeCalculator
543
1468
  assignable?(@data_t, t1) && assignable?(@data_t, t2)
544
1469
  end
545
1470
 
546
- def common_literal?(t1, t2)
547
- assignable?(@literal_t, t1) && assignable?(@literal_t, t2)
1471
+ def common_scalar?(t1, t2)
1472
+ assignable?(@scalar_t, t1) && assignable?(@scalar_t, t2)
548
1473
  end
549
1474
 
550
1475
  def common_numeric?(t1, t2)