puppet 4.2.3 → 4.3.0

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 (337) hide show
  1. data/Gemfile +3 -0
  2. data/README.md +1 -1
  3. data/ext/debian/puppet.init +0 -1
  4. data/ext/debian/puppet.logrotate +14 -5
  5. data/ext/osx/puppet.plist +0 -2
  6. data/ext/redhat/client.init +13 -5
  7. data/ext/redhat/logrotate +15 -3
  8. data/ext/redhat/puppet.spec.erb +5 -1
  9. data/ext/redhat/server.init +1 -1
  10. data/ext/systemd/puppet.service +1 -0
  11. data/lib/puppet.rb +12 -0
  12. data/lib/puppet/agent.rb +4 -4
  13. data/lib/puppet/agent/locker.rb +11 -2
  14. data/lib/puppet/application/agent.rb +5 -1
  15. data/lib/puppet/application/apply.rb +4 -0
  16. data/lib/puppet/application/filebucket.rb +78 -4
  17. data/lib/puppet/application/lookup.rb +356 -0
  18. data/lib/puppet/application/master.rb +3 -0
  19. data/lib/puppet/configurer.rb +9 -5
  20. data/lib/puppet/context.rb +16 -1
  21. data/lib/puppet/context/trusted_information.rb +21 -1
  22. data/lib/puppet/daemon.rb +17 -13
  23. data/lib/puppet/data_binding.rb +4 -2
  24. data/lib/puppet/data_providers.rb +12 -13
  25. data/lib/puppet/data_providers/data_adapter.rb +7 -68
  26. data/lib/puppet/data_providers/data_function_support.rb +5 -26
  27. data/lib/puppet/data_providers/function_env_data_provider.rb +0 -10
  28. data/lib/puppet/data_providers/function_module_data_provider.rb +0 -22
  29. data/lib/puppet/data_providers/hiera_config.rb +106 -0
  30. data/lib/puppet/data_providers/hiera_env_data_provider.rb +18 -0
  31. data/lib/puppet/data_providers/hiera_interpolate.rb +97 -0
  32. data/lib/puppet/data_providers/hiera_module_data_provider.rb +23 -0
  33. data/lib/puppet/data_providers/hiera_support.rb +37 -0
  34. data/lib/puppet/data_providers/json_data_provider_factory.rb +31 -0
  35. data/lib/puppet/data_providers/lookup_adapter.rb +200 -0
  36. data/lib/puppet/data_providers/yaml_data_provider_factory.rb +32 -0
  37. data/lib/puppet/defaults.rb +12 -2
  38. data/lib/puppet/error.rb +4 -0
  39. data/lib/puppet/face/module/changes.rb +2 -1
  40. data/lib/puppet/feature/cfacter.rb +1 -0
  41. data/lib/puppet/file_bucket/dipper.rb +58 -2
  42. data/lib/puppet/functions.rb +2 -4
  43. data/lib/puppet/functions/assert_type.rb +48 -12
  44. data/lib/puppet/functions/defined.rb +79 -48
  45. data/lib/puppet/functions/each.rb +85 -27
  46. data/lib/puppet/functions/filter.rb +58 -23
  47. data/lib/puppet/functions/hiera.rb +76 -3
  48. data/lib/puppet/functions/hiera_array.rb +65 -3
  49. data/lib/puppet/functions/hiera_hash.rb +74 -2
  50. data/lib/puppet/functions/hiera_include.rb +75 -2
  51. data/lib/puppet/functions/lookup.rb +19 -17
  52. data/lib/puppet/functions/map.rb +56 -21
  53. data/lib/puppet/functions/match.rb +29 -12
  54. data/lib/puppet/functions/reduce.rb +95 -58
  55. data/lib/puppet/functions/versioncmp.rb +36 -0
  56. data/lib/puppet/functions/with.rb +15 -7
  57. data/lib/puppet/indirector/catalog/compiler.rb +3 -3
  58. data/lib/puppet/indirector/catalog/static_compiler.rb +46 -30
  59. data/lib/puppet/indirector/data_binding/none.rb +4 -1
  60. data/lib/puppet/indirector/file_bucket_file/file.rb +58 -1
  61. data/lib/puppet/indirector/hiera.rb +4 -0
  62. data/lib/puppet/indirector/json.rb +1 -1
  63. data/lib/puppet/indirector/msgpack.rb +1 -1
  64. data/lib/puppet/indirector/request.rb +7 -8
  65. data/lib/puppet/indirector/resource_type/parser.rb +5 -3
  66. data/lib/puppet/info_service.rb +7 -0
  67. data/lib/puppet/info_service/class_information_service.rb +111 -0
  68. data/lib/puppet/module_tool/metadata.rb +32 -9
  69. data/lib/puppet/module_tool/skeleton/templates/generator/README.md.erb +42 -38
  70. data/lib/puppet/network/authconfig.rb +21 -1
  71. data/lib/puppet/network/authorization.rb +8 -1
  72. data/lib/puppet/network/http/api/master/v3.rb +7 -1
  73. data/lib/puppet/network/http/api/master/v3/environment.rb +59 -0
  74. data/lib/puppet/node/environment.rb +9 -2
  75. data/lib/puppet/parser.rb +3 -0
  76. data/lib/puppet/parser/ast/pops_bridge.rb +39 -1
  77. data/lib/puppet/parser/compiler.rb +302 -12
  78. data/lib/puppet/parser/compiler/catalog_validator.rb +33 -0
  79. data/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +64 -0
  80. data/lib/puppet/parser/compiler/catalog_validator/relationship_validator.rb +38 -0
  81. data/lib/puppet/parser/compiler/catalog_validator/site_validator.rb +20 -0
  82. data/lib/puppet/parser/environment_compiler.rb +165 -0
  83. data/lib/puppet/parser/functions/assert_type.rb +46 -16
  84. data/lib/puppet/parser/functions/defined.rb +105 -68
  85. data/lib/puppet/parser/functions/each.rb +85 -27
  86. data/lib/puppet/parser/functions/filter.rb +59 -23
  87. data/lib/puppet/parser/functions/hiera.rb +83 -27
  88. data/lib/puppet/parser/functions/hiera_array.rb +71 -28
  89. data/lib/puppet/parser/functions/hiera_hash.rb +81 -30
  90. data/lib/puppet/parser/functions/hiera_include.rb +81 -40
  91. data/lib/puppet/parser/functions/map.rb +55 -20
  92. data/lib/puppet/parser/functions/match.rb +27 -12
  93. data/lib/puppet/parser/functions/reduce.rb +97 -60
  94. data/lib/puppet/parser/functions/with.rb +16 -8
  95. data/lib/puppet/parser/resource.rb +98 -19
  96. data/lib/puppet/plugins/configuration.rb +3 -2
  97. data/lib/puppet/plugins/data_providers.rb +12 -60
  98. data/lib/puppet/plugins/data_providers/data_provider.rb +283 -0
  99. data/lib/puppet/plugins/data_providers/registry.rb +84 -0
  100. data/lib/puppet/pops.rb +19 -17
  101. data/lib/puppet/pops/adapters.rb +12 -0
  102. data/lib/puppet/pops/binder/binder.rb +2 -2
  103. data/lib/puppet/pops/binder/bindings_checker.rb +1 -1
  104. data/lib/puppet/pops/binder/bindings_label_provider.rb +3 -1
  105. data/lib/puppet/pops/binder/bindings_loader.rb +6 -2
  106. data/lib/puppet/pops/binder/bindings_model_meta.rb +2 -2
  107. data/lib/puppet/pops/binder/config/binder_config.rb +1 -1
  108. data/lib/puppet/pops/binder/injector.rb +4 -4
  109. data/lib/puppet/pops/binder/key_factory.rb +3 -9
  110. data/lib/puppet/pops/binder/scheme_handler/module_scheme.rb +68 -9
  111. data/lib/puppet/pops/evaluator/access_operator.rb +27 -60
  112. data/lib/puppet/pops/evaluator/closure.rb +8 -8
  113. data/lib/puppet/pops/evaluator/collectors/abstract_collector.rb +1 -1
  114. data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -5
  115. data/lib/puppet/pops/evaluator/literal_evaluator.rb +87 -0
  116. data/lib/puppet/pops/evaluator/relationship_operator.rb +7 -1
  117. data/lib/puppet/pops/functions/dispatcher.rb +3 -3
  118. data/lib/puppet/pops/issues.rb +1 -1
  119. data/lib/puppet/pops/label_provider.rb +1 -1
  120. data/lib/puppet/pops/lookup.rb +25 -47
  121. data/lib/puppet/pops/lookup/explainer.rb +402 -0
  122. data/lib/puppet/pops/lookup/invocation.rb +117 -0
  123. data/lib/puppet/pops/merge_strategy.rb +73 -5
  124. data/lib/puppet/pops/model/factory.rb +34 -0
  125. data/lib/puppet/pops/model/model_label_provider.rb +10 -1
  126. data/lib/puppet/pops/model/model_meta.rb +15 -0
  127. data/lib/puppet/pops/model/model_tree_dumper.rb +18 -0
  128. data/lib/puppet/pops/parser/code_merger.rb +13 -1
  129. data/lib/puppet/pops/parser/egrammar.ra +56 -3
  130. data/lib/puppet/pops/parser/eparser.rb +1549 -1352
  131. data/lib/puppet/pops/parser/lexer2.rb +31 -6
  132. data/lib/puppet/pops/parser/locator.rb +1 -1
  133. data/lib/puppet/pops/parser/parser_support.rb +25 -13
  134. data/lib/puppet/pops/types/enumeration.rb +1 -2
  135. data/lib/puppet/pops/types/type_asserter.rb +16 -15
  136. data/lib/puppet/pops/types/type_assertion_error.rb +1 -0
  137. data/lib/puppet/pops/types/type_calculator.rb +171 -1020
  138. data/lib/puppet/pops/types/type_factory.rb +87 -148
  139. data/lib/puppet/pops/types/type_mismatch_describer.rb +743 -0
  140. data/lib/puppet/pops/types/type_parser.rb +116 -127
  141. data/lib/puppet/pops/types/types.rb +1394 -255
  142. data/lib/puppet/pops/types/types_meta.rb +0 -234
  143. data/lib/puppet/pops/validation.rb +7 -2
  144. data/lib/puppet/pops/validation/checker4_0.rb +28 -0
  145. data/lib/puppet/provider/augeas/augeas.rb +50 -0
  146. data/lib/puppet/provider/group/directoryservice.rb +10 -0
  147. data/lib/puppet/provider/package/dnf.rb +41 -0
  148. data/lib/puppet/provider/package/gem.rb +7 -2
  149. data/lib/puppet/provider/package/rpm.rb +1 -0
  150. data/lib/puppet/provider/package/windows/exe_package.rb +10 -8
  151. data/lib/puppet/provider/package/windows/msi_package.rb +4 -3
  152. data/lib/puppet/provider/package/windows/package.rb +9 -1
  153. data/lib/puppet/provider/package/yum.rb +14 -9
  154. data/lib/puppet/provider/service/bsd.rb +1 -1
  155. data/lib/puppet/provider/service/debian.rb +21 -0
  156. data/lib/puppet/provider/service/init.rb +6 -0
  157. data/lib/puppet/provider/service/rcng.rb +51 -0
  158. data/lib/puppet/provider/service/redhat.rb +2 -1
  159. data/lib/puppet/provider/service/smf.rb +43 -2
  160. data/lib/puppet/provider/service/src.rb +27 -0
  161. data/lib/puppet/provider/service/systemd.rb +15 -3
  162. data/lib/puppet/provider/sshkey/parsed.rb +19 -9
  163. data/lib/puppet/reference/report.rb +9 -12
  164. data/lib/puppet/reports.rb +5 -1
  165. data/lib/puppet/resource.rb +50 -73
  166. data/lib/puppet/resource/capability_finder.rb +95 -0
  167. data/lib/puppet/resource/catalog.rb +47 -7
  168. data/lib/puppet/resource/status.rb +0 -2
  169. data/lib/puppet/resource/type.rb +238 -44
  170. data/lib/puppet/resource/type_collection.rb +60 -2
  171. data/lib/puppet/settings.rb +2 -2
  172. data/lib/puppet/ssl/certificate_authority/interface.rb +2 -2
  173. data/lib/puppet/ssl/oids.rb +9 -1
  174. data/lib/puppet/transaction.rb +4 -1
  175. data/lib/puppet/transaction/additional_resource_generator.rb +71 -8
  176. data/lib/puppet/transaction/resource_harness.rb +9 -4
  177. data/lib/puppet/type.rb +74 -3
  178. data/lib/puppet/type/augeas.rb +8 -0
  179. data/lib/puppet/type/file/source.rb +14 -12
  180. data/lib/puppet/type/user.rb +4 -2
  181. data/lib/puppet/util/windows/security.rb +4 -1
  182. data/lib/puppet/util/windows/taskscheduler.rb +1 -1
  183. data/lib/puppet/version.rb +1 -1
  184. data/spec/fixtures/unit/application/environments/production/data/common.yaml +3 -0
  185. data/spec/fixtures/unit/application/environments/production/environment.conf +1 -0
  186. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/data/bad.json +3 -0
  187. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/environment.conf +2 -0
  188. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/hiera.yaml +5 -0
  189. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_json/manifests/site.pp +5 -0
  190. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/data/bad.yaml +3 -0
  191. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/environment.conf +2 -0
  192. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/hiera.yaml +5 -0
  193. data/spec/fixtures/unit/data_providers/environments/hiera_bad_syntax_yaml/manifests/site.pp +5 -0
  194. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/data/common.yaml +2 -0
  195. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/environment.conf +2 -0
  196. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/manifests/site.pp +1 -0
  197. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/data/common.yaml +2 -0
  198. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/manifests/init.pp +5 -0
  199. data/spec/fixtures/unit/data_providers/environments/hiera_defaults/modules/one/metadata.json +9 -0
  200. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/first.json +3 -0
  201. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/name.yaml +2 -0
  202. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/second.json +3 -0
  203. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data1/single.yaml +2 -0
  204. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/data2/single.yaml +2 -0
  205. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/environment.conf +2 -0
  206. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/hiera.yaml +18 -0
  207. data/spec/fixtures/unit/data_providers/environments/hiera_env_config/manifests/site.pp +5 -0
  208. data/spec/fixtures/unit/data_providers/environments/hiera_misc/data/common.yaml +46 -0
  209. data/spec/fixtures/unit/data_providers/environments/hiera_misc/environment.conf +2 -0
  210. data/spec/fixtures/unit/data_providers/environments/hiera_misc/manifests/site.pp +1 -0
  211. data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/data/common.yaml +30 -0
  212. data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/manifests/init.pp +13 -0
  213. data/spec/fixtures/unit/data_providers/environments/hiera_misc/modules/one/metadata.json +9 -0
  214. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/environment.conf +2 -0
  215. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/manifests/site.pp +1 -0
  216. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/first.json +3 -0
  217. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/name.yaml +1 -0
  218. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/second.json +3 -0
  219. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data1/single.yaml +2 -0
  220. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/data2/single.yaml +2 -0
  221. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/hiera.yaml +18 -0
  222. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/manifests/init.pp +5 -0
  223. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/modules/one/metadata.json +9 -0
  224. data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_env_data.rb +1 -0
  225. data/spec/fixtures/unit/data_providers/environments/sample/modules/dataprovider/lib/puppet_x/helindbe/sample_module_data.rb +1 -0
  226. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/data/first.json +3 -0
  227. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/hiera.yaml +8 -0
  228. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/manifests/init.pp +5 -0
  229. data/spec/fixtures/unit/functions/lookup/environments/production/modules/hieraprovider/metadata.json +9 -0
  230. data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/lib/puppet/functions/meta/data.rb +9 -0
  231. data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/manifests/init.pp +3 -0
  232. data/spec/fixtures/unit/functions/lookup/environments/production/modules/meta/metadata.json +9 -0
  233. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/lib/puppet/bindings/metawcp/default.rb +10 -0
  234. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/lib/puppet_x/thallgren/sample_module_data.rb +23 -0
  235. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/manifests/init.pp +3 -0
  236. data/spec/fixtures/unit/functions/lookup/environments/production/modules/metawcp/metadata.json +9 -0
  237. data/spec/fixtures/unit/provider/package/yum/yum-check-update-security.txt +184 -0
  238. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_get/should_yield_to_the_block.yml +24 -0
  239. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_head/should_yield_to_the_block.yml +24 -0
  240. data/spec/fixtures/vcr/cassettes/Puppet_Network_HTTP_Connection/when_handling_requests/_request_post/should_yield_to_the_block.yml +24 -0
  241. data/spec/integration/data_binding_spec.rb +229 -0
  242. data/spec/integration/file_bucket/file_spec.rb +2 -2
  243. data/spec/integration/parser/compiler_spec.rb +23 -19
  244. data/spec/integration/parser/resource_expressions_spec.rb +4 -4
  245. data/spec/integration/parser/undef_param_spec.rb +1 -1
  246. data/spec/integration/resource/catalog_spec.rb +1 -1
  247. data/spec/integration/type/package_spec.rb +2 -0
  248. data/spec/integration/util/windows/security_spec.rb +18 -0
  249. data/spec/lib/matchers/include_in_order.rb +2 -2
  250. data/spec/shared_behaviours/iterative_functions.rb +8 -8
  251. data/spec/spec_helper.rb +7 -0
  252. data/spec/unit/agent/locker_spec.rb +4 -4
  253. data/spec/unit/agent_spec.rb +0 -8
  254. data/spec/unit/application/agent_spec.rb +5 -0
  255. data/spec/unit/application/apply_spec.rb +8 -0
  256. data/spec/unit/application/filebucket_spec.rb +87 -1
  257. data/spec/unit/application/lookup_spec.rb +195 -0
  258. data/spec/unit/appmgmt_spec.rb +657 -0
  259. data/spec/unit/capability_spec.rb +414 -0
  260. data/spec/unit/configurer_spec.rb +7 -1
  261. data/spec/unit/context/trusted_information_spec.rb +24 -1
  262. data/spec/unit/daemon_spec.rb +18 -8
  263. data/spec/unit/data_providers/hiera_data_provider_spec.rb +201 -0
  264. data/spec/unit/file_bucket/dipper_spec.rb +210 -1
  265. data/spec/unit/functions/assert_type_spec.rb +5 -7
  266. data/spec/unit/functions/defined_spec.rb +2 -2
  267. data/spec/unit/functions/epp_spec.rb +2 -2
  268. data/spec/unit/functions/lookup_spec.rb +200 -9
  269. data/spec/unit/functions/regsubst_spec.rb +17 -8
  270. data/spec/unit/functions/scanf_spec.rb +1 -1
  271. data/spec/unit/functions/split_spec.rb +2 -2
  272. data/spec/unit/functions/versioncmp_spec.rb +36 -0
  273. data/spec/unit/functions4_spec.rb +58 -72
  274. data/spec/unit/indirector/catalog/compiler_spec.rb +28 -8
  275. data/spec/unit/indirector/catalog/static_compiler_spec.rb +38 -20
  276. data/spec/unit/indirector/data_binding/none_spec.rb +2 -2
  277. data/spec/unit/indirector/file_bucket_file/file_spec.rb +52 -1
  278. data/spec/unit/indirector/request_spec.rb +8 -8
  279. data/spec/unit/info_service_spec.rb +236 -0
  280. data/spec/unit/module_tool/metadata_spec.rb +31 -2
  281. data/spec/unit/network/authconfig_spec.rb +62 -32
  282. data/spec/unit/network/authorization_spec.rb +30 -2
  283. data/spec/unit/network/http/connection_spec.rb +14 -19
  284. data/spec/unit/parser/compiler_spec.rb +86 -2
  285. data/spec/unit/parser/functions/create_resources_spec.rb +1 -1
  286. data/spec/unit/parser/resource_spec.rb +2 -20
  287. data/spec/unit/pops/binder/config/binder_config_spec.rb +1 -1
  288. data/spec/unit/pops/binder/injector_spec.rb +3 -3
  289. data/spec/unit/pops/evaluator/access_ops_spec.rb +13 -11
  290. data/spec/unit/pops/evaluator/basic_expressions_spec.rb +1 -2
  291. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +19 -11
  292. data/spec/unit/pops/evaluator/literal_evaluator_spec.rb +43 -0
  293. data/spec/unit/pops/label_provider_spec.rb +5 -1
  294. data/spec/unit/pops/parser/lexer2_spec.rb +33 -7
  295. data/spec/unit/pops/parser/parse_application_spec.rb +40 -0
  296. data/spec/unit/pops/parser/parse_basic_expressions_spec.rb +4 -0
  297. data/spec/unit/pops/parser/parse_capabilities_spec.rb +47 -0
  298. data/spec/unit/pops/parser/parse_site_spec.rb +38 -0
  299. data/spec/unit/pops/parser/parser_rspec_helper.rb +5 -0
  300. data/spec/unit/pops/parser/parser_spec.rb +18 -0
  301. data/spec/unit/pops/types/type_calculator_spec.rb +427 -444
  302. data/spec/unit/pops/types/type_factory_spec.rb +12 -12
  303. data/spec/unit/pops/types/type_parser_spec.rb +7 -12
  304. data/spec/unit/pops/validator/validator_spec.rb +25 -0
  305. data/spec/unit/provider/augeas/augeas_spec.rb +50 -0
  306. data/spec/unit/provider/group/directoryservice_spec.rb +33 -0
  307. data/spec/unit/provider/group/windows_adsi_spec.rb +3 -0
  308. data/spec/unit/provider/package/dnf_spec.rb +92 -0
  309. data/spec/unit/provider/package/gem_spec.rb +7 -0
  310. data/spec/unit/provider/package/rpm_spec.rb +25 -2
  311. data/spec/unit/provider/package/windows/package_spec.rb +41 -0
  312. data/spec/unit/provider/package/yum_spec.rb +21 -13
  313. data/spec/unit/provider/scheduled_task/win32_taskscheduler_spec.rb +10 -0
  314. data/spec/unit/provider/service/debian_spec.rb +27 -0
  315. data/spec/unit/provider/service/rcng_spec.rb +41 -0
  316. data/spec/unit/provider/service/redhat_spec.rb +8 -1
  317. data/spec/unit/provider/service/smf_spec.rb +30 -5
  318. data/spec/unit/provider/service/src_spec.rb +19 -4
  319. data/spec/unit/provider/service/systemd_spec.rb +78 -29
  320. data/spec/unit/provider/sshkey/parsed_spec.rb +23 -0
  321. data/spec/unit/reports_spec.rb +10 -0
  322. data/spec/unit/resource/capability_finder_spec.rb +56 -0
  323. data/spec/unit/resource/catalog_spec.rb +31 -8
  324. data/spec/unit/resource/type_collection_spec.rb +23 -2
  325. data/spec/unit/resource/type_spec.rb +1 -1
  326. data/spec/unit/resource_spec.rb +22 -4
  327. data/spec/unit/settings_spec.rb +90 -1
  328. data/spec/unit/ssl/certificate_authority/interface_spec.rb +4 -3
  329. data/spec/unit/ssl/oids_spec.rb +8 -0
  330. data/spec/unit/transaction/additional_resource_generator_spec.rb +78 -5
  331. data/spec/unit/transaction/report_spec.rb +24 -1
  332. data/spec/unit/type/package_spec.rb +1 -0
  333. data/spec/unit/type/user_spec.rb +14 -7
  334. data/spec/unit/type_spec.rb +1 -1
  335. metadata +169 -5
  336. data/lib/puppet/pops/evaluator/callable_mismatch_describer.rb +0 -175
  337. data/spec/integration/data_binding.rb +0 -104
@@ -0,0 +1,743 @@
1
+ module Puppet::Pops::Types
2
+ EMPTY_ARRAY = [].freeze
3
+
4
+ class TypePathElement
5
+ attr_reader :key
6
+
7
+ def initialize(key)
8
+ @key = key
9
+ end
10
+
11
+ def hash
12
+ key.hash
13
+ end
14
+
15
+ def ==(o)
16
+ self.class == o.class && key == o.key
17
+ end
18
+
19
+ alias :eql? :==
20
+ end
21
+
22
+ class MemberPathElement < TypePathElement
23
+ def to_s
24
+ "struct member #{key}"
25
+ end
26
+ end
27
+
28
+ class MemberKeyPathElement < TypePathElement
29
+ def to_s
30
+ "struct member key #{key}"
31
+ end
32
+ end
33
+
34
+ class ParameterPathElement < TypePathElement
35
+ def to_s
36
+ "parameter '#{key}'"
37
+ end
38
+ end
39
+
40
+ class BlockPathElement < ParameterPathElement
41
+ def initialize(name = 'block')
42
+ super(name)
43
+ end
44
+
45
+ def to_s
46
+ key
47
+ end
48
+ end
49
+
50
+ class ArrayPathElement < TypePathElement
51
+ def to_s
52
+ "index #{key}"
53
+ end
54
+ end
55
+
56
+ class VariantPathElement < TypePathElement
57
+ def to_s
58
+ "variant #{key}"
59
+ end
60
+ end
61
+
62
+ class SignaturePathElement < VariantPathElement
63
+ def to_s
64
+ "#{key+1}."
65
+ end
66
+ end
67
+
68
+ class Mismatch
69
+ attr_reader :path
70
+
71
+ def initialize(path)
72
+ @path = path || EMPTY_ARRAY
73
+ end
74
+
75
+ def canonical_path
76
+ @canonical_path ||= @path.reject { |e| e.is_a?(VariantPathElement) }
77
+ end
78
+
79
+ def message(variant, position)
80
+ "#{variant}unknown mismatch#{position}"
81
+ end
82
+
83
+ def merge(path, o)
84
+ self.class.new(path)
85
+ end
86
+
87
+ def ==(o)
88
+ self.class == o.class && canonical_path == o.canonical_path
89
+ end
90
+
91
+ alias :eql? :==
92
+
93
+ def hash
94
+ canonical_path.hash
95
+ end
96
+
97
+ def chop_path(element_index)
98
+ return self if element_index >= @path.size
99
+ chopped_path = @path.clone
100
+ chopped_path.delete_at(element_index)
101
+ copy = self.clone
102
+ copy.instance_variable_set(:@path, chopped_path)
103
+ copy
104
+ end
105
+
106
+ def path_string
107
+ @path.join(' ')
108
+ end
109
+
110
+ def to_s
111
+ p = @path
112
+ variant = ''
113
+ position = ''
114
+ unless p.empty?
115
+ f = p.first
116
+ if f.is_a?(SignaturePathElement)
117
+ variant = " #{f}"
118
+ p = p.drop(1)
119
+ end
120
+ position = " #{p.join(' ')}" unless p.empty?
121
+ end
122
+ message(variant, position)
123
+ end
124
+ end
125
+
126
+ # @abstract
127
+ class KeyMismatch < Mismatch
128
+ attr_reader :key
129
+
130
+ def initialize(path, key)
131
+ super(path)
132
+ @key = key
133
+ end
134
+
135
+ def ==(o)
136
+ super.==(o) && key == o.key
137
+ end
138
+
139
+ def hash
140
+ super.hash * 31 + key.hash
141
+ end
142
+ end
143
+
144
+ class MissingKey < KeyMismatch
145
+ def message(variant, position)
146
+ "#{variant}#{position} expects a value for key '#{key}'"
147
+ end
148
+ end
149
+
150
+ class MissingParameter < KeyMismatch
151
+ def message(variant, position)
152
+ "#{variant}#{position} expects a value for parameter '#{key}'"
153
+ end
154
+ end
155
+
156
+ class ExtraneousKey < KeyMismatch
157
+ def message(variant, position)
158
+ "#{variant}#{position} has no '#{@key}' key"
159
+ end
160
+ end
161
+
162
+ class InvalidParameter < ExtraneousKey
163
+ def message(variant, position)
164
+ "#{variant}#{position} has no parameter named '#{@key}'"
165
+ end
166
+ end
167
+
168
+ class UnexpectedBlock < Mismatch
169
+ def message(variant, position)
170
+ "#{variant}#{position} does not expect a block"
171
+ end
172
+ end
173
+
174
+ class MissingRequiredBlock < Mismatch
175
+ def message(variant, position)
176
+ "#{variant}#{position} expects a block"
177
+ end
178
+ end
179
+
180
+ class ExpectedActualMismatch < Mismatch
181
+ attr_reader :expected, :actual
182
+
183
+ def initialize(path, expected, actual)
184
+ super(path)
185
+ @expected = expected
186
+ @actual = actual
187
+ end
188
+
189
+ def ==(o)
190
+ super.==(o) && expected == o.expected && actual == o.actual
191
+ end
192
+
193
+ def hash
194
+ hash = super.hash
195
+ hash = hash * 31 + expected.hash
196
+ hash * 31 + actual.hash
197
+ end
198
+ end
199
+
200
+ class TypeMismatch < ExpectedActualMismatch
201
+ include Puppet::Pops::LabelProvider
202
+
203
+ # @return A new instance with the least restrictive respective boundaries
204
+ def merge(path, o)
205
+ self.class.new(path, [expected, o.expected].flatten.uniq, actual)
206
+ end
207
+
208
+ def message(variant, position)
209
+ e = expected
210
+ a = actual
211
+ multi = false
212
+ if e.is_a?(Array)
213
+ # Use simple names when classes differ, or in other words, only include details
214
+ # when the classes are equal.
215
+ #
216
+ if e.find { |t| t.class == a.class }
217
+ e = e.map { |t| t.to_s }
218
+ a = a.to_s
219
+ else
220
+ sns = e.map { |t| t.simple_name }
221
+ e = e.map { |t| s = t.simple_name; sns.count {|x| x == s } == 1 ? s : t.to_s }
222
+ a = a.simple_name
223
+ end
224
+ case e.size
225
+ when 1
226
+ e = e[0]
227
+ when 2
228
+ e = "#{e[0]} or #{e[1]}"
229
+ multi = true
230
+ else
231
+ e = "#{e[0..e.size-2].join(', ')}, or #{e[e.size-1]}"
232
+ multi = true
233
+ end
234
+ else
235
+ if e.class != a.class
236
+ e = e.simple_name
237
+ a = a.simple_name
238
+ else
239
+ e = e.to_s
240
+ a = a.to_s
241
+ end
242
+ end
243
+ multi ? "#{variant}#{position} expects a value of type #{e}, got #{label(a)}" : "#{variant}#{position} expects #{a_an(e)} value, got #{label(a)}"
244
+ end
245
+
246
+ def label(o)
247
+ o.to_s
248
+ end
249
+ end
250
+
251
+ class PatternMismatch < TypeMismatch
252
+ def message(variant, position)
253
+ "#{variant}#{position} expects a match for #{expected}, got #{actual_string}"
254
+ end
255
+
256
+ def actual_string
257
+ a = actual
258
+ a.is_a?(PStringType) && a.values.size == 1 ? "'#{a.values[0]}'" : a.simple_name
259
+ end
260
+ end
261
+
262
+ class SizeMismatch < ExpectedActualMismatch
263
+ def from
264
+ @expected.from || 0
265
+ end
266
+
267
+ def to
268
+ @expected.to || Float::INFINITY
269
+ end
270
+
271
+ # @return A new instance with the least restrictive respective boundaries
272
+ def merge(path, o)
273
+ range = PIntegerType.new(from < o.from ? from : o.from, to > o.to ? to : o.to)
274
+ self.class.new(path, range, @actual)
275
+ end
276
+
277
+ def message(variant, position)
278
+ "#{variant}#{position} expects size to be #{range_to_s(expected, '0')}, got #{range_to_s(actual, '0')}"
279
+ end
280
+
281
+ def range_to_s(range, zero_string)
282
+ min = range.from || 0
283
+ max = range.to || Float::INFINITY
284
+ if min == max
285
+ min == 0 ? zero_string : min.to_s
286
+ elsif min == 0
287
+ max == Float::INFINITY ? 'unlimited' : "at most #{max}"
288
+ elsif max == Float::INFINITY
289
+ "at least #{min}"
290
+ else
291
+ "between #{min} and #{max}"
292
+ end
293
+ end
294
+ end
295
+
296
+ class CountMismatch < SizeMismatch
297
+ def initialize(path, expected, actual)
298
+ super(path, expected, actual)
299
+ end
300
+
301
+ def message(variant, position)
302
+ min = expected.from || 0
303
+ max = expected.to || Float::INFINITY
304
+ suffix = min == 1 && (max == 1 || max == Float::INFINITY) || min == 0 && max == 1 ? '' : 's'
305
+ "#{variant}#{position} expects #{range_to_s(expected, 'no')} argument#{suffix}, got #{range_to_s(actual, 'none')}"
306
+ end
307
+ end
308
+
309
+ class TypeMismatchDescriber
310
+ def self.validate_parameters(subject, params_struct, given_hash, missing_ok = false)
311
+ singleton.validate_parameters(subject, params_struct, given_hash, missing_ok)
312
+ end
313
+
314
+ def self.validate_default_parameter(subject, param_name, param_type, value)
315
+ singleton.validate_default_parameter(subject, param_name, param_type, value)
316
+ end
317
+
318
+ def self.describe_signatures(closure, signatures, args_tuple)
319
+ singleton.describe_signatures(closure, signatures, args_tuple)
320
+ end
321
+
322
+ def self.singleton
323
+ @singleton ||= new
324
+ end
325
+
326
+ # Validates that all entries in the give_hash exists in the given param_struct, that their type conforms
327
+ # with the corresponding param_struct element and that all required values are provided.
328
+ #
329
+ # @param subject [String] string to be prepended to the exception message
330
+ # @param params_struct [PStructType] Struct to use for validation
331
+ # @param given_hash [Hash<String,Object>] the parameters to validate
332
+ # @param missing_ok [Boolean] Do not generate errors on missing parameters
333
+ #
334
+ def validate_parameters(subject, params_struct, given_hash, missing_ok = false)
335
+ errors = describe_struct_signature(params_struct, given_hash, missing_ok).flatten
336
+ case errors.size
337
+ when 0
338
+ when 1
339
+ raise Puppet::ParseError.new("#{subject}:#{errors[0]}")
340
+ else
341
+ raise Puppet::ParseError.new("#{subject}:\n #{errors.join("\n ")}")
342
+ end
343
+ end
344
+
345
+ # @param subject [String] string to be prepended to the exception message
346
+ # @param param_name [String] parameter name
347
+ # @param param_type [PAnyType] parameter type
348
+ # @param value [Object] value to be validated against the given type
349
+ #
350
+ def validate_default_parameter(subject, param_name, param_type, value)
351
+ unless param_type.instance?(value)
352
+ errors = describe(param_type, TypeCalculator.singleton.infer_set(value).generalize, [ParameterPathElement.new(param_name)])
353
+ case errors.size
354
+ when 0
355
+ when 1
356
+ raise Puppet::ParseError.new("#{subject}:#{errors[0]}")
357
+ else
358
+ raise Puppet::ParseError.new("#{subject}:\n #{errors.join("\n ")}")
359
+ end
360
+ end
361
+ end
362
+
363
+ # Validates that all entries in the _param_hash_ exists in the given param_struct, that their type conforms
364
+ # with the corresponding param_struct element and that all required values are provided.
365
+ # An error message is created for each problem found.
366
+ #
367
+ # @param params_struct [PStructType] Struct to use for validation
368
+ # @param param_hash [Hash<String,Object>] The parameters to validate
369
+ # @param missing_ok [Boolean] Do not generate errors on missing parameters
370
+ # @return [Array<Mismatch>] An array of found errors. An empty array indicates no errors.
371
+ def describe_struct_signature(params_struct, param_hash, missing_ok = false)
372
+ param_type_hash = params_struct.hashed_elements
373
+ result = param_hash.each_key.reject { |name| param_type_hash.include?(name) }.map { |name| InvalidParameter.new(nil, name) }
374
+
375
+ params_struct.elements.each do |elem|
376
+ name = elem.name
377
+ value = param_hash[name]
378
+ value_type = elem.value_type
379
+ if param_hash.include?(name)
380
+ result << describe(value_type, TypeCalculator.singleton.infer_set(value).generalize, [ParameterPathElement.new(name)]) unless value_type.instance?(value)
381
+ else
382
+ result << MissingParameter.new(nil, name) unless elem.key_type.assignable?(PUndefType::DEFAULT) unless missing_ok
383
+ end
384
+ end
385
+ result
386
+ end
387
+
388
+ def describe_signatures(closure, signatures, args_tuple)
389
+ error_arrays = []
390
+ signatures.each_with_index do |signature, index|
391
+ error_arrays << describe_signature_arguments(signature, args_tuple, [SignaturePathElement.new(index)])
392
+ end
393
+
394
+ # Skip block checks if all signatures have argument errors
395
+ unless error_arrays.all? { |a| !a.empty? }
396
+ block_arrays = []
397
+ signatures.each_with_index do |signature, index|
398
+ block_arrays << describe_signature_block(signature, args_tuple, [SignaturePathElement.new(index)])
399
+ end
400
+ bc_count = block_arrays.count { |a| !a.empty? }
401
+ if bc_count == block_arrays.size
402
+ # Skip argument errors when all alternatives have block errors
403
+ error_arrays = block_arrays
404
+ elsif bc_count > 0
405
+ # Merge errors giving argument errors precedence over block errors
406
+ error_arrays.each_with_index { |a, index| error_arrays[index] = block_arrays[index] if a.empty? }
407
+ end
408
+ end
409
+ return nil if error_arrays.empty?
410
+
411
+ label = closure == 'lambda' ? 'block' : "'#{closure}'"
412
+ errors = merge_descriptions(0, CountMismatch, error_arrays)
413
+ if errors.size == 1
414
+ "#{label}#{errors[0]}"
415
+ else
416
+ if signatures.size == 1
417
+ sig = signatures[0]
418
+ result = ["#{label} expected (#{signature_string(sig)})"]
419
+ result.concat(error_arrays[0].map { |e| " rejected:#{e.chop_path(0)}" })
420
+ else
421
+ result = ["#{label} expected one of:"]
422
+ signatures.each_with_index do |sg, index|
423
+ result << " (#{signature_string(sg)})"
424
+ result.concat(error_arrays[index].map { |e| " rejected:#{e.chop_path(0)}" })
425
+ end
426
+ end
427
+ result.join("\n")
428
+ end
429
+ end
430
+
431
+ def describe_signature_arguments(signature, args_tuple, path)
432
+ params_tuple = signature.type.param_types
433
+ params_size_t = params_tuple.size_type || TypeFactory.range(*params_tuple.size_range)
434
+
435
+ if args_tuple.is_a?(PTupleType)
436
+ arg_types = args_tuple.types
437
+ elsif args_tuple.is_a?(PArrayType)
438
+ arg_types = Array.new(params_tuple.types.size, args_tuple.element_type || PUndefType::DEFAULT)
439
+ else
440
+ return [TypeMismatch.new(path, params_tuple, args_tuple)]
441
+ end
442
+
443
+ if arg_types.last.kind_of_callable?
444
+ # Check other arguments
445
+ arg_count = arg_types.size - 1
446
+ describe_no_block_arguments(signature, arg_types, path, params_size_t, TypeFactory.range(arg_count, arg_count), arg_count)
447
+ else
448
+ args_size_t = TypeFactory.range(*args_tuple.size_range)
449
+ describe_no_block_arguments(signature, arg_types, path, params_size_t, args_size_t, arg_types.size)
450
+ end
451
+ end
452
+
453
+ def describe_signature_block(signature, args_tuple, path)
454
+ param_block_t = signature.block_type
455
+ arg_block_t = args_tuple.is_a?(PTupleType) ? args_tuple.types.last : nil
456
+ if TypeCalculator.is_kind_of_callable?(arg_block_t)
457
+ # Can't pass a block to a callable that doesn't accept one
458
+ if param_block_t.nil?
459
+ [UnexpectedBlock.new(path)]
460
+ else
461
+ # Check that the block is of the right type
462
+ describe(param_block_t, arg_block_t, path + [BlockPathElement.new])
463
+ end
464
+ else
465
+ # Check that the block is optional
466
+ if param_block_t.nil? || param_block_t.assignable?(PUndefType::DEFAULT)
467
+ EMPTY_ARRAY
468
+ else
469
+ [MissingRequiredBlock.new(path)]
470
+ end
471
+ end
472
+ end
473
+
474
+ def describe_no_block_arguments(signature, atypes, path, expected_size, actual_size, arg_count)
475
+ # not assignable if the number of types in actual is outside number of types in expected
476
+ if expected_size.assignable?(actual_size)
477
+ etypes = signature.type.param_types.types
478
+ enames = signature.parameter_names
479
+ arg_count.times do |index|
480
+ adx = index >= etypes.size ? etypes.size - 1 : index
481
+ etype = etypes[adx]
482
+ descriptions = describe(etype, atypes[index], path + [ParameterPathElement.new(enames[adx])])
483
+ return descriptions unless descriptions.empty?
484
+ end
485
+ EMPTY_ARRAY
486
+ else
487
+ [CountMismatch.new(path, expected_size, actual_size)]
488
+ end
489
+ end
490
+
491
+ def describe_PVariantType(expected, actual, path)
492
+ variant_descriptions = []
493
+ expected.types.each_with_index do |vt, index|
494
+ d = describe(vt, actual, path + [VariantPathElement.new(index)])
495
+ return EMPTY_ARRAY if d.empty?
496
+ variant_descriptions << d
497
+ end
498
+ merge_descriptions(path.length, SizeMismatch, variant_descriptions)
499
+ end
500
+
501
+ def merge_descriptions(varying_path_position, size_mismatch_class, variant_descriptions)
502
+ descriptions = variant_descriptions.flatten
503
+ [size_mismatch_class, MissingRequiredBlock, UnexpectedBlock, TypeMismatch].each do |mismatch_class|
504
+ mismatches = descriptions.select { |desc| desc.is_a?(mismatch_class) }
505
+ if mismatches.size == variant_descriptions.size
506
+ # If they all have the same canonical path, then we can compact this into one
507
+ generic_mismatch = mismatches.inject do |prev, curr|
508
+ break nil unless prev.canonical_path == curr.canonical_path
509
+ prev.merge(prev.path, curr)
510
+ end
511
+ unless generic_mismatch.nil?
512
+ # Report the generic mismatch and skip the rest
513
+ descriptions = [generic_mismatch]
514
+ break
515
+ end
516
+ end
517
+ end
518
+ descriptions = descriptions.uniq
519
+ descriptions.size == 1 ? [descriptions[0].chop_path(varying_path_position)] : descriptions
520
+ end
521
+
522
+ def describe_POptionalType(expected, actual, path)
523
+ actual.is_a?(PUndefType) ? [] : describe(expected.optional_type, actual, path)
524
+ end
525
+
526
+ def describe_PEnumType(expected, actual, path)
527
+ [PatternMismatch.new(path, expected, actual)]
528
+ end
529
+
530
+ def describe_PPatternType(expected, actual, path)
531
+ [PatternMismatch.new(path, expected, actual)]
532
+ end
533
+
534
+ def describe_PStructType(expected, actual, path)
535
+ elements = expected.elements
536
+ descriptions = []
537
+ if actual.is_a?(PStructType)
538
+ h2 = actual.hashed_elements.clone
539
+ elements.each do |e1|
540
+ key = e1.name
541
+ e2 = h2.delete(key)
542
+ if e2.nil?
543
+ descriptions << MissingKey.new(path, key) unless e1.key_type.assignable?(PUndefType::DEFAULT)
544
+ else
545
+ descriptions.concat(describe(e1.key_type, e2.key_type, path + [MemberKeyPathElement.new(key)])) unless e1.key_type.assignable?(e2.key_type)
546
+ descriptions.concat(describe(e1.value_type, e2.value_type, path + [MemberPathElement.new(key)])) unless e1.value_type.assignable?(e2.value_type)
547
+ end
548
+ end
549
+ h2.each_key { |key| descriptions << ExtraneousKey.new(path, key) }
550
+ elsif actual.is_a?(PHashType)
551
+ actual_size = actual.size_type || PCollectionType::DEFAULT_SIZE
552
+ expected_size = PIntegerType.new(elements.count { |e| !e.type.assignable?(PUndefType::DEFAULT) }, elements.size)
553
+ if expected_size.assignable?(actual_size)
554
+ if actual_size.to == 0 || PStringType::NON_EMPTY.assignable?(actual.key_type)
555
+ descriptions.concat(describe(e.type, actual.element_type, path + [MemberPathElement.new(e.key)]))
556
+ else
557
+ descriptions << TypeMismatch(path, @non_empty_string_, actual.key_type)
558
+ end
559
+ else
560
+ descriptions << SizeMismatch(path, expected_size, actual_size)
561
+ end
562
+ else
563
+ descriptions << TypeMismatch.new(path, expected, actual)
564
+ end
565
+ descriptions
566
+ end
567
+
568
+ def describe_PTupleType(expected, actual, path)
569
+ describe_tuple(expected, actual, path, SizeMismatch)
570
+ end
571
+
572
+ def describe_argument_tuple(expected, actual, path)
573
+ describe_tuple(expected, actual, path, CountMismatch)
574
+ end
575
+
576
+ def describe_tuple(expected, actual, path, size_mismatch_class)
577
+ return if expected == actual || expected.types.empty? && (actual.is_a?(PArrayType))
578
+ expected_size = expected.size_type || TypeFactory.range(*expected.size_range)
579
+
580
+ if actual.is_a?(PTupleType)
581
+ actual_size = actual.size_type || TypeFactory.range(*actual.size_range)
582
+
583
+ # not assignable if the number of types in actual is outside number of types in expected
584
+ if expected_size.assignable?(actual_size)
585
+ etypes = expected.types
586
+ descriptions = []
587
+ actual.types.each_with_index do |atype, index|
588
+ adx = index >= etypes.size ? etypes.size - 1 : index
589
+ etype = etypes[adx]
590
+ descriptions.concat(describe(etypes[adx], atype, path + [ArrayPathElement.new(adx)]))
591
+ end
592
+ descriptions
593
+ else
594
+ [size_mismatch_class.new(path, expected_size, actual_size)]
595
+ end
596
+ elsif actual.is_a?(PArrayType)
597
+ t2_entry = actual.element_type
598
+
599
+ if t2_entry.nil?
600
+ # Array of anything can not be assigned (unless tuple is tuple of anything) - this case
601
+ # was handled at the top of this method.
602
+ #
603
+ [TypeMismatch.new(path, expected, actual)]
604
+ else
605
+ expected_size = expected.size_type || TypeFactory.range(*expected.size_range)
606
+ actual_size = actual.size_type || PCollectionType::DEFAULT_SIZE
607
+ if expected_size.assignable?(actual_size)
608
+ descriptions = []
609
+ expected.types.each_with_index do |etype, index|
610
+ descriptions.concat(describe(etype, actual.element_type, path + [ArrayPathElement.new(index)]))
611
+ end
612
+ descriptions
613
+ else
614
+ [size_mismatch_class.new(path, expected_size, actual_size)]
615
+ end
616
+ end
617
+ else
618
+ [TypeMismatch.new(path, expected, actual)]
619
+ end
620
+ end
621
+
622
+ def describe_PCallableType(expected, actual, path)
623
+ if actual.is_a?(PCallableType)
624
+ # nil param_types means, any other Callable is assignable
625
+ if expected.param_types.nil?
626
+ EMPTY_ARRAY
627
+ else
628
+ # NOTE: these tests are made in reverse as it is calling the callable that is constrained
629
+ # (it's lower bound), not its upper bound
630
+ param_errors = describe_argument_tuple(expected.param_types, actual.param_types, path)
631
+ if param_errors.empty?
632
+ # names are ignored, they are just information
633
+ # Blocks must be compatible
634
+ this_block_t = expected.block_type || PUndefType::DEFAULT
635
+ that_block_t = actual.block_type || PUndefType::DEFAULT
636
+ if that_block_t.assignable?(this_block_t)
637
+ EMPTY_ARRAY
638
+ else
639
+ [TypeMismatch.new(path + BlockPathElement.new, this_block_t, that_block_t)]
640
+ end
641
+ else
642
+ param_errors
643
+ end
644
+ end
645
+ else
646
+ [TypeMismatch.new(path, expected, actual)]
647
+ end
648
+ end
649
+
650
+ def describe_PAnyType(expected, actual, path)
651
+ expected.assignable?(actual) ? EMPTY_ARRAY : [TypeMismatch.new(path, expected, actual)]
652
+ end
653
+
654
+ def describe(expected, actual, path)
655
+ case expected
656
+ when PVariantType
657
+ describe_PVariantType(expected, actual, path)
658
+ when PStructType
659
+ describe_PStructType(expected, actual, path)
660
+ when PTupleType
661
+ describe_PTupleType(expected, actual, path)
662
+ when PCallableType
663
+ describe_PCallableType(expected, actual, path)
664
+ when POptionalType
665
+ describe_POptionalType(expected, actual, path)
666
+ when PPatternType
667
+ describe_PPatternType(expected, actual, path)
668
+ when PEnumType
669
+ describe_PEnumType(expected, actual, path)
670
+ else
671
+ describe_PAnyType(expected, actual, path)
672
+ end
673
+ end
674
+
675
+ # Produces a string for the signature(s)
676
+ #
677
+ # @api private
678
+ def signature_string(signature)
679
+ param_types = signature.type.param_types
680
+ param_names = signature.parameter_names
681
+
682
+ from, to = param_types.size_range
683
+ if from == 0 && to == 0
684
+ # No parameters function
685
+ return ''
686
+ end
687
+
688
+ required_count = from
689
+ types =
690
+ case param_types
691
+ when Puppet::Pops::Types::PTupleType
692
+ param_types.types
693
+ when Puppet::Pops::Types::PArrayType
694
+ [param_types.element_type]
695
+ end
696
+ tc = Puppet::Pops::Types::TypeCalculator.singleton
697
+
698
+ # join type with names (types are always present, names are optional)
699
+ # separate entries with comma
700
+ #
701
+ param_names = Array.new(types.size, '') if param_names.empty?
702
+ limit = param_names.size
703
+ result = param_names.each_with_index.map do |name, index|
704
+ type = types[index] || types[-1]
705
+ indicator = ''
706
+ if to == Float::INFINITY && index == limit - 1
707
+ # Last is a repeated_param.
708
+ indicator = from == param_names.size ? '+' : '*'
709
+ elsif optional(index, required_count)
710
+ indicator = '?'
711
+ type = type.optional_type if type.is_a?(Puppet::Pops::Types::POptionalType)
712
+ end
713
+ "#{tc.string(type)} #{name}#{indicator}"
714
+ end.join(', ')
715
+
716
+ # If there is a block, include it
717
+ case signature.type.block_type
718
+ when Puppet::Pops::Types::POptionalType
719
+ result << ', ' unless result == ''
720
+ result << "#{signature.type.block_type.optional_type} #{signature.block_name}?"
721
+ when Puppet::Pops::Types::PCallableType
722
+ result << ', ' unless result == ''
723
+ result << "#{signature.type.block_type} #{signature.block_name}"
724
+ when NilClass
725
+ # nothing
726
+ end
727
+ result
728
+ end
729
+
730
+ # Why oh why Ruby do you not have a standard Math.max ?
731
+ # @api private
732
+ def max(a, b)
733
+ a >= b ? a : b
734
+ end
735
+
736
+ # @api private
737
+ def optional(index, required_count)
738
+ count = index + 1
739
+ count > required_count
740
+ end
741
+ end
742
+ end
743
+