puppet 6.11.1 → 6.16.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 (395) hide show
  1. checksums.yaml +4 -4
  2. data/CODEOWNERS +3 -8
  3. data/CONTRIBUTING.md +7 -13
  4. data/Gemfile +1 -0
  5. data/Gemfile.lock +39 -36
  6. data/README.md +17 -24
  7. data/ext/build_defaults.yaml +1 -0
  8. data/ext/project_data.yaml +1 -1
  9. data/ext/windows/service/daemon.rb +25 -20
  10. data/lib/puppet.rb +52 -13
  11. data/lib/puppet/agent.rb +20 -14
  12. data/lib/puppet/application/agent.rb +12 -14
  13. data/lib/puppet/application/describe.rb +7 -5
  14. data/lib/puppet/application/device.rb +2 -2
  15. data/lib/puppet/application/filebucket.rb +19 -15
  16. data/lib/puppet/application/plugin.rb +1 -0
  17. data/lib/puppet/application/resource.rb +1 -1
  18. data/lib/puppet/application/ssl.rb +4 -4
  19. data/lib/puppet/concurrent.rb +2 -0
  20. data/lib/puppet/concurrent/lock.rb +16 -0
  21. data/lib/puppet/concurrent/synchronized.rb +15 -0
  22. data/lib/puppet/concurrent/thread_local_singleton.rb +14 -0
  23. data/lib/puppet/configurer.rb +85 -83
  24. data/lib/puppet/configurer/plugin_handler.rb +10 -1
  25. data/lib/puppet/context/trusted_information.rb +14 -8
  26. data/lib/puppet/daemon.rb +13 -27
  27. data/lib/puppet/defaults.rb +158 -40
  28. data/lib/puppet/environments.rb +30 -20
  29. data/lib/puppet/error.rb +9 -1
  30. data/lib/puppet/face/facts.rb +8 -5
  31. data/lib/puppet/face/help.rb +29 -3
  32. data/lib/puppet/face/module/search.rb +5 -0
  33. data/lib/puppet/face/plugin.rb +2 -2
  34. data/lib/puppet/file_serving/http_metadata.rb +1 -1
  35. data/lib/puppet/file_system/file_impl.rb +13 -9
  36. data/lib/puppet/file_system/memory_file.rb +6 -0
  37. data/lib/puppet/file_system/memory_impl.rb +13 -0
  38. data/lib/puppet/file_system/uniquefile.rb +4 -0
  39. data/lib/puppet/file_system/windows.rb +7 -10
  40. data/lib/puppet/forge.rb +3 -3
  41. data/lib/puppet/forge/errors.rb +2 -2
  42. data/lib/puppet/forge/repository.rb +31 -86
  43. data/lib/puppet/functions/call.rb +1 -1
  44. data/lib/puppet/functions/camelcase.rb +2 -2
  45. data/lib/puppet/functions/epp.rb +4 -4
  46. data/lib/puppet/functions/eyaml_lookup_key.rb +13 -8
  47. data/lib/puppet/functions/filter.rb +1 -0
  48. data/lib/puppet/functions/find_file.rb +9 -9
  49. data/lib/puppet/functions/find_template.rb +63 -0
  50. data/lib/puppet/functions/inline_epp.rb +5 -5
  51. data/lib/puppet/functions/reduce.rb +2 -4
  52. data/lib/puppet/http.rb +7 -0
  53. data/lib/puppet/http/client.rb +341 -54
  54. data/lib/puppet/http/errors.rb +2 -0
  55. data/lib/puppet/http/external_client.rb +90 -0
  56. data/lib/puppet/http/redirector.rb +34 -0
  57. data/lib/puppet/http/resolver.rb +57 -1
  58. data/lib/puppet/http/resolver/server_list.rb +98 -0
  59. data/lib/puppet/http/resolver/settings.rb +23 -2
  60. data/lib/puppet/http/resolver/srv.rb +36 -4
  61. data/lib/puppet/http/response.rb +68 -1
  62. data/lib/puppet/http/retry_after_handler.rb +39 -0
  63. data/lib/puppet/http/service.rb +179 -3
  64. data/lib/puppet/http/service/ca.rb +84 -21
  65. data/lib/puppet/http/service/compiler.rb +319 -0
  66. data/lib/puppet/http/service/file_server.rb +206 -0
  67. data/lib/puppet/http/service/report.rb +66 -0
  68. data/lib/puppet/http/session.rb +106 -31
  69. data/lib/puppet/indirector/catalog/compiler.rb +10 -0
  70. data/lib/puppet/indirector/catalog/rest.rb +34 -0
  71. data/lib/puppet/indirector/facts/rest.rb +42 -0
  72. data/lib/puppet/indirector/file_bucket_file/file.rb +1 -1
  73. data/lib/puppet/indirector/file_bucket_file/rest.rb +48 -0
  74. data/lib/puppet/indirector/file_content/http.rb +5 -0
  75. data/lib/puppet/indirector/file_content/rest.rb +30 -0
  76. data/lib/puppet/indirector/file_metadata/http.rb +4 -4
  77. data/lib/puppet/indirector/file_metadata/rest.rb +52 -0
  78. data/lib/puppet/indirector/json.rb +1 -1
  79. data/lib/puppet/indirector/msgpack.rb +1 -1
  80. data/lib/puppet/indirector/node/rest.rb +24 -0
  81. data/lib/puppet/indirector/report/rest.rb +19 -0
  82. data/lib/puppet/indirector/report/yaml.rb +23 -0
  83. data/lib/puppet/indirector/rest.rb +12 -0
  84. data/lib/puppet/indirector/status/rest.rb +18 -0
  85. data/lib/puppet/loaders.rb +6 -0
  86. data/lib/puppet/metatype/manager.rb +80 -80
  87. data/lib/puppet/network/http/base_pool.rb +19 -1
  88. data/lib/puppet/network/http/compression.rb +7 -0
  89. data/lib/puppet/network/http/connection.rb +6 -0
  90. data/lib/puppet/network/http/connection_adapter.rb +182 -0
  91. data/lib/puppet/network/http/nocache_pool.rb +2 -0
  92. data/lib/puppet/network/http/pool.rb +13 -6
  93. data/lib/puppet/network/http_pool.rb +2 -1
  94. data/lib/puppet/node/environment.rb +24 -8
  95. data/lib/puppet/pal/catalog_compiler.rb +5 -0
  96. data/lib/puppet/pal/pal_impl.rb +9 -29
  97. data/lib/puppet/parser/ast/pops_bridge.rb +6 -11
  98. data/lib/puppet/parser/compiler.rb +42 -32
  99. data/lib/puppet/parser/functions.rb +18 -13
  100. data/lib/puppet/parser/functions/epp.rb +3 -3
  101. data/lib/puppet/parser/functions/filter.rb +1 -0
  102. data/lib/puppet/parser/functions/inline_epp.rb +5 -5
  103. data/lib/puppet/pops/evaluator/access_operator.rb +2 -2
  104. data/lib/puppet/pops/evaluator/evaluator_impl.rb +1 -1
  105. data/lib/puppet/pops/evaluator/runtime3_support.rb +1 -1
  106. data/lib/puppet/pops/loader/puppet_plan_instantiator.rb +12 -3
  107. data/lib/puppet/pops/loaders.rb +7 -5
  108. data/lib/puppet/pops/lookup/invocation.rb +10 -3
  109. data/lib/puppet/pops/model/pn_transformer.rb +5 -9
  110. data/lib/puppet/pops/parser/evaluating_parser.rb +8 -11
  111. data/lib/puppet/pops/serialization/json_path.rb +3 -3
  112. data/lib/puppet/pops/time/timespan.rb +3 -5
  113. data/lib/puppet/pops/types/p_object_type_extension.rb +10 -0
  114. data/lib/puppet/pops/types/string_converter.rb +6 -9
  115. data/lib/puppet/pops/types/type_calculator.rb +30 -10
  116. data/lib/puppet/pops/types/type_formatter.rb +9 -11
  117. data/lib/puppet/pops/types/type_parser.rb +3 -3
  118. data/lib/puppet/pops/validation/checker4_0.rb +1 -1
  119. data/lib/puppet/pops/validation/tasks_checker.rb +5 -1
  120. data/lib/puppet/provider/aix_object.rb +4 -2
  121. data/lib/puppet/provider/group/aix.rb +1 -0
  122. data/lib/puppet/provider/group/groupadd.rb +57 -24
  123. data/lib/puppet/provider/group/windows_adsi.rb +3 -3
  124. data/lib/puppet/provider/package/aix.rb +17 -2
  125. data/lib/puppet/provider/package/apt.rb +78 -4
  126. data/lib/puppet/provider/package/dnfmodule.rb +69 -15
  127. data/lib/puppet/provider/package/dpkg.rb +14 -7
  128. data/lib/puppet/provider/package/fink.rb +20 -3
  129. data/lib/puppet/provider/package/gem.rb +41 -7
  130. data/lib/puppet/provider/package/openbsd.rb +13 -1
  131. data/lib/puppet/provider/package/pacman.rb +2 -5
  132. data/lib/puppet/provider/package/pip.rb +143 -48
  133. data/lib/puppet/provider/package/pip3.rb +0 -2
  134. data/lib/puppet/provider/package/pkg.rb +18 -5
  135. data/lib/puppet/provider/package/pkgdmg.rb +1 -1
  136. data/lib/puppet/provider/package/pkgng.rb +16 -4
  137. data/lib/puppet/provider/package/portage.rb +5 -5
  138. data/lib/puppet/provider/package/puppet_gem.rb +6 -2
  139. data/lib/puppet/provider/package/rpm.rb +6 -213
  140. data/lib/puppet/provider/package/yum.rb +108 -24
  141. data/lib/puppet/provider/package/zypper.rb +59 -1
  142. data/lib/puppet/provider/package_targetable.rb +5 -4
  143. data/lib/puppet/provider/service/systemd.rb +23 -5
  144. data/lib/puppet/provider/user/aix.rb +1 -0
  145. data/lib/puppet/provider/user/directoryservice.rb +30 -5
  146. data/lib/puppet/provider/user/hpux.rb +1 -1
  147. data/lib/puppet/provider/user/useradd.rb +11 -8
  148. data/lib/puppet/reports/http.rb +13 -9
  149. data/lib/puppet/reports/store.rb +1 -1
  150. data/lib/puppet/resource/type_collection.rb +20 -16
  151. data/lib/puppet/runtime.rb +32 -1
  152. data/lib/puppet/settings.rb +4 -0
  153. data/lib/puppet/settings/http_extra_headers_setting.rb +25 -0
  154. data/lib/puppet/ssl.rb +1 -0
  155. data/lib/puppet/ssl/certificate.rb +2 -1
  156. data/lib/puppet/ssl/host.rb +4 -4
  157. data/lib/puppet/ssl/oids.rb +1 -0
  158. data/lib/puppet/ssl/ssl_provider.rb +20 -0
  159. data/lib/puppet/ssl/state_machine.rb +81 -35
  160. data/lib/puppet/ssl/verifier_adapter.rb +9 -1
  161. data/lib/puppet/test/test_helper.rb +7 -1
  162. data/lib/puppet/transaction.rb +33 -11
  163. data/lib/puppet/transaction/report.rb +2 -2
  164. data/lib/puppet/transaction/resource_harness.rb +1 -1
  165. data/lib/puppet/type.rb +7 -2
  166. data/lib/puppet/type/file.rb +13 -0
  167. data/lib/puppet/type/file/data_sync.rb +5 -1
  168. data/lib/puppet/type/file/source.rb +49 -58
  169. data/lib/puppet/type/group.rb +5 -4
  170. data/lib/puppet/type/package.rb +102 -10
  171. data/lib/puppet/type/service.rb +6 -8
  172. data/lib/puppet/type/user.rb +6 -30
  173. data/lib/puppet/util.rb +34 -11
  174. data/lib/puppet/util/at_fork.rb +1 -1
  175. data/lib/puppet/util/autoload.rb +4 -18
  176. data/lib/puppet/util/instance_loader.rb +14 -10
  177. data/lib/puppet/util/log/destinations.rb +2 -11
  178. data/lib/puppet/util/logging.rb +30 -18
  179. data/lib/puppet/util/package/version/debian.rb +175 -0
  180. data/lib/puppet/util/package/version/gem.rb +15 -0
  181. data/lib/puppet/util/package/version/pip.rb +167 -0
  182. data/lib/puppet/util/package/version/range.rb +53 -0
  183. data/lib/puppet/util/package/version/range/eq.rb +14 -0
  184. data/lib/puppet/util/package/version/range/gt.rb +14 -0
  185. data/lib/puppet/util/package/version/range/gt_eq.rb +14 -0
  186. data/lib/puppet/util/package/version/range/lt.rb +14 -0
  187. data/lib/puppet/util/package/version/range/lt_eq.rb +14 -0
  188. data/lib/puppet/util/package/version/range/min_max.rb +21 -0
  189. data/lib/puppet/util/package/version/range/simple.rb +11 -0
  190. data/lib/puppet/util/package/version/rpm.rb +73 -0
  191. data/lib/puppet/util/pidlock.rb +36 -10
  192. data/lib/puppet/util/platform.rb +5 -0
  193. data/lib/puppet/util/plist.rb +6 -0
  194. data/lib/puppet/util/rpm_compare.rb +193 -0
  195. data/lib/puppet/util/storage.rb +0 -1
  196. data/lib/puppet/util/windows/adsi.rb +50 -20
  197. data/lib/puppet/util/windows/process.rb +15 -14
  198. data/lib/puppet/util/windows/security.rb +1 -0
  199. data/lib/puppet/util/windows/sid.rb +3 -3
  200. data/lib/puppet/util/yaml.rb +1 -1
  201. data/lib/puppet/version.rb +1 -1
  202. data/lib/puppet/x509/cert_provider.rb +9 -5
  203. data/locales/puppet.pot +640 -521
  204. data/man/man5/puppet.conf.5 +88 -9
  205. data/man/man8/puppet-agent.8 +6 -6
  206. data/man/man8/puppet-apply.8 +1 -1
  207. data/man/man8/puppet-catalog.8 +1 -1
  208. data/man/man8/puppet-config.8 +1 -1
  209. data/man/man8/puppet-describe.8 +1 -1
  210. data/man/man8/puppet-device.8 +2 -2
  211. data/man/man8/puppet-doc.8 +1 -1
  212. data/man/man8/puppet-epp.8 +1 -1
  213. data/man/man8/puppet-facts.8 +1 -1
  214. data/man/man8/puppet-filebucket.8 +17 -2
  215. data/man/man8/puppet-generate.8 +1 -1
  216. data/man/man8/puppet-help.8 +6 -3
  217. data/man/man8/puppet-key.8 +1 -1
  218. data/man/man8/puppet-lookup.8 +1 -1
  219. data/man/man8/puppet-man.8 +1 -1
  220. data/man/man8/puppet-module.8 +4 -1
  221. data/man/man8/puppet-node.8 +1 -1
  222. data/man/man8/puppet-parser.8 +1 -1
  223. data/man/man8/puppet-plugin.8 +1 -1
  224. data/man/man8/puppet-report.8 +1 -1
  225. data/man/man8/puppet-resource.8 +1 -1
  226. data/man/man8/puppet-script.8 +1 -1
  227. data/man/man8/puppet-ssl.8 +2 -2
  228. data/man/man8/puppet-status.8 +1 -1
  229. data/man/man8/puppet.8 +2 -2
  230. data/spec/fixtures/ssl/unknown-127.0.0.1-key.pem +67 -0
  231. data/spec/fixtures/ssl/unknown-127.0.0.1.pem +48 -0
  232. data/spec/fixtures/ssl/unknown-ca-key.pem +67 -0
  233. data/spec/fixtures/ssl/unknown-ca.pem +59 -0
  234. data/spec/fixtures/unit/forge/bacula.json +76 -0
  235. data/spec/fixtures/unit/provider/package/dnfmodule/{dnf-module-list-installed.txt → dnf-module-list.txt} +8 -0
  236. data/spec/fixtures/unit/provider/package/pkgng/pkg.version +2 -0
  237. data/spec/fixtures/unit/provider/package/yum/yum-check-update-subscription-manager.txt +9 -0
  238. data/spec/fixtures/unit/provider/package/zypper/zypper-search-uninstalled.out +13 -0
  239. data/spec/fixtures/unit/provider/service/systemd/list_unit_files_services +9 -0
  240. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_fetch_if_not_on_the_local_disk.yml +1 -102
  241. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_not_update_if_content_on_disk_is_up-to-date.yml +1 -106
  242. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_md5/should_update_if_content_differs_on_disk.yml +1 -106
  243. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_mtime_is_older_on_disk.yml +1 -102
  244. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_no_header_specified.yml +1 -98
  245. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_fetch_if_not_on_the_local_disk.yml +1 -102
  246. data/spec/fixtures/vcr/cassettes/Puppet_Type_File/when_sourcing/from_http/using_mtime/should_not_update_if_mtime_is_newer_on_disk.yml +1 -102
  247. data/spec/integration/application/agent_spec.rb +394 -0
  248. data/spec/integration/application/apply_spec.rb +132 -3
  249. data/spec/integration/application/filebucket_spec.rb +190 -0
  250. data/spec/integration/application/plugin_spec.rb +73 -0
  251. data/spec/integration/configurer_spec.rb +26 -7
  252. data/spec/integration/http/client_spec.rb +154 -0
  253. data/spec/integration/indirector/facts/facter_spec.rb +4 -0
  254. data/spec/integration/indirector/report/yaml.rb +83 -0
  255. data/spec/integration/module_tool/forge_spec.rb +51 -0
  256. data/spec/integration/network/http_pool_spec.rb +76 -20
  257. data/spec/integration/node/environment_spec.rb +15 -0
  258. data/spec/integration/util/windows/adsi_spec.rb +6 -1
  259. data/spec/lib/puppet/test_ca.rb +2 -2
  260. data/spec/lib/puppet_spec/https.rb +20 -9
  261. data/spec/lib/puppet_spec/puppetserver.rb +119 -0
  262. data/spec/shared_contexts/https.rb +29 -0
  263. data/spec/spec_helper.rb +6 -2
  264. data/spec/unit/agent_spec.rb +80 -26
  265. data/spec/unit/application/agent_spec.rb +9 -5
  266. data/spec/unit/application/apply_spec.rb +2 -12
  267. data/spec/unit/application/describe_spec.rb +88 -50
  268. data/spec/unit/application/device_spec.rb +2 -2
  269. data/spec/unit/application/filebucket_spec.rb +22 -2
  270. data/spec/unit/application/resource_spec.rb +2 -2
  271. data/spec/unit/concurrent/lock_spec.rb +29 -0
  272. data/spec/unit/configurer/fact_handler_spec.rb +0 -4
  273. data/spec/unit/configurer/plugin_handler_spec.rb +36 -19
  274. data/spec/unit/configurer_spec.rb +400 -406
  275. data/spec/unit/context/trusted_information_spec.rb +17 -0
  276. data/spec/unit/daemon_spec.rb +5 -64
  277. data/spec/unit/defaults_spec.rb +38 -4
  278. data/spec/unit/environments_spec.rb +65 -28
  279. data/spec/unit/face/facts_spec.rb +24 -20
  280. data/spec/unit/face/module/search_spec.rb +17 -0
  281. data/spec/unit/face/plugin_spec.rb +12 -10
  282. data/spec/unit/file_system/uniquefile_spec.rb +11 -0
  283. data/spec/unit/file_system_spec.rb +26 -2
  284. data/spec/unit/forge/errors_spec.rb +1 -1
  285. data/spec/unit/forge/forge_spec.rb +12 -54
  286. data/spec/unit/forge/module_release_spec.rb +19 -6
  287. data/spec/unit/forge/repository_spec.rb +63 -157
  288. data/spec/unit/forge_spec.rb +46 -116
  289. data/spec/unit/functions/find_template_spec.rb +69 -0
  290. data/spec/unit/functions/lookup_spec.rb +13 -0
  291. data/spec/unit/http/client_spec.rb +395 -27
  292. data/spec/unit/http/external_client_spec.rb +201 -0
  293. data/spec/unit/http/resolver_spec.rb +81 -12
  294. data/spec/unit/http/response_spec.rb +69 -0
  295. data/spec/unit/http/service/ca_spec.rb +100 -7
  296. data/spec/unit/http/service/compiler_spec.rb +627 -0
  297. data/spec/unit/http/service/file_server_spec.rb +308 -0
  298. data/spec/unit/http/service/report_spec.rb +118 -0
  299. data/spec/unit/http/service_spec.rb +117 -4
  300. data/spec/unit/http/session_spec.rb +237 -19
  301. data/spec/unit/indirector/catalog/compiler_spec.rb +47 -29
  302. data/spec/unit/indirector/catalog/rest_spec.rb +59 -2
  303. data/spec/unit/indirector/facts/rest_spec.rb +79 -24
  304. data/spec/unit/indirector/file_bucket_file/rest_spec.rb +82 -2
  305. data/spec/unit/indirector/file_content/rest_spec.rb +53 -2
  306. data/spec/unit/indirector/file_metadata/http_spec.rb +167 -0
  307. data/spec/unit/indirector/file_metadata/rest_spec.rb +110 -2
  308. data/spec/unit/indirector/node/rest_spec.rb +57 -2
  309. data/spec/unit/indirector/report/rest_spec.rb +58 -51
  310. data/spec/unit/indirector/resource/ral_spec.rb +7 -8
  311. data/spec/unit/indirector/rest_spec.rb +13 -0
  312. data/spec/unit/indirector/status/rest_spec.rb +43 -2
  313. data/spec/unit/network/http/connection_spec.rb +549 -176
  314. data/spec/unit/network/http/nocache_pool_spec.rb +25 -3
  315. data/spec/unit/network/http/pool_spec.rb +89 -11
  316. data/spec/unit/network/http_pool_spec.rb +63 -57
  317. data/spec/unit/network/http_spec.rb +1 -1
  318. data/spec/unit/node/environment_spec.rb +16 -0
  319. data/spec/unit/node/facts_spec.rb +2 -1
  320. data/spec/unit/node_spec.rb +7 -4
  321. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +8 -3
  322. data/spec/unit/pops/serialization/to_from_hr_spec.rb +6 -1
  323. data/spec/unit/pops/validator/validator_spec.rb +7 -2
  324. data/spec/unit/provider/aix_object_spec.rb +16 -2
  325. data/spec/unit/provider/group/groupadd_spec.rb +181 -56
  326. data/spec/unit/provider/group/windows_adsi_spec.rb +43 -10
  327. data/spec/unit/provider/package/aix_spec.rb +29 -0
  328. data/spec/unit/provider/package/apt_spec.rb +43 -2
  329. data/spec/unit/provider/package/aptitude_spec.rb +1 -0
  330. data/spec/unit/provider/package/dnfmodule_spec.rb +76 -15
  331. data/spec/unit/provider/package/dpkg_spec.rb +28 -6
  332. data/spec/unit/provider/package/gem_spec.rb +40 -0
  333. data/spec/unit/provider/package/openbsd_spec.rb +17 -0
  334. data/spec/unit/provider/package/pacman_spec.rb +6 -21
  335. data/spec/unit/provider/package/pip_spec.rb +68 -19
  336. data/spec/unit/provider/package/pkg_spec.rb +15 -1
  337. data/spec/unit/provider/package/pkgdmg_spec.rb +1 -1
  338. data/spec/unit/provider/package/pkgng_spec.rb +38 -0
  339. data/spec/unit/provider/package/portage_spec.rb +9 -4
  340. data/spec/unit/provider/package/puppet_gem_spec.rb +8 -0
  341. data/spec/unit/provider/package/rpm_spec.rb +0 -212
  342. data/spec/unit/provider/package/yum_spec.rb +292 -0
  343. data/spec/unit/provider/package/zypper_spec.rb +84 -0
  344. data/spec/unit/provider/package_targetable_spec.rb +60 -0
  345. data/spec/unit/provider/service/init_spec.rb +1 -0
  346. data/spec/unit/provider/service/openbsd_spec.rb +9 -0
  347. data/spec/unit/provider/service/openwrt_spec.rb +1 -0
  348. data/spec/unit/provider/service/redhat_spec.rb +9 -0
  349. data/spec/unit/provider/service/systemd_spec.rb +92 -12
  350. data/spec/unit/provider/user/directoryservice_spec.rb +41 -0
  351. data/spec/unit/provider/user/hpux_spec.rb +2 -2
  352. data/spec/unit/provider/user/useradd_spec.rb +21 -8
  353. data/spec/unit/provider/user/windows_adsi_spec.rb +3 -3
  354. data/spec/unit/puppet_pal_2pec.rb +0 -26
  355. data/spec/unit/puppet_pal_catalog_spec.rb +46 -0
  356. data/spec/unit/puppet_spec.rb +47 -0
  357. data/spec/unit/reports/http_spec.rb +70 -52
  358. data/spec/unit/settings/autosign_setting_spec.rb +1 -1
  359. data/spec/unit/settings/http_extra_headers_spec.rb +64 -0
  360. data/spec/unit/ssl/certificate_spec.rb +7 -0
  361. data/spec/unit/ssl/host_spec.rb +4 -2
  362. data/spec/unit/ssl/oids_spec.rb +1 -0
  363. data/spec/unit/ssl/ssl_provider_spec.rb +71 -0
  364. data/spec/unit/ssl/state_machine_spec.rb +99 -13
  365. data/spec/unit/transaction/persistence_spec.rb +1 -10
  366. data/spec/unit/transaction/report_spec.rb +4 -0
  367. data/spec/unit/transaction_spec.rb +45 -1
  368. data/spec/unit/type/file/content_spec.rb +9 -3
  369. data/spec/unit/type/file/ensure_spec.rb +1 -2
  370. data/spec/unit/type/file/source_spec.rb +86 -35
  371. data/spec/unit/type/package_spec.rb +8 -0
  372. data/spec/unit/type/service_spec.rb +9 -8
  373. data/spec/unit/type/user_spec.rb +1 -2
  374. data/spec/unit/util/at_fork_spec.rb +3 -2
  375. data/spec/unit/util/autoload_spec.rb +2 -1
  376. data/spec/unit/util/log/destinations_spec.rb +1 -29
  377. data/spec/unit/util/log_spec.rb +0 -138
  378. data/spec/unit/util/logging_spec.rb +200 -0
  379. data/spec/unit/util/package/version/debian_spec.rb +83 -0
  380. data/spec/unit/util/package/version/pip_spec.rb +464 -0
  381. data/spec/unit/util/package/version/range_spec.rb +175 -0
  382. data/spec/unit/util/package/version/rpm_spec.rb +121 -0
  383. data/spec/unit/util/pidlock_spec.rb +112 -42
  384. data/spec/unit/util/plist_spec.rb +20 -0
  385. data/spec/unit/util/rpm_compare_spec.rb +196 -0
  386. data/spec/unit/util/storage_spec.rb +1 -8
  387. data/spec/unit/util/windows/adsi_spec.rb +55 -4
  388. data/spec/unit/util/windows/sid_spec.rb +2 -2
  389. data/spec/unit/x509/cert_provider_spec.rb +24 -4
  390. data/tasks/generate_cert_fixtures.rake +15 -1
  391. data/tasks/manpages.rake +6 -35
  392. metadata +92 -12
  393. data/COMMITTERS.md +0 -244
  394. data/spec/integration/faces/plugin_spec.rb +0 -61
  395. data/spec/lib/puppet_spec/validators.rb +0 -37
@@ -1,275 +1,648 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet/network/http/connection'
3
- require 'puppet_spec/validators'
3
+ require 'puppet/network/http/connection_adapter'
4
4
  require 'puppet/test_ca'
5
5
 
6
6
  describe Puppet::Network::HTTP::Connection do
7
- let (:host) { "me.example.com" }
8
- let (:port) { 8140 }
9
- let (:url) { "https://#{host}:#{port}/foo" }
7
+ let(:host) { "me.example.com" }
8
+ let(:port) { 8140 }
9
+ let(:path) { '/foo' }
10
+ let(:url) { "https://#{host}:#{port}#{path}" }
10
11
 
11
- subject { Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator) }
12
+ shared_examples_for "an HTTP connection" do |klass, legacy_api|
13
+ subject { klass.new(host, port, :verify => Puppet::SSL::Validator.no_validator) }
12
14
 
13
- context "when providing HTTP connections" do
14
- context "when initializing http instances" do
15
- it "should return an http instance created with the passed host and port" do
16
- conn = Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator)
15
+ context "when providing HTTP connections" do
16
+ context "when initializing http instances" do
17
+ it "should return an http instance created with the passed host and port" do
18
+ conn = klass.new(host, port, :verify => Puppet::SSL::Validator.no_validator)
17
19
 
18
- expect(conn.address).to eq(host)
19
- expect(conn.port).to eq(port)
20
+ expect(conn.address).to eq(host)
21
+ expect(conn.port).to eq(port)
22
+ end
23
+
24
+ it "should enable ssl on the http instance by default" do
25
+ conn = klass.new(host, port, :verify => Puppet::SSL::Validator.no_validator)
26
+
27
+ expect(conn).to be_use_ssl
28
+ end
29
+
30
+ it "can disable ssl using an option and ignore the verify" do
31
+ conn = klass.new(host, port, :use_ssl => false)
32
+
33
+ expect(conn).to_not be_use_ssl
34
+ end
35
+
36
+ it "can enable ssl using an option" do
37
+ conn = klass.new(host, port, :use_ssl => true, :verify => Puppet::SSL::Validator.no_validator)
38
+
39
+ expect(conn).to be_use_ssl
40
+ end
41
+
42
+ it "ignores the ':verify' option when ssl is disabled" do
43
+ conn = klass.new(host, port, :use_ssl => false, :verify => Puppet::SSL::Validator.no_validator)
44
+
45
+ expect(conn.verifier).to be_nil
46
+ end
47
+
48
+ it "wraps the validator in an adapter" do
49
+ conn = klass.new(host, port, :verify => Puppet::SSL::Validator.no_validator)
50
+
51
+ expect(conn.verifier).to be_a_kind_of(Puppet::SSL::VerifierAdapter)
52
+ end
53
+
54
+ it "should raise Puppet::Error when invalid options are specified" do
55
+ expect { klass.new(host, port, :invalid_option => nil) }.to raise_error(Puppet::Error, 'Unrecognized option(s): :invalid_option')
56
+ end
57
+
58
+ it "accepts a verifier" do
59
+ verifier = Puppet::SSL::Verifier.new(host, double('ssl_context'))
60
+ conn = klass.new(host, port, :use_ssl => true, :verifier => verifier)
61
+
62
+ expect(conn.verifier).to eq(verifier)
63
+ end
64
+
65
+ it "raises if the wrong verifier class is specified" do
66
+ expect {
67
+ klass.new(host, port, :verifier => Puppet::SSL::Validator.default_validator)
68
+ }.to raise_error(ArgumentError,
69
+ "Expected an instance of Puppet::SSL::Verifier but was passed a Puppet::SSL::Validator::DefaultValidator")
70
+ end
20
71
  end
72
+ end
21
73
 
22
- it "should enable ssl on the http instance by default" do
23
- conn = Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator)
74
+ context "for streaming GET requests" do
75
+ it 'yields the response' do
76
+ stub_request(:get, url)
24
77
 
25
- expect(conn).to be_use_ssl
78
+ expect { |b|
79
+ subject.request_get('/foo', {}, &b)
80
+ }.to yield_with_args(Net::HTTPResponse)
26
81
  end
27
82
 
28
- it "can disable ssl using an option and ignore the verify" do
29
- conn = Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false)
83
+ it "stringifies keys and encodes values in the query" do
84
+ stub_request(:get, url).with(query: "foo=bar%3Dbaz")
30
85
 
31
- expect(conn).to_not be_use_ssl
86
+ subject.request_get("#{path}?foo=bar=baz") { |_| }
32
87
  end
33
88
 
34
- it "can enable ssl using an option" do
35
- conn = Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => true, :verify => Puppet::SSL::Validator.no_validator)
89
+ it "merges custom headers with default ones" do
90
+ stub_request(:get, url).with(headers: { 'X-Foo' => 'Bar', 'User-Agent' => /./ })
36
91
 
37
- expect(conn).to be_use_ssl
92
+ subject.request_get(path, {'X-Foo' => 'Bar'}) { |_| }
38
93
  end
39
94
 
40
- it "ignores the ':verify' option when ssl is disabled" do
41
- conn = Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => false, :verify => Puppet::SSL::Validator.no_validator)
95
+ it "returns the response" do
96
+ stub_request(:get, url)
42
97
 
43
- expect(conn.verifier).to be_nil
98
+ response = subject.request_get(path) { |_| }
99
+ expect(response).to be_an_instance_of(Net::HTTPOK)
100
+ expect(response.code).to eq("200")
44
101
  end
45
102
 
46
- it "wraps the validator in an adapter" do
47
- conn = Puppet::Network::HTTP::Connection.new(host, port, :verify => Puppet::SSL::Validator.no_validator)
103
+ it "accepts a URL string as the path" do
104
+ stub_request(:get, url)
48
105
 
49
- expect(conn.verifier).to be_a_kind_of(Puppet::SSL::VerifierAdapter)
106
+ response = subject.request_get(url) { |_| }
107
+ expect(response).to be_an_instance_of(Net::HTTPOK)
50
108
  end
109
+ end
51
110
 
52
- it "should raise Puppet::Error when invalid options are specified" do
53
- expect { Puppet::Network::HTTP::Connection.new(host, port, :invalid_option => nil) }.to raise_error(Puppet::Error, 'Unrecognized option(s): :invalid_option')
111
+ context "for streaming head requests" do
112
+ it 'yields the response when request_head is called' do
113
+ stub_request(:head, url)
114
+
115
+ expect { |b|
116
+ subject.request_head('/foo', {}, &b)
117
+ }.to yield_with_args(Net::HTTPResponse)
54
118
  end
55
119
 
56
- it "accepts a verifier" do
57
- verifier = Puppet::SSL::Verifier.new('fqdn', double('ssl_context'))
58
- conn = Puppet::Network::HTTP::Connection.new(host, port, :use_ssl => true, :verifier => verifier)
120
+ it "stringifies keys and encodes values in the query" do
121
+ stub_request(:head, url).with(query: "foo=bar%3Dbaz")
59
122
 
60
- expect(conn.verifier).to eq(verifier)
123
+ subject.request_head("#{path}?foo=bar=baz") { |_| }
61
124
  end
62
125
 
63
- it "raises if the wrong verifier class is specified" do
64
- expect {
65
- Puppet::Network::HTTP::Connection.new(host, port, :verifier => Puppet::SSL::Validator.default_validator)
66
- }.to raise_error(ArgumentError,
67
- "Expected an instance of Puppet::SSL::Verifier but was passed a Puppet::SSL::Validator::DefaultValidator")
126
+ it "merges custom headers with default ones" do
127
+ stub_request(:head, url).with(headers: { 'X-Foo' => 'Bar', 'User-Agent' => /./ })
128
+
129
+ subject.request_head(path, {'X-Foo' => 'Bar'}) { |_| }
68
130
  end
69
- end
70
- end
71
131
 
72
- context "when handling requests" do
73
- it 'yields the response when request_get is called' do
74
- stub_request(:get, url)
132
+ it "returns the response" do
133
+ stub_request(:head, url)
75
134
 
76
- expect { |b|
77
- subject.request_get('/foo', {}, &b)
78
- }.to yield_with_args(Net::HTTPResponse)
79
- end
135
+ response = subject.request_head(path) { |_| }
136
+ expect(response).to be_an_instance_of(Net::HTTPOK)
137
+ expect(response.code).to eq("200")
138
+ end
80
139
 
81
- it 'yields the response when request_head is called' do
82
- stub_request(:head, url)
140
+ it "accepts a URL string as the path" do
141
+ stub_request(:head, url)
83
142
 
84
- expect { |b|
85
- subject.request_head('/foo', {}, &b)
86
- }.to yield_with_args(Net::HTTPResponse)
143
+ response = subject.request_head(url) { |_| }
144
+ expect(response).to be_an_instance_of(Net::HTTPOK)
145
+ end
87
146
  end
88
147
 
89
- it 'yields the response when request_post is called' do
90
- stub_request(:post, url)
148
+ context "for streaming post requests" do
149
+ it 'yields the response when request_post is called' do
150
+ stub_request(:post, url)
91
151
 
92
- expect { |b|
93
- subject.request_post('/foo', "param: value", &b)
94
- }.to yield_with_args(Net::HTTPResponse)
95
- end
96
- end
152
+ expect { |b|
153
+ subject.request_post('/foo', "param: value", &b)
154
+ }.to yield_with_args(Net::HTTPResponse)
155
+ end
97
156
 
98
- context "when response is a redirect" do
99
- def create_connection(options = {})
100
- options[:use_ssl] = false
101
- options[:verify] = Puppet::SSL::Validator.no_validator
102
- Puppet::Network::HTTP::Connection.new(host, port, options)
103
- end
157
+ it "stringifies keys and encodes values in the query" do
158
+ stub_request(:post, url).with(query: "foo=bar%3Dbaz")
104
159
 
105
- def redirect_to(url)
106
- { status: 302, headers: { 'Location' => url } }
107
- end
160
+ subject.request_post("#{path}?foo=bar=baz", "") { |_| }
161
+ end
108
162
 
109
- it "should follow the redirect to the final resource location" do
110
- stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
111
- stub_request(:get, "http://me.example.com:8140/bar").to_return(status: 200)
163
+ it "merges custom headers with default ones" do
164
+ stub_request(:post, url).with(headers: { 'X-Foo' => 'Bar', 'User-Agent' => /./ })
112
165
 
113
- create_connection.get('/foo')
114
- end
166
+ subject.request_post(path, "", {'X-Foo' => 'Bar'}) { |_| }
167
+ end
115
168
 
116
- def expects_limit_exceeded(conn)
117
- expect {
118
- conn.get('/')
119
- }.to raise_error(Puppet::Network::HTTP::RedirectionLimitExceededException)
120
- end
169
+ it "returns the response" do
170
+ stub_request(:post, url)
171
+
172
+ response = subject.request_post(path, "") { |_| }
173
+ expect(response).to be_an_instance_of(Net::HTTPOK)
174
+ expect(response.code).to eq("200")
175
+ end
121
176
 
122
- it "should not follow any redirects when the limit is 0" do
123
- stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
177
+ it "accepts a URL string as the path" do
178
+ stub_request(:post, url)
124
179
 
125
- conn = create_connection(:redirect_limit => 0)
126
- expects_limit_exceeded(conn)
180
+ response = subject.request_post(url, "") { |_| }
181
+ expect(response).to be_an_instance_of(Net::HTTPOK)
182
+ end
127
183
  end
128
184
 
129
- it "should follow the redirect once" do
130
- stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
131
- stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
185
+ context "for GET requests" do
186
+ it "includes default HTTP headers" do
187
+ stub_request(:get, url).with(headers: {'User-Agent' => /./})
132
188
 
133
- conn = create_connection(:redirect_limit => 1)
134
- expects_limit_exceeded(conn)
135
- end
189
+ subject.get(path)
190
+ end
136
191
 
137
- it "should raise an exception when the redirect limit is exceeded" do
138
- stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
139
- stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
140
- stub_request(:get, "http://me.example.com:8140/bar").to_return(redirect_to("http://me.example.com:8140/baz"))
141
- stub_request(:get, "http://me.example.com:8140/baz").to_return(redirect_to("http://me.example.com:8140/qux"))
192
+ it "stringifies keys and encodes values in the query" do
193
+ stub_request(:get, url).with(query: "foo=bar%3Dbaz")
142
194
 
143
- conn = create_connection(:redirect_limit => 3)
144
- expects_limit_exceeded(conn)
145
- end
146
- end
195
+ subject.get("#{path}?foo=bar=baz")
196
+ end
147
197
 
148
- context "when response indicates an overloaded server" do
149
- def retry_after(datetime)
150
- stub_request(:get, url)
151
- .to_return(status: [503, 'Service Unavailable'], headers: {'Retry-After' => datetime}).then
152
- .to_return(status: 200)
153
- end
198
+ it "merges custom headers with default ones" do
199
+ stub_request(:get, url).with(headers: { 'X-Foo' => 'Bar', 'User-Agent' => /./ })
154
200
 
155
- it "should return a 503 response if Retry-After is not set" do
156
- stub_request(:get, url).to_return(status: [503, 'Service Unavailable'])
201
+ subject.get(path, {'X-Foo' => 'Bar'})
202
+ end
157
203
 
158
- result = subject.get('/foo')
159
- expect(result.code).to eq("503")
160
- end
204
+ it "returns the response" do
205
+ stub_request(:get, url)
161
206
 
162
- it "should return a 503 response if Retry-After is not convertible to an Integer or RFC 2822 Date" do
163
- stub_request(:get, url).to_return(status: [503, 'Service Unavailable'], headers: {'Retry-After' => 'foo'})
207
+ response = subject.get(path)
208
+ expect(response).to be_an_instance_of(Net::HTTPOK)
209
+ expect(response.code).to eq("200")
210
+ end
164
211
 
165
- result = subject.get('/foo')
166
- expect(result.code).to eq("503")
167
- end
212
+ it "returns the entire response body" do
213
+ stub_request(:get, url).to_return(body: "abc")
168
214
 
169
- it "should sleep and retry if Retry-After is an Integer" do
170
- retry_after('42')
215
+ response = subject.get(path)
216
+ expect(response.body).to eq("abc")
217
+ end
171
218
 
172
- expect(::Kernel).to receive(:sleep).with(42)
219
+ it "accepts a URL string as the path" do
220
+ stub_request(:get, url)
173
221
 
174
- result = subject.get('/foo')
175
- expect(result.code).to eq("200")
222
+ response = subject.get(url)
223
+ expect(response).to be_an_instance_of(Net::HTTPOK)
224
+ end
176
225
  end
177
226
 
178
- it "should sleep and retry if Retry-After is an RFC 2822 Date" do
179
- retry_after('Wed, 13 Apr 2005 15:18:05 GMT')
227
+ context "for HEAD requests" do
228
+ it "includes default HTTP headers" do
229
+ stub_request(:head, url).with(headers: {'User-Agent' => /./})
230
+
231
+ subject.head(path)
232
+ end
180
233
 
181
- now = DateTime.new(2005, 4, 13, 8, 17, 5, '-07:00')
182
- allow(DateTime).to receive(:now).and_return(now)
234
+ it "stringifies keys and encodes values in the query" do
235
+ stub_request(:head, url).with(query: "foo=bar%3Dbaz")
183
236
 
184
- expect(::Kernel).to receive(:sleep).with(60)
237
+ subject.head("#{path}?foo=bar=baz")
238
+ end
185
239
 
186
- result = subject.get('/foo')
187
- expect(result.code).to eq("200")
188
- end
240
+ it "merges custom headers with default ones" do
241
+ stub_request(:head, url).with(headers: { 'X-Foo' => 'Bar', 'User-Agent' => /./ })
189
242
 
190
- it "should sleep for no more than the Puppet runinterval" do
191
- retry_after('60')
192
- Puppet[:runinterval] = 30
243
+ subject.head(path, {'X-Foo' => 'Bar'})
244
+ end
193
245
 
194
- expect(::Kernel).to receive(:sleep).with(30)
246
+ it "returns the response" do
247
+ stub_request(:head, url)
195
248
 
196
- subject.get('/foo')
249
+ response = subject.head(path)
250
+ expect(response).to be_an_instance_of(Net::HTTPOK)
251
+ expect(response.code).to eq("200")
252
+ end
253
+
254
+ it "accepts a URL string as the path" do
255
+ stub_request(:head, url)
256
+
257
+ response = subject.head(url)
258
+ expect(response).to be_an_instance_of(Net::HTTPOK)
259
+ end
197
260
  end
198
261
 
199
- it "should sleep for 0 seconds if the RFC 2822 date has past" do
200
- retry_after('Wed, 13 Apr 2005 15:18:05 GMT')
262
+ context "for PUT requests" do
263
+ it "includes default HTTP headers" do
264
+ stub_request(:put, url).with(headers: {'User-Agent' => /./})
201
265
 
202
- expect(::Kernel).to receive(:sleep).with(0)
266
+ subject.put(path, "", {'Content-Type' => 'text/plain'})
267
+ end
203
268
 
204
- subject.get('/foo')
205
- end
206
- end
269
+ it "stringifies keys and encodes values in the query" do
270
+ stub_request(:put, url).with(query: "foo=bar%3Dbaz")
207
271
 
208
- context "basic auth" do
209
- let(:auth) { { :user => 'user', :password => 'password' } }
210
- let(:creds) { [ 'user', 'password'] }
272
+ subject.put("#{path}?foo=bar=baz", "")
273
+ end
274
+
275
+ it "includes custom headers" do
276
+ stub_request(:put, url).with(headers: { 'X-Foo' => 'Bar' })
277
+
278
+ subject.put(path, "", {'X-Foo' => 'Bar', 'Content-Type' => 'text/plain'})
279
+ end
280
+
281
+ it "returns the response" do
282
+ stub_request(:put, url)
283
+
284
+ response = subject.put(path, "", {'Content-Type' => 'text/plain'})
285
+ expect(response).to be_an_instance_of(Net::HTTPOK)
286
+ expect(response.code).to eq("200")
287
+ end
288
+
289
+ it "sets content-type for the body" do
290
+ stub_request(:put, url).with(headers: {"Content-Type" => "text/plain"})
291
+
292
+ subject.put(path, "hello", {'Content-Type' => 'text/plain'})
293
+ end
294
+
295
+ it 'sends an empty body' do
296
+ stub_request(:put, url).with(body: '')
211
297
 
212
- it "is allowed in get requests" do
213
- stub_request(:get, url).with(basic_auth: creds)
298
+ subject.put(path, nil)
299
+ end
214
300
 
215
- subject.get('/foo', nil, :basic_auth => auth)
301
+ it 'defaults content-type to application/x-www-form-urlencoded' do
302
+ skip("Net::HTTP sends a default content-type header, but it's not visible to webmock") if legacy_api
303
+
304
+ stub_request(:put, url).with(headers: {'Content-Type' => 'application/x-www-form-urlencoded'})
305
+
306
+ subject.put(path, '')
307
+ end
308
+
309
+ it "accepts a URL string as the path" do
310
+ stub_request(:put, url)
311
+
312
+ response = subject.put(url, '')
313
+ expect(response).to be_an_instance_of(Net::HTTPOK)
314
+ end
216
315
  end
217
316
 
218
- it "is allowed in post requests" do
219
- stub_request(:post, url).with(basic_auth: creds)
317
+ context "for POST requests" do
318
+ it "includes default HTTP headers" do
319
+ stub_request(:post, url).with(headers: {'User-Agent' => /./})
320
+
321
+ subject.post(path, "", {'Content-Type' => 'text/plain'})
322
+ end
323
+
324
+ it "stringifies keys and encodes values in the query" do
325
+ stub_request(:post, url).with(query: "foo=bar%3Dbaz")
326
+
327
+ subject.post("#{path}?foo=bar=baz", "", {'Content-Type' => 'text/plain'})
328
+ end
329
+
330
+ it "includes custom headers" do
331
+ stub_request(:post, url).with(headers: { 'X-Foo' => 'Bar' })
332
+
333
+ subject.post(path, "", {'X-Foo' => 'Bar', 'Content-Type' => 'text/plain'})
334
+ end
335
+
336
+ it "returns the response" do
337
+ stub_request(:post, url)
338
+
339
+ response = subject.post(path, "", {'Content-Type' => 'text/plain'})
340
+ expect(response).to be_an_instance_of(Net::HTTPOK)
341
+ expect(response.code).to eq("200")
342
+ end
343
+
344
+ it "sets content-type for the body" do
345
+ stub_request(:post, url).with(headers: {"Content-Type" => "text/plain"})
346
+
347
+ subject.post(path, "hello", {'Content-Type' => 'text/plain'})
348
+ end
349
+
350
+ it 'sends an empty body' do
351
+ stub_request(:post, url).with(body: '')
352
+
353
+ subject.post(path, nil)
354
+ end
355
+
356
+ it 'defaults content-type to application/x-www-form-urlencoded' do
357
+ skip("Net::HTTP sends a default content-type header, but it's not visible to webmock") if legacy_api
220
358
 
221
- subject.post('/foo', 'data', nil, :basic_auth => auth)
359
+ stub_request(:post, url).with(headers: {'Content-Type' => 'application/x-www-form-urlencoded'})
360
+
361
+ subject.post(path, "")
362
+ end
363
+
364
+ it "accepts a URL string as the path" do
365
+ stub_request(:post, url)
366
+
367
+ response = subject.post(url, '')
368
+ expect(response).to be_an_instance_of(Net::HTTPOK)
369
+ end
222
370
  end
223
371
 
224
- it "is allowed in head requests" do
225
- stub_request(:head, url).with(basic_auth: creds)
372
+ context "for DELETE requests" do
373
+ it "includes default HTTP headers" do
374
+ stub_request(:delete, url).with(headers: {'User-Agent' => /./})
375
+
376
+ subject.delete(path)
377
+ end
378
+
379
+ it "merges custom headers with default ones" do
380
+ stub_request(:delete, url).with(headers: { 'X-Foo' => 'Bar', 'User-Agent' => /./ })
381
+
382
+ subject.delete(path, {'X-Foo' => 'Bar'})
383
+ end
384
+
385
+ it "stringifies keys and encodes values in the query" do
386
+ stub_request(:delete, url).with(query: "foo=bar%3Dbaz")
387
+
388
+ subject.delete("#{path}?foo=bar=baz")
389
+ end
226
390
 
227
- subject.head('/foo', nil, :basic_auth => auth)
391
+ it "returns the response" do
392
+ stub_request(:delete, url)
393
+
394
+ response = subject.delete(path)
395
+ expect(response).to be_an_instance_of(Net::HTTPOK)
396
+ expect(response.code).to eq("200")
397
+ end
398
+
399
+ it "returns the entire response body" do
400
+ stub_request(:delete, url).to_return(body: "abc")
401
+
402
+ expect(subject.delete(path).body).to eq("abc")
403
+ end
404
+
405
+ it "accepts a URL string as the path" do
406
+ stub_request(:delete, url)
407
+
408
+ response = subject.delete(url)
409
+ expect(response).to be_an_instance_of(Net::HTTPOK)
410
+ end
228
411
  end
229
412
 
230
- it "is allowed in delete requests" do
231
- stub_request(:delete, url).with(basic_auth: creds)
413
+ context "when response is a redirect" do
414
+ subject { klass }
415
+
416
+ def create_connection(options = {})
417
+ options[:use_ssl] = false
418
+ options[:verify] = Puppet::SSL::Validator.no_validator
419
+ subject.new(host, port, options)
420
+ end
421
+
422
+ def redirect_to(url)
423
+ { status: 302, headers: { 'Location' => url } }
424
+ end
232
425
 
233
- subject.delete('/foo', nil, :basic_auth => auth)
426
+ it "should follow the redirect to the final resource location" do
427
+ stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
428
+ stub_request(:get, "http://me.example.com:8140/bar").to_return(status: 200)
429
+
430
+ create_connection.get('/foo')
431
+ end
432
+
433
+ def expects_limit_exceeded(conn)
434
+ expect {
435
+ conn.get('/')
436
+ }.to raise_error(Puppet::Network::HTTP::RedirectionLimitExceededException)
437
+ end
438
+
439
+ it "should not follow any redirects when the limit is 0" do
440
+ stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
441
+
442
+ conn = create_connection(:redirect_limit => 0)
443
+ expects_limit_exceeded(conn)
444
+ end
445
+
446
+ it "should follow the redirect once" do
447
+ stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
448
+ stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
449
+
450
+ conn = create_connection(:redirect_limit => 1)
451
+ expects_limit_exceeded(conn)
452
+ end
453
+
454
+ it "should raise an exception when the redirect limit is exceeded" do
455
+ stub_request(:get, "http://me.example.com:8140/").to_return(redirect_to("http://me.example.com:8140/foo"))
456
+ stub_request(:get, "http://me.example.com:8140/foo").to_return(redirect_to("http://me.example.com:8140/bar"))
457
+ stub_request(:get, "http://me.example.com:8140/bar").to_return(redirect_to("http://me.example.com:8140/baz"))
458
+ stub_request(:get, "http://me.example.com:8140/baz").to_return(redirect_to("http://me.example.com:8140/qux"))
459
+
460
+ conn = create_connection(:redirect_limit => 3)
461
+ expects_limit_exceeded(conn)
462
+ end
463
+
464
+ it 'raises an exception when the location header is missing' do
465
+ stub_request(:get, "http://me.example.com:8140/").to_return(status: 302)
466
+
467
+ if legacy_api
468
+ expect {
469
+ create_connection.get('/')
470
+ }.to raise_error(URI::InvalidURIError, /bad URI/)
471
+ else
472
+ expect {
473
+ create_connection.get('/')
474
+ }.to raise_error(Puppet::HTTP::ProtocolError, /Location response header is missing/)
475
+ end
476
+ end
234
477
  end
235
478
 
236
- it "is allowed in put requests" do
237
- stub_request(:put, url).with(basic_auth: creds)
479
+ context "when response indicates an overloaded server" do
480
+ def retry_after(datetime)
481
+ stub_request(:get, url)
482
+ .to_return(status: [503, 'Service Unavailable'], headers: {'Retry-After' => datetime}).then
483
+ .to_return(status: 200)
484
+ end
485
+
486
+ it "should return a 503 response if Retry-After is not set" do
487
+ stub_request(:get, url).to_return(status: [503, 'Service Unavailable'])
488
+
489
+ result = subject.get('/foo')
490
+ expect(result.code).to eq("503")
491
+ end
492
+
493
+ it "should return a 503 response if Retry-After is not convertible to an Integer or RFC 2822 Date" do
494
+ retry_after('foo')
495
+
496
+ if legacy_api
497
+ result = subject.get('/foo')
498
+ expect(result.code).to eq("503")
499
+ else
500
+ expect {
501
+ subject.get('/foo')
502
+ }.to raise_error(Puppet::HTTP::ProtocolError, /Failed to parse Retry-After header 'foo'/)
503
+ end
504
+ end
505
+
506
+ it "should close the connection before sleeping" do
507
+ retry_after('42')
508
+
509
+ http1 = Net::HTTP.new(host, port)
510
+ http1.use_ssl = true
511
+ allow(http1).to receive(:started?).and_return(true)
238
512
 
239
- subject.put('/foo', 'data', nil, :basic_auth => auth)
513
+ http2 = Net::HTTP.new(host, port)
514
+ http2.use_ssl = true
515
+ allow(http1).to receive(:started?).and_return(true)
516
+
517
+ # The "with_connection" method is required to yield started connections
518
+ pool = if legacy_api
519
+ Puppet.lookup(:http_pool)
520
+ else
521
+ Puppet.runtime[:http].pool
522
+ end
523
+
524
+ allow(pool).to receive(:with_connection).and_yield(http1).and_yield(http2)
525
+
526
+ expect(http1).to receive(:finish).ordered
527
+ expect(::Kernel).to receive(:sleep).with(42).ordered
528
+
529
+ subject.get('/foo')
530
+ end
531
+
532
+ it "should sleep and retry if Retry-After is an Integer" do
533
+ retry_after('42')
534
+
535
+ expect(::Kernel).to receive(:sleep).with(42)
536
+
537
+ result = subject.get('/foo')
538
+ expect(result.code).to eq("200")
539
+ end
540
+
541
+ it "should sleep and retry if Retry-After is an RFC 2822 Date" do
542
+ retry_after('Wed, 13 Apr 2005 15:18:05 GMT')
543
+
544
+ now = DateTime.new(2005, 4, 13, 8, 17, 5, '-07:00')
545
+ allow(DateTime).to receive(:now).and_return(now)
546
+
547
+ expect(::Kernel).to receive(:sleep).with(60)
548
+
549
+ result = subject.get('/foo')
550
+ expect(result.code).to eq("200")
551
+ end
552
+
553
+ it "should sleep for no more than the Puppet runinterval" do
554
+ retry_after('60')
555
+
556
+ Puppet[:runinterval] = 30
557
+
558
+ expect(::Kernel).to receive(:sleep).with(30)
559
+
560
+ subject.get('/foo')
561
+ end
562
+
563
+ it "should sleep for 0 seconds if the RFC 2822 date has past" do
564
+ retry_after('Wed, 13 Apr 2005 15:18:05 GMT')
565
+
566
+ expect(::Kernel).to receive(:sleep).with(0)
567
+
568
+ subject.get('/foo')
569
+ end
240
570
  end
241
- end
242
571
 
243
- it "sets HTTP User-Agent header" do
244
- puppet_ua = "Puppet/#{Puppet.version} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
245
- stub_request(:get, url).with(headers: { 'User-Agent' => puppet_ua })
572
+ context "basic auth" do
573
+ let(:auth) { { :user => 'user', :password => 'password' } }
574
+ let(:creds) { [ 'user', 'password'] }
246
575
 
247
- subject.get('/foo')
248
- end
576
+ it "is allowed in get requests" do
577
+ stub_request(:get, url).with(basic_auth: creds)
249
578
 
250
- describe 'connection request errors' do
251
- it "logs and raises generic http errors" do
252
- generic_error = Net::HTTPError.new('generic error', double("response"))
253
- stub_request(:get, url).to_raise(generic_error)
579
+ subject.get('/foo', nil, :basic_auth => auth)
580
+ end
581
+
582
+ it "is allowed in post requests" do
583
+ stub_request(:post, url).with(basic_auth: creds)
584
+
585
+ subject.post('/foo', 'data', nil, :basic_auth => auth)
586
+ end
587
+
588
+ it "is allowed in head requests" do
589
+ stub_request(:head, url).with(basic_auth: creds)
590
+
591
+ subject.head('/foo', nil, :basic_auth => auth)
592
+ end
593
+
594
+ it "is allowed in delete requests" do
595
+ stub_request(:delete, url).with(basic_auth: creds)
596
+
597
+ subject.delete('/foo', nil, :basic_auth => auth)
598
+ end
599
+
600
+ it "is allowed in put requests" do
601
+ stub_request(:put, url).with(basic_auth: creds)
254
602
 
255
- expect(Puppet).to receive(:log_exception).with(anything, /^.*failed: generic error$/)
256
- expect { subject.get('/foo') }.to raise_error(generic_error)
603
+ subject.put('/foo', 'data', nil, :basic_auth => auth)
604
+ end
257
605
  end
258
606
 
259
- it "logs and raises timeout errors" do
260
- timeout_error = Timeout::Error.new
261
- stub_request(:get, url).to_raise(timeout_error)
607
+ it "sets HTTP User-Agent header" do
608
+ puppet_ua = "Puppet/#{Puppet.version} Ruby/#{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} (#{RUBY_PLATFORM})"
609
+ stub_request(:get, url).with(headers: { 'User-Agent' => puppet_ua })
262
610
 
263
- expect(Puppet).to receive(:log_exception).with(anything, /^.*timed out after .* seconds$/)
264
- expect { subject.get('/foo') }.to raise_error(timeout_error)
611
+ subject.get('/foo')
265
612
  end
266
613
 
267
- it "logs and raises eof errors" do
268
- eof_error = EOFError
269
- stub_request(:get, url).to_raise(eof_error)
614
+ describe 'connection request errors' do
615
+ it "logs and raises generic http errors" do
616
+ generic_error = Net::HTTPError.new('generic error', double("response"))
617
+ stub_request(:get, url).to_raise(generic_error)
618
+
619
+ expect(Puppet).to receive(:log_exception).with(anything, /^.*failed.*: generic error$/)
620
+ expect { subject.get('/foo') }.to raise_error(generic_error)
621
+ end
622
+
623
+ it "logs and raises timeout errors" do
624
+ timeout_error = Net::OpenTimeout.new
625
+ stub_request(:get, url).to_raise(timeout_error)
626
+
627
+ expect(Puppet).to receive(:log_exception).with(anything, /^.*timed out .*after .* seconds/)
628
+ expect { subject.get('/foo') }.to raise_error(timeout_error)
629
+ end
630
+
631
+ it "logs and raises eof errors" do
632
+ eof_error = EOFError
633
+ stub_request(:get, url).to_raise(eof_error)
270
634
 
271
- expect(Puppet).to receive(:log_exception).with(anything, /^.*interrupted after .* seconds$/)
272
- expect { subject.get('/foo') }.to raise_error(eof_error)
635
+ expect(Puppet).to receive(:log_exception).with(anything, /^.*interrupted after .* seconds$/)
636
+ expect { subject.get('/foo') }.to raise_error(eof_error)
637
+ end
273
638
  end
274
639
  end
640
+
641
+ describe Puppet::Network::HTTP::Connection do
642
+ it_behaves_like "an HTTP connection", described_class, true
643
+ end
644
+
645
+ describe Puppet::Network::HTTP::ConnectionAdapter do
646
+ it_behaves_like "an HTTP connection", described_class, false
647
+ end
275
648
  end