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
@@ -14,14 +14,6 @@ describe Puppet::Application::Apply do
14
14
  Puppet[:reports] = "none"
15
15
  end
16
16
 
17
- after :each do
18
- Puppet::Node::Facts.indirection.reset_terminus_class
19
- Puppet::Node::Facts.indirection.cache_class = nil
20
-
21
- Puppet::Node.indirection.reset_terminus_class
22
- Puppet::Node.indirection.cache_class = nil
23
- end
24
-
25
17
  [:debug,:loadclasses,:test,:verbose,:use_nodes,:detailed_exitcodes,:catalog, :write_catalog_summary].each do |option|
26
18
  it "should declare handle_#{option} method" do
27
19
  expect(@apply).to respond_to("handle_#{option}".to_sym)
@@ -182,13 +174,11 @@ describe Puppet::Application::Apply do
182
174
  Puppet[:prerun_command] = ''
183
175
  Puppet[:postrun_command] = ''
184
176
 
185
- Puppet::Node::Facts.indirection.terminus_class = :memory
186
- Puppet::Node::Facts.indirection.cache_class = :memory
187
177
  Puppet::Node.indirection.terminus_class = :memory
188
178
  Puppet::Node.indirection.cache_class = :memory
189
179
 
190
- @facts = Puppet::Node::Facts.new(Puppet[:node_name_value])
191
- Puppet::Node::Facts.indirection.save(@facts)
180
+ facts = Puppet::Node::Facts.new(Puppet[:node_name_value])
181
+ Puppet::Node::Facts.indirection.save(facts)
192
182
 
193
183
  @node = Puppet::Node.new(Puppet[:node_name_value])
194
184
  Puppet::Node.indirection.save(@node)
@@ -3,95 +3,133 @@ require 'spec_helper'
3
3
  require 'puppet/application/describe'
4
4
 
5
5
  describe Puppet::Application::Describe do
6
- before :each do
7
- @describe = Puppet::Application[:describe]
8
- end
6
+ let(:describe) { Puppet::Application[:describe] }
7
+
8
+ it "lists all types" do
9
+ describe.command_line.args << '--list'
9
10
 
10
- it "should declare a main command" do
11
- expect(@describe).to respond_to(:main)
11
+ expect {
12
+ describe.run
13
+ }.to output(/These are the types known to puppet:/).to_stdout
12
14
  end
13
15
 
14
- it "should declare a preinit block" do
15
- expect(@describe).to respond_to(:preinit)
16
+ it "describes a single type" do
17
+ describe.command_line.args << 'exec'
18
+
19
+ expect {
20
+ describe.run
21
+ }.to output(/exec.*====.*Executes external commands/m).to_stdout
16
22
  end
17
23
 
18
- [:providers,:list,:meta].each do |option|
19
- it "should declare handle_#{option} method" do
20
- expect(@describe).to respond_to("handle_#{option}".to_sym)
21
- end
24
+ it "describes multiple types" do
25
+ describe.command_line.args.concat(['exec', 'file'])
22
26
 
23
- it "should store argument value when calling handle_#{option}" do
24
- expect(@describe.options).to receive(:[]=).with("#{option}".to_sym, 'arg')
25
- @describe.send("handle_#{option}".to_sym, 'arg')
26
- end
27
+ expect {
28
+ describe.run
29
+ }.to output(/Executes external commands.*Manages files, including their content, ownership, and permissions./m).to_stdout
27
30
  end
28
31
 
32
+ it "describes parameters for the type by default" do
33
+ describe.command_line.args << 'exec'
29
34
 
30
- describe "in preinit" do
31
- it "should set options[:parameters] to true" do
32
- @describe.preinit
35
+ expect {
36
+ describe.run
37
+ }.to output(/Parameters\n----------/m).to_stdout
38
+ end
33
39
 
34
- expect(@describe.options[:parameters]).to be_truthy
35
- end
40
+ it "lists parameter names, but excludes description in short mode" do
41
+ describe.command_line.args.concat(['exec', '-s'])
42
+
43
+ expect {
44
+ describe.run
45
+ }.to output(/Parameters.*command, creates, cwd/m).to_stdout
36
46
  end
37
47
 
38
- describe "when handling parameters" do
39
- it "should set options[:parameters] to false" do
40
- @describe.handle_short(nil)
48
+ it "outputs providers for the type" do
49
+ describe.command_line.args.concat(['exec', '--providers'])
41
50
 
42
- expect(@describe.options[:parameters]).to be_falsey
43
- end
51
+ expect {
52
+ describe.run
53
+ }.to output(/Providers.*#{Regexp.escape('**posix**')}.*#{Regexp.escape('**windows**')}/m).to_stdout
44
54
  end
45
55
 
46
- describe "during setup" do
47
- it "should collect arguments in options[:types]" do
48
- allow(@describe.command_line).to receive(:args).and_return(['1','2'])
49
- @describe.setup
56
+ it "lists metaparameters for a type" do
57
+ describe.command_line.args.concat(['exec', '--meta'])
50
58
 
51
- expect(@describe.options[:types]).to eq(['1','2'])
52
- end
59
+ expect {
60
+ describe.run
61
+ }.to output(/Meta Parameters.*#{Regexp.escape('**notify**')}/m).to_stdout
53
62
  end
54
63
 
55
- describe "when running" do
64
+ it "outputs no documentation if the summary is missing" do
65
+ Puppet::Type.newtype(:describe_test) {}
66
+
67
+ describe.command_line.args << '--list'
68
+ expect {
69
+ describe.run
70
+ }.to output(/#{Regexp.escape("describe_test - .. no documentation ..")}/).to_stdout
71
+ end
56
72
 
57
- before :each do
58
- @typedoc = double('type_doc')
59
- allow(TypeDoc).to receive(:new).and_return(@typedoc)
73
+ it "outputs the first short sentence ending in a dot" do
74
+ Puppet::Type.newtype(:describe_test) do
75
+ @doc = "ends in a dot."
60
76
  end
61
77
 
62
- it "should call list_types if options list is set" do
63
- @describe.options[:list] = true
78
+ describe.command_line.args << '--list'
79
+ expect {
80
+ describe.run
81
+ }.to output(/#{Regexp.escape("describe_test - ends in a dot\n")}/).to_stdout
82
+ end
64
83
 
65
- expect(@typedoc).to receive(:list_types)
84
+ it "outputs the first short sentence missing a dot" do
85
+ Puppet::Type.newtype(:describe_test) do
86
+ @doc = "missing a dot"
87
+ end
66
88
 
67
- @describe.run_command
89
+ describe.command_line.args << '--list'
90
+ expect {
91
+ describe.run
92
+ }.to output(/describe_test - missing a dot\n/).to_stdout
93
+ end
94
+
95
+ it "truncates long summaries ending in a dot" do
96
+ Puppet::Type.newtype(:describe_test) do
97
+ @doc = "This sentence is more than 45 characters and ends in a dot."
68
98
  end
69
99
 
70
- it "should call format_type for each given types" do
71
- @describe.options[:list] = false
72
- @describe.options[:types] = ['type']
100
+ describe.command_line.args << '--list'
101
+ expect {
102
+ describe.run
103
+ }.to output(/#{Regexp.escape("describe_test - This sentence is more than 45 characters and ...")}/).to_stdout
104
+ end
73
105
 
74
- expect(@typedoc).to receive(:format_type).with('type', @describe.options)
75
- @describe.run_command
106
+ it "truncates long summaries missing a dot" do
107
+ Puppet::Type.newtype(:describe_test) do
108
+ @doc = "This sentence is more than 45 characters and is missing a dot"
76
109
  end
110
+
111
+ describe.command_line.args << '--list'
112
+ expect {
113
+ describe.run
114
+ }.to output(/#{Regexp.escape("describe_test - This sentence is more than 45 characters and ...")}/).to_stdout
77
115
  end
78
116
 
79
- it "should format text with long non-space runs without garbling" do
80
- @f = Formatter.new(76)
117
+ it "formats text with long non-space runs without garbling" do
118
+ f = Formatter.new(76)
81
119
 
82
- @teststring = <<TESTSTRING
120
+ teststring = <<TESTSTRING
83
121
  . 12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 nick@magpie.puppetlabs.lan
84
122
  **this part should not repeat!**
85
123
  TESTSTRING
86
124
 
87
- @expected_result = <<EXPECTED
125
+ expected_result = <<EXPECTED
88
126
  .
89
127
  1234567890123456789012345678901234567890123456789012345678901234567890123456
90
128
  7890123456789012345678901234567890 nick@magpie.puppetlabs.lan
91
129
  **this part should not repeat!**
92
130
  EXPECTED
93
131
 
94
- result = @f.wrap(@teststring, {:indent => 0, :scrub => true})
95
- expect(result).to eql(@expected_result)
132
+ result = f.wrap(teststring, {:indent => 0, :scrub => true})
133
+ expect(result).to eql(expected_result)
96
134
  end
97
135
  end
@@ -459,7 +459,7 @@ describe Puppet::Application::Device do
459
459
  resource = Puppet::Type.type(:user).new(:name => "jim").to_resource
460
460
  allow(device.command_line).to receive(:args).and_return(['user', 'jim'])
461
461
  expect(Puppet::Resource.indirection).to receive(:find).with('user/jim').and_return(resource)
462
- expect(device).to receive(:puts).with("user { 'jim':\n}")
462
+ expect(device).to receive(:puts).with("user { 'jim':\n ensure => 'absent',\n}")
463
463
  expect { device.main }.to exit_with 0
464
464
  end
465
465
 
@@ -470,7 +470,7 @@ describe Puppet::Application::Device do
470
470
  allow(device.options).to receive(:[]).with(:to_yaml).and_return(true)
471
471
  allow(device.command_line).to receive(:args).and_return(['user'])
472
472
  expect(Puppet::Resource.indirection).to receive(:search).with('user/', {}).and_return(resources)
473
- expect(device).to receive(:puts).with("---\nuser:\n title: {}\n")
473
+ expect(device).to receive(:puts).with("---\nuser:\n title:\n ensure: absent\n")
474
474
  expect { device.main }.to exit_with 0
475
475
  end
476
476
  end
@@ -114,12 +114,31 @@ describe Puppet::Application::Filebucket do
114
114
  @filebucket.setup
115
115
  end
116
116
 
117
- it "should default to the first server_list entry if set" do
117
+ it "should default to the first good server_list entry if server_list is set" do
118
+ stub_request(:get, "https://foo:8140/status/v1/simple/master").to_return(status: 200)
118
119
  Puppet[:server_list] = "foo,bar,baz"
119
120
  expect(Puppet::FileBucket::Dipper).to receive(:new).with(hash_including(Server: "foo"))
120
121
  @filebucket.setup
121
122
  end
122
123
 
124
+ it "should walk server_list until it finds a good entry" do
125
+ stub_request(:get, "https://foo:8140/status/v1/simple/master").to_return(status: 502)
126
+ stub_request(:get, "https://bar:8140/status/v1/simple/master").to_return(status: 200)
127
+ Puppet[:server_list] = "foo,bar,baz"
128
+ expect(Puppet::FileBucket::Dipper).to receive(:new).with(hash_including(Server: "bar"))
129
+ @filebucket.setup
130
+ end
131
+
132
+ # FileBucket catches any exceptions raised, logs them, then just exits
133
+ it "raises an error if there are no functional servers in server_list" do
134
+ stub_request(:get, "https://foo:8140/status/v1/simple/master").to_return(status: 404)
135
+ stub_request(:get, "https://bar:8140/status/v1/simple/master").to_return(status: 404)
136
+ Puppet[:server] = 'horacio'
137
+ Puppet[:server_list] = "foo,bar"
138
+
139
+ expect{@filebucket.setup}.to exit_with(1)
140
+ end
141
+
123
142
  it "should fall back to server if server_list is empty" do
124
143
  Puppet[:server_list] = ""
125
144
  expect(Puppet::FileBucket::Dipper).to receive(:new).with(hash_including(Server: "puppet"))
@@ -127,8 +146,9 @@ describe Puppet::Application::Filebucket do
127
146
  end
128
147
 
129
148
  it "should take both the server and port specified in server_list" do
149
+ stub_request(:get, "https://foo:632/status/v1/simple/master").to_return(status: 200)
130
150
  Puppet[:server_list] = "foo:632,bar:6215,baz:351"
131
- expect(Puppet::FileBucket::Dipper).to receive(:new).with({ :Server => "foo", :Port => "632" })
151
+ expect(Puppet::FileBucket::Dipper).to receive(:new).with({ :Server => "foo", :Port => 632 })
132
152
  @filebucket.setup
133
153
  end
134
154
  end
@@ -12,9 +12,9 @@ describe Puppet::Application::Resource do
12
12
  end
13
13
 
14
14
  describe "in preinit" do
15
- it "should init extra_params to empty array" do
15
+ it "should include provider parameter by default" do
16
16
  @resource_app.preinit
17
- expect(@resource_app.extra_params).to eq([])
17
+ expect(@resource_app.extra_params).to eq([:provider])
18
18
  end
19
19
  end
20
20
 
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'puppet/concurrent/lock'
3
+
4
+ describe Puppet::Concurrent::Lock do
5
+ if Puppet::Util::Platform.jruby?
6
+ context 'on jruby' do
7
+ it 'synchronizes a block on itself' do
8
+ iterations = 100
9
+ value = 0
10
+
11
+ lock = Puppet::Concurrent::Lock.new
12
+ threads = iterations.times.collect do
13
+ Thread.new do
14
+ lock.synchronize do
15
+ tmp = (value += 1)
16
+ sleep(0.001)
17
+ # This update using tmp is designed to lose increments if threads overlap
18
+ value = tmp + 1
19
+ end
20
+ end
21
+ end
22
+ threads.each(&:join)
23
+
24
+ # In my testing this always fails by quite a lot when not synchronized (ie on mri)
25
+ expect(value).to eq(iterations * 2)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -22,10 +22,6 @@ describe Puppet::Configurer::FactHandler do
22
22
 
23
23
  let(:facthandler) { FactHandlerTester.new('production') }
24
24
 
25
- before :each do
26
- Puppet::Node::Facts.indirection.terminus_class = :memory
27
- end
28
-
29
25
  describe "when finding facts" do
30
26
  it "should use the node name value to retrieve the facts" do
31
27
  foo_facts = Puppet::Node::Facts.new('foo')
@@ -6,13 +6,17 @@ describe Puppet::Configurer::PluginHandler do
6
6
  let(:pluginhandler) { Puppet::Configurer::PluginHandler.new() }
7
7
  let(:environment) { Puppet::Node::Environment.create(:myenv, []) }
8
8
 
9
+ before :each do
10
+ # PluginHandler#load_plugin has an extra-strong rescue clause
11
+ # this mock is to make sure that we don't silently ignore errors
12
+ expect(Puppet).not_to receive(:err)
13
+ end
14
+
9
15
  context "server agent version is 5.3.4" do
10
- before :each do
11
- # PluginHandler#load_plugin has an extra-strong rescue clause
12
- # this mock is to make sure that we don't silently ignore errors
13
- expect(Puppet).not_to receive(:err)
14
- # Server_agent version needs to be at 5.3.4 in order to mount locales
15
- Puppet.push_context({:server_agent_version => "5.3.4"})
16
+ around do |example|
17
+ Puppet.override(server_agent_version: "5.3.4") do
18
+ example.run
19
+ end
16
20
  end
17
21
 
18
22
  it "downloads plugins, facts, and locales" do
@@ -43,12 +47,10 @@ describe Puppet::Configurer::PluginHandler do
43
47
  end
44
48
 
45
49
  context "server agent version is 5.3.3" do
46
- before :each do
47
- # PluginHandler#load_plugin has an extra-strong rescue clause
48
- # this mock is to make sure that we don't silently ignore errors
49
- expect(Puppet).not_to receive(:err)
50
- # Server_agent version needs to be at 5.3.4 in order to mount locales
51
- Puppet.push_context({:server_agent_version => "5.3.3"})
50
+ around do |example|
51
+ Puppet.override(server_agent_version: "5.3.3") do
52
+ example.run
53
+ end
52
54
  end
53
55
 
54
56
  it "returns downloaded plugin, fact, but not locale filenames" do
@@ -69,15 +71,30 @@ describe Puppet::Configurer::PluginHandler do
69
71
  end
70
72
 
71
73
  context "blank server agent version" do
72
- before :each do
73
- # PluginHandler#load_plugin has an extra-strong rescue clause
74
- # this mock is to make sure that we don't silently ignore errors
75
- expect(Puppet).not_to receive(:err)
76
- # Server_agent version needs to be at 5.3.4 in order to mount locales
77
- # A blank version will default to 0.0
78
- Puppet.push_context({:server_agent_version => ""})
74
+ around do |example|
75
+ Puppet.override(server_agent_version: "") do
76
+ example.run
77
+ end
78
+ end
79
+
80
+ it "returns downloaded plugin, fact, but not locale filenames" do
81
+ times_called = 0
82
+ allow_any_instance_of(Puppet::Configurer::Downloader).to receive(:evaluate) do
83
+ times_called += 1
84
+
85
+ if times_called == 1
86
+ %w[/a]
87
+ else
88
+ %w[/b]
89
+ end
90
+ end
91
+
92
+ expect(pluginhandler.download_plugins(environment)).to match_array(%w[/a /b])
93
+ expect(times_called).to eq(2)
79
94
  end
95
+ end
80
96
 
97
+ context "nil server agent version" do
81
98
  it "returns downloaded plugin, fact, but not locale filenames" do
82
99
  times_called = 0
83
100
  allow_any_instance_of(Puppet::Configurer::Downloader).to receive(:evaluate) do
@@ -1,108 +1,88 @@
1
1
  require 'spec_helper'
2
2
  require 'puppet/configurer'
3
+ require 'webmock/rspec'
3
4
 
4
5
  describe Puppet::Configurer do
5
6
  before do
6
- allow(Puppet.settings).to receive(:use).and_return(true)
7
- @agent = Puppet::Configurer.new
8
- allow(@agent).to receive(:init_storage)
9
- allow(Puppet::Util::Storage).to receive(:store)
10
7
  Puppet[:server] = "puppetmaster"
11
8
  Puppet[:report] = true
12
- end
13
9
 
14
- it "should include the Fact Handler module" do
15
- expect(Puppet::Configurer.ancestors).to be_include(Puppet::Configurer::FactHandler)
10
+ catalog.add_resource(resource)
16
11
  end
17
12
 
13
+ let(:node_name) { Puppet[:node_name_value] }
14
+ let(:configurer) { Puppet::Configurer.new }
15
+ let(:report) { Puppet::Transaction::Report.new }
16
+ let(:catalog) { Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) }
17
+ let(:resource) { Puppet::Resource.new(:notice, 'a') }
18
+ let(:facts) { Puppet::Node::Facts.new(node_name) }
19
+
18
20
  describe "when executing a pre-run hook" do
19
21
  it "should do nothing if the hook is set to an empty string" do
20
22
  Puppet.settings[:prerun_command] = ""
21
- expect(Puppet::Util).not_to receive(:exec)
23
+ expect(Puppet::Util::Execution).not_to receive(:execute)
22
24
 
23
- @agent.execute_prerun_command
25
+ configurer.execute_prerun_command
24
26
  end
25
27
 
26
28
  it "should execute any pre-run command provided via the 'prerun_command' setting" do
27
29
  Puppet.settings[:prerun_command] = "/my/command"
28
30
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
29
31
 
30
- @agent.execute_prerun_command
32
+ configurer.execute_prerun_command
31
33
  end
32
34
 
33
35
  it "should fail if the command fails" do
34
36
  Puppet.settings[:prerun_command] = "/my/command"
35
37
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
36
38
 
37
- expect(@agent.execute_prerun_command).to be_falsey
39
+ expect(configurer.execute_prerun_command).to be_falsey
38
40
  end
39
41
  end
40
42
 
41
43
  describe "when executing a post-run hook" do
42
44
  it "should do nothing if the hook is set to an empty string" do
43
45
  Puppet.settings[:postrun_command] = ""
44
- expect(Puppet::Util).not_to receive(:exec)
46
+ expect(Puppet::Util::Execution).not_to receive(:execute)
45
47
 
46
- @agent.execute_postrun_command
48
+ configurer.execute_postrun_command
47
49
  end
48
50
 
49
51
  it "should execute any post-run command provided via the 'postrun_command' setting" do
50
52
  Puppet.settings[:postrun_command] = "/my/command"
51
53
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
52
54
 
53
- @agent.execute_postrun_command
55
+ configurer.execute_postrun_command
54
56
  end
55
57
 
56
58
  it "should fail if the command fails" do
57
59
  Puppet.settings[:postrun_command] = "/my/command"
58
60
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
59
61
 
60
- expect(@agent.execute_postrun_command).to be_falsey
62
+ expect(configurer.execute_postrun_command).to be_falsey
61
63
  end
62
64
  end
63
65
 
64
66
  describe "when executing a catalog run" do
65
67
  before do
66
- allow(Puppet.settings).to receive(:use).and_return(true)
67
- allow(@agent).to receive(:download_plugins)
68
- Puppet::Node::Facts.indirection.terminus_class = :memory
69
- @facts = Puppet::Node::Facts.new(Puppet[:node_name_value])
70
- Puppet::Node::Facts.indirection.save(@facts)
71
-
72
- @catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
73
- allow(@catalog).to receive(:to_ral).and_return(@catalog)
74
68
  Puppet::Resource::Catalog.indirection.terminus_class = :rest
75
- allow(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(@catalog)
76
- allow(@agent).to receive(:send_report)
77
- allow(@agent).to receive(:save_last_run_summary)
78
-
79
- allow(Puppet::Util::Log).to receive(:close_all)
80
- end
81
-
82
- after :all do
83
- Puppet::Node::Facts.indirection.reset_terminus_class
84
- Puppet::Resource::Catalog.indirection.reset_terminus_class
85
- end
86
-
87
- it "should initialize storage" do
88
- expect(Puppet::Util::Storage).to receive(:load)
89
- @agent.run
69
+ allow(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(catalog)
90
70
  end
91
71
 
92
72
  it "downloads plugins when told" do
93
- expect(@agent).to receive(:download_plugins)
94
- @agent.run(:pluginsync => true)
73
+ expect(configurer).to receive(:download_plugins)
74
+ configurer.run(:pluginsync => true)
95
75
  end
96
76
 
97
77
  it "does not download plugins when told" do
98
- expect(@agent).not_to receive(:download_plugins)
99
- @agent.run(:pluginsync => false)
78
+ expect(configurer).not_to receive(:download_plugins)
79
+ configurer.run(:pluginsync => false)
100
80
  end
101
81
 
102
82
  it "should carry on when it can't fetch its node definition" do
103
83
  error = Net::HTTPError.new(400, 'dummy server communication error')
104
84
  expect(Puppet::Node.indirection).to receive(:find).and_raise(error)
105
- expect(@agent.run).to eq(0)
85
+ expect(configurer.run).to eq(0)
106
86
  end
107
87
 
108
88
  it "applies a cached catalog when it can't connect to the master" do
@@ -110,200 +90,158 @@ describe Puppet::Configurer do
110
90
 
111
91
  expect(Puppet::Node.indirection).to receive(:find).and_raise(error)
112
92
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_cache => true)).and_raise(error)
113
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_terminus => true)).and_return(@catalog)
93
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(:ignore_terminus => true)).and_return(catalog)
114
94
 
115
- expect(@agent.run).to eq(0)
95
+ expect(configurer.run).to eq(0)
116
96
  end
117
97
 
118
98
  it "should initialize a transaction report if one is not provided" do
119
- report = Puppet::Transaction::Report.new
120
99
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
121
100
 
122
- @agent.run
101
+ configurer.run
123
102
  end
124
103
 
125
104
  it "should respect node_name_fact when setting the host on a report" do
105
+ Puppet[:node_name_value] = nil
126
106
  Puppet[:node_name_fact] = 'my_name_fact'
127
- @facts.values = {'my_name_fact' => 'node_name_from_fact'}
107
+ facts.values = {'my_name_fact' => 'node_name_from_fact'}
108
+ Puppet::Node::Facts.indirection.save(facts)
128
109
 
129
- report = Puppet::Transaction::Report.new
130
-
131
- @agent.run(:report => report)
110
+ configurer.run(:report => report)
132
111
  expect(report.host).to eq('node_name_from_fact')
133
112
  end
134
113
 
135
- it "should pass the new report to the catalog" do
136
- report = Puppet::Transaction::Report.new
137
- allow(Puppet::Transaction::Report).to receive(:new).and_return(report)
138
- expect(@catalog).to receive(:apply).with(hash_including(report: report))
139
-
140
- @agent.run
141
- end
142
-
143
- it "should use the provided report if it was passed one" do
144
- report = Puppet::Transaction::Report.new
145
- expect(@catalog).to receive(:apply).with(hash_including(report: report))
146
-
147
- @agent.run(:report => report)
148
- end
149
-
150
- it "should set the report as a log destination" do
151
- report = Puppet::Transaction::Report.new
152
-
153
- expect(report).to receive(:<<).with(instance_of(Puppet::Util::Log)).at_least(:once)
114
+ it "creates a new report when applying the catalog" do
115
+ options = {}
116
+ configurer.run(options)
154
117
 
155
- @agent.run(:report => report)
118
+ expect(options[:report].metrics['time']['catalog_application']).to be_an_instance_of(Float)
156
119
  end
157
120
 
158
- it "should retrieve the catalog" do
159
- expect(@agent).to receive(:retrieve_catalog)
121
+ it "uses the provided report when applying the catalog" do
122
+ configurer.run(:report => report)
160
123
 
161
- @agent.run
124
+ expect(report.metrics['time']['catalog_application']).to be_an_instance_of(Float)
162
125
  end
163
126
 
164
127
  it "should log a failure and do nothing if no catalog can be retrieved" do
165
- expect(@agent).to receive(:retrieve_catalog).and_return(nil)
128
+ expect(configurer).to receive(:retrieve_catalog).and_return(nil)
166
129
 
167
130
  expect(Puppet).to receive(:err).with("Could not retrieve catalog; skipping run")
168
131
 
169
- @agent.run
132
+ configurer.run
170
133
  end
171
134
 
172
- it "should apply the catalog with all options to :run" do
173
- expect(@agent).to receive(:retrieve_catalog).and_return(@catalog)
135
+ it "passes arbitrary options when applying the catalog" do
136
+ expect(catalog).to receive(:apply).with(hash_including(one: true))
174
137
 
175
- expect(@catalog).to receive(:apply).with(hash_including(one: true))
176
- @agent.run :one => true
177
- end
178
-
179
- it "should accept a catalog and use it instead of retrieving a different one" do
180
- expect(@agent).not_to receive(:retrieve_catalog)
181
-
182
- expect(@catalog).to receive(:apply)
183
- @agent.run :one => true, :catalog => @catalog
138
+ configurer.run(catalog: catalog, one: true)
184
139
  end
185
140
 
186
141
  it "should benchmark how long it takes to apply the catalog" do
187
- expect(@agent).to receive(:benchmark).with(:notice, instance_of(String))
188
-
189
- expect(@agent).to receive(:retrieve_catalog).and_return(@catalog)
190
-
191
- expect(@catalog).not_to receive(:apply) # because we're not yielding
192
- @agent.run
193
- end
194
-
195
- it "should execute post-run hooks after the run" do
196
- expect(@agent).to receive(:execute_postrun_command)
142
+ configurer.run(report: report)
197
143
 
198
- @agent.run
144
+ expect(report.logs).to include(an_object_having_attributes(level: :notice, message: /Applied catalog in .* seconds/))
199
145
  end
200
146
 
201
147
  it "should create report with passed transaction_uuid and job_id" do
202
- @agent = Puppet::Configurer.new("test_tuuid", "test_jid")
203
- allow(@agent).to receive(:init_storage)
148
+ configurer = Puppet::Configurer.new("test_tuuid", "test_jid")
204
149
 
205
150
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
206
- expect(Puppet::Transaction::Report).to receive(:new).with(anything, anything, 'test_tuuid', 'test_jid').and_return(report)
207
- expect(@agent).to receive(:send_report).with(report)
151
+ expect(Puppet::Transaction::Report).to receive(:new).with(anything, anything, 'test_tuuid', 'test_jid', anything).and_return(report)
152
+ expect(configurer).to receive(:send_report).with(report)
208
153
 
209
- @agent.run
154
+ configurer.run
210
155
  end
211
156
 
212
157
  it "should send the report" do
213
158
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
214
159
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
215
- expect(@agent).to receive(:send_report).with(report)
160
+ expect(configurer).to receive(:send_report).with(report)
216
161
 
217
162
  expect(report.environment).to eq("test")
218
163
  expect(report.transaction_uuid).to eq("aaaa")
219
164
 
220
- @agent.run
165
+ configurer.run
221
166
  end
222
167
 
223
168
  it "should send the transaction report even if the catalog could not be retrieved" do
224
- expect(@agent).to receive(:retrieve_catalog).and_return(nil)
169
+ expect(configurer).to receive(:retrieve_catalog).and_return(nil)
225
170
 
226
171
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
227
172
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
228
- expect(@agent).to receive(:send_report).with(report)
173
+ expect(configurer).to receive(:send_report).with(report)
229
174
 
230
175
  expect(report.environment).to eq("test")
231
176
  expect(report.transaction_uuid).to eq("aaaa")
232
177
 
233
- @agent.run
178
+ configurer.run
234
179
  end
235
180
 
236
181
  it "should send the transaction report even if there is a failure" do
237
- expect(@agent).to receive(:retrieve_catalog).and_raise("whatever")
182
+ expect(configurer).to receive(:retrieve_catalog).and_raise("whatever")
238
183
 
239
184
  report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
240
185
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
241
- expect(@agent).to receive(:send_report).with(report)
186
+ expect(configurer).to receive(:send_report).with(report)
242
187
 
243
188
  expect(report.environment).to eq("test")
244
189
  expect(report.transaction_uuid).to eq("aaaa")
245
190
 
246
- expect(@agent.run).to be_nil
191
+ expect(configurer.run).to be_nil
247
192
  end
248
193
 
249
194
  it "should remove the report as a log destination when the run is finished" do
250
- report = Puppet::Transaction::Report.new
251
195
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
252
196
 
253
- @agent.run
197
+ configurer.run
254
198
 
255
199
  expect(Puppet::Util::Log.destinations).not_to include(report)
256
200
  end
257
201
 
258
202
  it "should return the report exit_status as the result of the run" do
259
- report = Puppet::Transaction::Report.new
260
203
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
261
204
  expect(report).to receive(:exit_status).and_return(1234)
262
205
 
263
- expect(@agent.run).to eq(1234)
206
+ expect(configurer.run).to eq(1234)
264
207
  end
265
208
 
266
209
  it "should return nil if catalog application fails" do
267
- expect(@catalog).to receive(:apply).and_raise(Puppet::Error, 'One or more resource dependency cycles detected in graph')
268
- report = Puppet::Transaction::Report.new
269
- expect(@agent.run(catalog: @catalog, report: report)).to be_nil
210
+ expect_any_instance_of(Puppet::Resource::Catalog).to receive(:apply).and_raise(Puppet::Error, 'One or more resource dependency cycles detected in graph')
211
+ expect(configurer.run(catalog: catalog, report: report)).to be_nil
270
212
  end
271
213
 
272
214
  it "should send the transaction report even if the pre-run command fails" do
273
- report = Puppet::Transaction::Report.new
274
215
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
275
216
 
276
217
  Puppet.settings[:prerun_command] = "/my/command"
277
218
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
278
- expect(@agent).to receive(:send_report).with(report)
219
+ expect(configurer).to receive(:send_report).with(report)
279
220
 
280
- expect(@agent.run).to be_nil
221
+ expect(configurer.run).to be_nil
281
222
  end
282
223
 
283
224
  it "should include the pre-run command failure in the report" do
284
- report = Puppet::Transaction::Report.new
285
225
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
286
226
 
287
227
  Puppet.settings[:prerun_command] = "/my/command"
288
228
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
289
229
 
290
- expect(@agent.run).to be_nil
230
+ expect(configurer.run).to be_nil
291
231
  expect(report.logs.find { |x| x.message =~ /Could not run command from prerun_command/ }).to be
292
232
  end
293
233
 
294
234
  it "should send the transaction report even if the post-run command fails" do
295
- report = Puppet::Transaction::Report.new
296
235
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
297
236
 
298
237
  Puppet.settings[:postrun_command] = "/my/command"
299
238
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
300
- expect(@agent).to receive(:send_report).with(report)
239
+ expect(configurer).to receive(:send_report).with(report)
301
240
 
302
- expect(@agent.run).to be_nil
241
+ expect(configurer.run).to be_nil
303
242
  end
304
243
 
305
244
  it "should include the post-run command failure in the report" do
306
- report = Puppet::Transaction::Report.new
307
245
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
308
246
 
309
247
  Puppet.settings[:postrun_command] = "/my/command"
@@ -311,7 +249,7 @@ describe Puppet::Configurer do
311
249
 
312
250
  expect(report).to receive(:<<) { |log, _| expect(log.message).to match(/Could not run command from postrun_command/) }.at_least(:once)
313
251
 
314
- expect(@agent.run).to be_nil
252
+ expect(configurer.run).to be_nil
315
253
  end
316
254
 
317
255
  it "should execute post-run command even if the pre-run command fails" do
@@ -320,47 +258,42 @@ describe Puppet::Configurer do
320
258
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/precommand"]).and_raise(Puppet::ExecutionFailure, "Failed")
321
259
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/postcommand"])
322
260
 
323
- expect(@agent.run).to be_nil
261
+ expect(configurer.run).to be_nil
324
262
  end
325
263
 
326
264
  it "should finalize the report" do
327
- report = Puppet::Transaction::Report.new
328
265
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
329
266
 
330
267
  expect(report).to receive(:finalize_report)
331
- @agent.run
268
+ configurer.run
332
269
  end
333
270
 
334
271
  it "should not apply the catalog if the pre-run command fails" do
335
- report = Puppet::Transaction::Report.new
336
272
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
337
273
 
338
274
  Puppet.settings[:prerun_command] = "/my/command"
339
275
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
340
276
 
341
- expect(@catalog).not_to receive(:apply)
342
- expect(@agent).to receive(:send_report)
277
+ expect_any_instance_of(Puppet::Resource::Catalog).not_to receive(:apply)
278
+ expect(configurer).to receive(:send_report)
343
279
 
344
- expect(@agent.run).to be_nil
280
+ expect(configurer.run).to be_nil
345
281
  end
346
282
 
347
283
  it "should apply the catalog, send the report, and return nil if the post-run command fails" do
348
- report = Puppet::Transaction::Report.new
349
284
  expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
350
285
 
351
286
  Puppet.settings[:postrun_command] = "/my/command"
352
287
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
353
288
 
354
- expect(@catalog).to receive(:apply)
355
- expect(@agent).to receive(:send_report)
289
+ expect_any_instance_of(Puppet::Resource::Catalog).to receive(:apply)
290
+ expect(configurer).to receive(:send_report)
356
291
 
357
- expect(@agent.run).to be_nil
292
+ expect(configurer.run).to be_nil
358
293
  end
359
294
 
360
295
  it 'includes total time metrics in the report after successfully applying the catalog' do
361
- report = Puppet::Transaction::Report.new
362
- allow(@catalog).to receive(:apply).with(hash_including(report: report))
363
- @agent.run(report: report)
296
+ configurer.run(report: report)
364
297
 
365
298
  expect(report.metrics['time']).to be
366
299
  expect(report.metrics['time']['total']).to be_a_kind_of(Numeric)
@@ -370,120 +303,109 @@ describe Puppet::Configurer do
370
303
  Puppet.settings[:prerun_command] = "/my/command"
371
304
  expect(Puppet::Util::Execution).to receive(:execute).with(["/my/command"]).and_raise(Puppet::ExecutionFailure, "Failed")
372
305
 
373
- report = Puppet::Transaction::Report.new
374
- @agent.run(report: report)
306
+ configurer.run(report: report)
375
307
 
376
308
  expect(report.metrics['time']).to be
377
309
  expect(report.metrics['time']['total']).to be_a_kind_of(Numeric)
378
310
  end
379
311
 
380
312
  it 'includes total time metrics in the report even if catalog retrieval fails' do
381
- report = Puppet::Transaction::Report.new
382
- allow(@agent).to receive(:prepare_and_retrieve_catalog_from_cache).and_raise
383
- @agent.run(:report => report)
313
+ allow(configurer).to receive(:prepare_and_retrieve_catalog_from_cache).and_raise
314
+ configurer.run(:report => report)
384
315
 
385
316
  expect(report.metrics['time']).to be
386
317
  expect(report.metrics['time']['total']).to be_a_kind_of(Numeric)
387
318
  end
388
319
 
389
320
  it "should refetch the catalog if the server specifies a new environment in the catalog" do
390
- catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
391
- expect(@agent).to receive(:retrieve_catalog).and_return(catalog).twice
321
+ catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote('second_env'))
322
+ expect(configurer).to receive(:retrieve_catalog).and_return(catalog).twice
392
323
 
393
- @agent.run
324
+ configurer.run
394
325
  end
395
326
 
396
- it "should change the environment setting if the server specifies a new environment in the catalog" do
397
- allow(@catalog).to receive(:environment).and_return("second_env")
327
+ it "changes the configurer's environment if the server specifies a new environment in the catalog" do
328
+ allow_any_instance_of(Puppet::Resource::Catalog).to receive(:environment).and_return("second_env")
398
329
 
399
- @agent.run
330
+ configurer.run
400
331
 
401
- expect(@agent.environment).to eq("second_env")
332
+ expect(configurer.environment).to eq("second_env")
402
333
  end
403
334
 
404
- it "should fix the report if the server specifies a new environment in the catalog" do
405
- report = Puppet::Transaction::Report.new(nil, "test", "aaaa")
406
- expect(Puppet::Transaction::Report).to receive(:new).and_return(report)
407
- expect(@agent).to receive(:send_report).with(report)
408
-
409
- allow(@catalog).to receive(:environment).and_return("second_env")
410
- allow(@agent).to receive(:retrieve_catalog).and_return(@catalog)
335
+ it "changes the report's environment if the server specifies a new environment in the catalog" do
336
+ allow_any_instance_of(Puppet::Resource::Catalog).to receive(:environment).and_return("second_env")
411
337
 
412
- @agent.run
338
+ configurer.run(report: report)
413
339
 
414
340
  expect(report.environment).to eq("second_env")
415
341
  end
416
342
 
417
343
  it "sends the transaction uuid in a catalog request" do
418
- @agent.instance_variable_set(:@transaction_uuid, 'aaa')
344
+ configurer = Puppet::Configurer.new('aaa')
419
345
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(transaction_uuid: 'aaa'))
420
- @agent.run
346
+ configurer.run
421
347
  end
422
348
 
423
349
  it "sends the transaction uuid in a catalog request" do
424
- @agent.instance_variable_set(:@job_id, 'aaa')
350
+ configurer = Puppet::Configurer.new('b', 'aaa')
425
351
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(job_id: 'aaa'))
426
- @agent.run
352
+ configurer.run
427
353
  end
428
354
 
429
355
  it "sets the static_catalog query param to true in a catalog request" do
430
356
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(static_catalog: true))
431
- @agent.run
357
+ configurer.run
432
358
  end
433
359
 
434
360
  it "sets the checksum_type query param to the default supported_checksum_types in a catalog request" do
435
361
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything,
436
362
  hash_including(checksum_type: 'md5.sha256.sha384.sha512.sha224'))
437
- @agent.run
363
+ configurer.run
438
364
  end
439
365
 
440
366
  it "sets the checksum_type query param to the supported_checksum_types setting in a catalog request" do
441
- # Regenerate the agent to pick up the new setting
442
367
  Puppet[:supported_checksum_types] = ['sha256']
443
- @agent = Puppet::Configurer.new
444
- allow(@agent).to receive(:init_storage)
445
- allow(@agent).to receive(:download_plugins)
446
- allow(@agent).to receive(:send_report)
447
- allow(@agent).to receive(:save_last_run_summary)
368
+ # Regenerate the agent to pick up the new setting
369
+ configurer = Puppet::Configurer.new
448
370
 
449
371
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(checksum_type: 'sha256'))
450
- @agent.run
372
+ configurer.run
451
373
  end
452
374
 
453
375
  describe "when not using a REST terminus for catalogs" do
454
376
  it "should not pass any facts when retrieving the catalog" do
377
+ # This is weird, we collect facts when constructing the node,
378
+ # but we don't send them in the indirector request. Then the compiler
379
+ # looks up the node, and collects its facts, which we could have sent
380
+ # in the first place. This seems like a bug.
455
381
  Puppet::Resource::Catalog.indirection.terminus_class = :compiler
456
- expect(@agent).not_to receive(:facts_for_uploading)
382
+
457
383
  expect(Puppet::Resource::Catalog.indirection).to receive(:find) do |name, options|
458
- options[:facts].nil?
459
- end.and_return(@catalog)
384
+ expect(options[:facts]).to be_nil
385
+ end.and_return(catalog)
460
386
 
461
- @agent.run
387
+ configurer.run
462
388
  end
463
389
  end
464
390
 
465
391
  describe "when using a REST terminus for catalogs" do
466
- it "should pass the prepared facts and the facts format as arguments when retrieving the catalog" do
392
+ it "should pass the url encoded facts and facts format as arguments when retrieving the catalog" do
467
393
  Puppet::Resource::Catalog.indirection.terminus_class = :rest
468
- # the "facts_for_uploading" are prepeared by first finding facts, and then encoding them
469
- # this mocks the "find" with a special value 12345, which is then expected back in the
470
- # call to "encode" - the encode in turn returns mocked data that is asserted as being
471
- # presented to the catalog terminus as options.
472
- #
473
- expect(@agent).to receive(:find_facts).and_return(12345)
474
- expect(@agent).to receive(:encode_facts).with(12345).and_return(:facts => "myfacts", :facts_format => :foo)
475
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(facts: "myfacts", facts_format: :foo)).and_return(@catalog)
476
-
477
- @agent.run
478
- end
479
- end
480
- end
481
394
 
482
- describe "when initialized with a transaction_uuid" do
483
- it "stores it" do
484
- expect(SecureRandom).not_to receive(:uuid)
485
- configurer = Puppet::Configurer.new('foo')
486
- expect(configurer.instance_variable_get(:@transaction_uuid) == 'foo')
395
+ facts.values = { 'foo' => 'bar' }
396
+ Puppet::Node::Facts.indirection.save(facts)
397
+
398
+ expect(
399
+ Puppet::Resource::Catalog.indirection
400
+ ).to receive(:find) do |_, options|
401
+ expect(options[:facts_format]).to eq("application/json")
402
+
403
+ unescaped = JSON.parse(CGI.unescape(options[:facts]))
404
+ expect(unescaped).to include("values" => {"foo" => "bar"})
405
+ end.and_return(catalog)
406
+
407
+ configurer.run
408
+ end
487
409
  end
488
410
  end
489
411
 
@@ -491,56 +413,52 @@ describe Puppet::Configurer do
491
413
  include PuppetSpec::Files
492
414
 
493
415
  before do
494
- allow(Puppet.settings).to receive(:use).and_return(true)
495
- @configurer = Puppet::Configurer.new
496
416
  Puppet[:lastrunfile] = tmpfile('last_run_file')
497
-
498
- @report = Puppet::Transaction::Report.new
499
417
  Puppet[:reports] = "none"
500
418
  end
501
419
 
502
420
  it "should print a report summary if configured to do so" do
503
421
  Puppet.settings[:summarize] = true
504
422
 
505
- expect(@report).to receive(:summary).and_return("stuff")
423
+ expect(report).to receive(:summary).and_return("stuff")
506
424
 
507
- expect(@configurer).to receive(:puts).with("stuff")
508
- @configurer.send_report(@report)
425
+ expect(configurer).to receive(:puts).with("stuff")
426
+ configurer.send_report(report)
509
427
  end
510
428
 
511
429
  it "should not print a report summary if not configured to do so" do
512
430
  Puppet.settings[:summarize] = false
513
431
 
514
- expect(@configurer).not_to receive(:puts)
515
- @configurer.send_report(@report)
432
+ expect(configurer).not_to receive(:puts)
433
+ configurer.send_report(report)
516
434
  end
517
435
 
518
436
  it "should save the report if reporting is enabled" do
519
437
  Puppet.settings[:report] = true
520
438
 
521
- expect(Puppet::Transaction::Report.indirection).to receive(:save).with(@report, nil, instance_of(Hash))
522
- @configurer.send_report(@report)
439
+ expect(Puppet::Transaction::Report.indirection).to receive(:save).with(report, nil, instance_of(Hash))
440
+ configurer.send_report(report)
523
441
  end
524
442
 
525
443
  it "should not save the report if reporting is disabled" do
526
444
  Puppet.settings[:report] = false
527
445
 
528
- expect(Puppet::Transaction::Report.indirection).not_to receive(:save).with(@report, nil, instance_of(Hash))
529
- @configurer.send_report(@report)
446
+ expect(Puppet::Transaction::Report.indirection).not_to receive(:save).with(report, nil, instance_of(Hash))
447
+ configurer.send_report(report)
530
448
  end
531
449
 
532
450
  it "should save the last run summary if reporting is enabled" do
533
451
  Puppet.settings[:report] = true
534
452
 
535
- expect(@configurer).to receive(:save_last_run_summary).with(@report)
536
- @configurer.send_report(@report)
453
+ expect(configurer).to receive(:save_last_run_summary).with(report)
454
+ configurer.send_report(report)
537
455
  end
538
456
 
539
457
  it "should save the last run summary if reporting is disabled" do
540
458
  Puppet.settings[:report] = false
541
459
 
542
- expect(@configurer).to receive(:save_last_run_summary).with(@report)
543
- @configurer.send_report(@report)
460
+ expect(configurer).to receive(:save_last_run_summary).with(report)
461
+ configurer.send_report(report)
544
462
  end
545
463
 
546
464
  it "should log but not fail if saving the report fails" do
@@ -548,8 +466,9 @@ describe Puppet::Configurer do
548
466
 
549
467
  expect(Puppet::Transaction::Report.indirection).to receive(:save).and_raise("whatever")
550
468
 
551
- expect(Puppet).to receive(:send_log).with(:err, 'Could not send report: whatever')
552
- @configurer.send_report(@report)
469
+ configurer.send_report(report)
470
+
471
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: 'Could not send report: whatever'))
553
472
  end
554
473
  end
555
474
 
@@ -557,22 +476,17 @@ describe Puppet::Configurer do
557
476
  include PuppetSpec::Files
558
477
 
559
478
  before do
560
- allow(Puppet.settings).to receive(:use).and_return(true)
561
- @configurer = Puppet::Configurer.new
562
-
563
- @report = double('report', :raw_summary => {})
564
-
565
479
  Puppet[:lastrunfile] = tmpfile('last_run_file')
566
480
  end
567
481
 
568
482
  it "should write the last run file" do
569
- @configurer.save_last_run_summary(@report)
483
+ configurer.save_last_run_summary(report)
570
484
  expect(Puppet::FileSystem.exist?(Puppet[:lastrunfile])).to be_truthy
571
485
  end
572
486
 
573
487
  it "should write the raw summary as yaml" do
574
- expect(@report).to receive(:raw_summary).and_return("summary")
575
- @configurer.save_last_run_summary(@report)
488
+ expect(report).to receive(:raw_summary).and_return("summary")
489
+ configurer.save_last_run_summary(report)
576
490
  expect(File.read(Puppet[:lastrunfile])).to eq(YAML.dump("summary"))
577
491
  end
578
492
 
@@ -587,13 +501,14 @@ describe Puppet::Configurer do
587
501
 
588
502
  expect(Puppet::Util).to receive(:replace_file).and_yield(fh)
589
503
 
590
- expect(Puppet).to receive(:send_log).with(:err, 'Could not save last run local report: failed to do print')
591
- @configurer.save_last_run_summary(@report)
504
+ configurer.save_last_run_summary(report)
505
+
506
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: 'Could not save last run local report: failed to do print'))
592
507
  end
593
508
 
594
509
  it "should create the last run file with the correct mode" do
595
510
  expect(Puppet.settings.setting(:lastrunfile)).to receive(:mode).and_return('664')
596
- @configurer.save_last_run_summary(@report)
511
+ configurer.save_last_run_summary(report)
597
512
 
598
513
  if Puppet::Util::Platform.windows?
599
514
  require 'puppet/util/windows/security'
@@ -606,26 +521,28 @@ describe Puppet::Configurer do
606
521
 
607
522
  it "should report invalid last run file permissions" do
608
523
  expect(Puppet.settings.setting(:lastrunfile)).to receive(:mode).and_return('892')
609
- expect(Puppet).to receive(:send_log).with(:err, /Could not save last run local report.*892 is invalid/)
610
- @configurer.save_last_run_summary(@report)
524
+
525
+ configurer.save_last_run_summary(report)
526
+
527
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: /Could not save last run local report.*892 is invalid/))
611
528
  end
612
529
  end
613
530
 
614
531
  describe "when requesting a node" do
615
532
  it "uses the transaction uuid in the request" do
616
533
  expect(Puppet::Node.indirection).to receive(:find).with(anything, hash_including(transaction_uuid: anything)).twice
617
- @agent.run
534
+ configurer.run
618
535
  end
619
536
 
620
537
  it "sends an explicitly configured environment request" do
621
538
  expect(Puppet.settings).to receive(:set_by_config?).with(:environment).and_return(true)
622
539
  expect(Puppet::Node.indirection).to receive(:find).with(anything, hash_including(configured_environment: Puppet[:environment])).twice
623
- @agent.run
540
+ configurer.run
624
541
  end
625
542
 
626
543
  it "does not send a configured_environment when using the default" do
627
544
  expect(Puppet::Node.indirection).to receive(:find).with(anything, hash_including(configured_environment: nil)).twice
628
- @agent.run
545
+ configurer.run
629
546
  end
630
547
  end
631
548
 
@@ -656,14 +573,6 @@ describe Puppet::Configurer do
656
573
 
657
574
  describe "when retrieving a catalog" do
658
575
  before do
659
- allow(Puppet.settings).to receive(:use).and_return(true)
660
- allow(@agent).to receive(:facts_for_uploading).and_return({})
661
- allow(@agent).to receive(:download_plugins)
662
-
663
- # retrieve a catalog in the current environment, so we don't try to converge unexpectedly
664
- @catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
665
-
666
- # this is the default when using a Configurer instance
667
576
  allow(Puppet::Resource::Catalog.indirection).to receive(:terminus_class).and_return(:rest)
668
577
  end
669
578
 
@@ -673,101 +582,139 @@ describe Puppet::Configurer do
673
582
  end
674
583
 
675
584
  it "should first look in the cache for a catalog" do
676
- expects_cached_catalog_only(@catalog)
585
+ expects_cached_catalog_only(catalog)
677
586
 
678
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
587
+ configurer.run
679
588
  end
680
589
 
681
590
  it "should not make a node request or pluginsync when a cached catalog is successfully retrieved" do
682
591
  expect(Puppet::Node.indirection).not_to receive(:find)
683
- expects_cached_catalog_only(@catalog)
684
- expect(@agent).not_to receive(:download_plugins)
592
+ expects_cached_catalog_only(catalog)
593
+ expect(configurer).not_to receive(:download_plugins)
685
594
 
686
- @agent.run
595
+ configurer.run
687
596
  end
688
597
 
689
598
  it "should make a node request and pluginsync when a cached catalog cannot be retrieved" do
690
599
  expect(Puppet::Node.indirection).to receive(:find).and_return(nil)
691
- expects_fallback_to_new_catalog(@catalog)
692
- expect(@agent).to receive(:download_plugins)
600
+ expects_fallback_to_new_catalog(catalog)
601
+ expect(configurer).to receive(:download_plugins)
693
602
 
694
- @agent.run
603
+ configurer.run
695
604
  end
696
605
 
697
606
  it "should set its cached_catalog_status to 'explicitly_requested'" do
698
- expects_cached_catalog_only(@catalog)
607
+ expects_cached_catalog_only(catalog)
608
+
609
+ options = {}
610
+ configurer.run(options)
699
611
 
700
- @agent.retrieve_catalog({})
701
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('explicitly_requested')
612
+ expect(options[:report].cached_catalog_status).to eq('explicitly_requested')
702
613
  end
703
614
 
704
615
  it "should set its cached_catalog_status to 'explicitly requested' if the cached catalog is from a different environment" do
705
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
616
+ cached_catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote('second_env'))
706
617
  expects_cached_catalog_only(cached_catalog)
707
618
 
708
- @agent.retrieve_catalog({})
709
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('explicitly_requested')
710
- end
711
-
712
- it "should compile a new catalog if none is found in the cache" do
713
- expects_fallback_to_new_catalog(@catalog)
619
+ options = {}
620
+ configurer.run(options)
714
621
 
715
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
622
+ expect(options[:report].cached_catalog_status).to eq('explicitly_requested')
716
623
  end
717
624
 
718
- it "should set its cached_catalog_status to 'not_used' if no catalog is found in the cache" do
719
- expects_fallback_to_new_catalog(@catalog)
625
+ it "should pluginsync and compile a new catalog if none is found in the cache" do
626
+ expects_fallback_to_new_catalog(catalog)
627
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
628
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
720
629
 
721
- @agent.retrieve_catalog({})
722
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
630
+ options = {}
631
+ configurer.run(options)
632
+
633
+ expect(options[:report].cached_catalog_status).to eq('not_used')
723
634
  end
724
635
 
725
636
  it "should not attempt to retrieve a cached catalog again if the first attempt failed" do
726
637
  expect(Puppet::Node.indirection).to receive(:find).and_return(nil)
727
638
  expects_neither_new_or_cached_catalog
728
639
 
729
- @agent.run
640
+ # after failing to use a cached catalog, we'll need to pluginsync before getting
641
+ # a new catalog, which also fails.
642
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
643
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
644
+
645
+ configurer.run
730
646
  end
731
647
 
732
648
  it "should return the cached catalog when the environment doesn't match" do
733
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
649
+ cached_catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote('second_env'))
734
650
  expects_cached_catalog_only(cached_catalog)
735
651
 
652
+ allow(Puppet).to receive(:info)
736
653
  expect(Puppet).to receive(:info).with("Using cached catalog from environment 'second_env'")
737
- expect(@agent.retrieve_catalog({})).to eq(cached_catalog)
654
+
655
+ configurer.run
656
+ end
657
+
658
+ it "applies the catalog passed as options when the catalog cache terminus is not set" do
659
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
660
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
661
+
662
+ catalog.add_resource(Puppet::Resource.new('notify', 'from apply'))
663
+ configurer.run(catalog: catalog.to_ral)
664
+
665
+ # make sure cache class is not set to avoid surprises later
666
+ expect(Puppet::Resource::Catalog.indirection).to_not be_cache
667
+ expect(@logs).to include(an_object_having_attributes(level: :notice, message: /defined 'message' as 'from apply'/))
668
+ end
669
+
670
+ it "applies the cached catalog when the catalog cache terminus is set, ignoring the catalog passed as options" do
671
+ Puppet::Resource::Catalog.indirection.cache_class = :json
672
+
673
+ cached_catalog = Puppet::Resource::Catalog.new(Puppet[:node_name_value], Puppet[:environment])
674
+ cached_catalog.add_resource(Puppet::Resource.new('notify', 'from cache'))
675
+
676
+ # update cached catalog
677
+ Puppet.settings.use(:main, :agent)
678
+ path = Puppet::Resource::Catalog.indirection.cache.path(cached_catalog.name)
679
+ FileUtils.mkdir(File.dirname(path))
680
+ File.write(path, cached_catalog.render(:json))
681
+
682
+ configurer.run(catalog: catalog.to_ral)
683
+
684
+ expect(@logs).to include(an_object_having_attributes(level: :notice, message: /defined 'message' as 'from cache'/))
738
685
  end
739
686
  end
740
687
 
741
688
  describe "and strict environment mode is set" do
742
689
  before do
743
- allow(@catalog).to receive(:to_ral).and_return(@catalog)
744
- allow(@catalog).to receive(:write_class_file)
745
- allow(@catalog).to receive(:write_resource_file)
746
- allow(@agent).to receive(:send_report)
747
- allow(@agent).to receive(:save_last_run_summary)
748
690
  Puppet.settings[:strict_environment_mode] = true
749
691
  end
750
692
 
751
693
  it "should not make a node request" do
752
- expects_new_catalog_only(@catalog)
694
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/plugins}).to_return(:status => 404)
695
+ stub_request(:get, %r{/puppet/v3/file_metadatas?/pluginfacts}).to_return(:status => 404)
696
+ expects_new_catalog_only(catalog)
697
+
753
698
  expect(Puppet::Node.indirection).not_to receive(:find)
754
699
 
755
- @agent.run
700
+ configurer.run
756
701
  end
757
702
 
758
703
  it "should return nil when the catalog's environment doesn't match the agent specified environment" do
759
- @agent.instance_variable_set(:@environment, 'second_env')
760
- expects_new_catalog_only(@catalog)
704
+ Puppet[:environment] = 'second_env'
705
+ configurer = Puppet::Configurer.new
706
+
707
+ catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote("production"))
708
+ expects_new_catalog_only(catalog)
761
709
 
762
710
  expect(Puppet).to receive(:err).with("Not using catalog because its environment 'production' does not match agent specified environment 'second_env' and strict_environment_mode is set")
763
- expect(@agent.run).to be_nil
711
+ expect(configurer.run).to be_nil
764
712
  end
765
713
 
766
- it "should not return nil when the catalog's environment matches the agent specified environment" do
767
- @agent.instance_variable_set(:@environment, 'production')
768
- expects_new_catalog_only(@catalog)
714
+ it "should return 0 when the catalog's environment matches the agent specified environment" do
715
+ expects_new_catalog_only(catalog)
769
716
 
770
- expect(@agent.run).to eq(0)
717
+ expect(configurer.run).to eq(0)
771
718
  end
772
719
 
773
720
  describe "and a cached catalog is explicitly requested" do
@@ -776,83 +723,81 @@ describe Puppet::Configurer do
776
723
  end
777
724
 
778
725
  it "should return nil when the cached catalog's environment doesn't match the agent specified environment" do
779
- @agent.instance_variable_set(:@environment, 'second_env')
780
- expects_cached_catalog_only(@catalog)
726
+ Puppet[:environment] = 'second_env'
727
+ configurer = Puppet::Configurer.new
728
+
729
+ catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote("production"))
730
+ expects_cached_catalog_only(catalog)
781
731
 
782
732
  expect(Puppet).to receive(:err).with("Not using catalog because its environment 'production' does not match agent specified environment 'second_env' and strict_environment_mode is set")
783
- expect(@agent.run).to be_nil
733
+ expect(configurer.run).to be_nil
784
734
  end
785
735
 
786
736
  it "should proceed with the cached catalog if its environment matchs the local environment" do
787
- Puppet.settings[:use_cached_catalog] = true
788
- @agent.instance_variable_set(:@environment, 'production')
789
- expects_cached_catalog_only(@catalog)
737
+ expects_cached_catalog_only(catalog)
790
738
 
791
- expect(@agent.run).to eq(0)
739
+ expect(configurer.run).to eq(0)
792
740
  end
793
741
  end
794
742
  end
795
743
 
796
- it "should use the Catalog class to get its catalog" do
797
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(@catalog)
798
-
799
- @agent.retrieve_catalog({})
800
- end
801
-
802
744
  it "should set its cached_catalog_status to 'not_used' when downloading a new catalog" do
803
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(@catalog)
745
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(catalog)
804
746
 
805
- @agent.retrieve_catalog({})
806
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
747
+ options = {}
748
+ configurer.run(options)
749
+
750
+ expect(options[:report].cached_catalog_status).to eq('not_used')
807
751
  end
808
752
 
809
753
  it "should use its node_name_value to retrieve the catalog" do
810
- allow(Facter).to receive(:value).and_return("eh")
811
- Puppet.settings[:node_name_value] = "myhost.domain.com"
812
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with("myhost.domain.com", anything).and_return(@catalog)
754
+ myhost_facts = Puppet::Node::Facts.new("myhost.domain.com")
755
+ Puppet::Node::Facts.indirection.save(myhost_facts)
813
756
 
814
- @agent.retrieve_catalog({})
815
- end
816
-
817
- it "should default to returning a catalog retrieved directly from the server, skipping the cache" do
818
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(@catalog)
757
+ Puppet.settings[:node_name_value] = "myhost.domain.com"
758
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with("myhost.domain.com", anything).and_return(catalog)
819
759
 
820
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
760
+ configurer.run
821
761
  end
822
762
 
823
- it "should log and return the cached catalog when no catalog can be retrieved from the server" do
824
- expects_fallback_to_cached_catalog(@catalog)
763
+ it "should log when no catalog can be retrieved from the server" do
764
+ expects_fallback_to_cached_catalog(catalog)
825
765
 
766
+ allow(Puppet).to receive(:info)
826
767
  expect(Puppet).to receive(:info).with("Using cached catalog from environment 'production'")
827
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
768
+ configurer.run
828
769
  end
829
770
 
830
771
  it "should set its cached_catalog_status to 'on_failure' when no catalog can be retrieved from the server" do
831
- expects_fallback_to_cached_catalog(@catalog)
772
+ expects_fallback_to_cached_catalog(catalog)
832
773
 
833
- @agent.retrieve_catalog({})
834
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('on_failure')
774
+ options = {}
775
+ configurer.run(options)
776
+
777
+ expect(options[:report].cached_catalog_status).to eq('on_failure')
835
778
  end
836
779
 
837
780
  it "should not look in the cache for a catalog if one is returned from the server" do
838
- expects_new_catalog_only(@catalog)
781
+ expects_new_catalog_only(catalog)
839
782
 
840
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
783
+ configurer.run
841
784
  end
842
785
 
843
786
  it "should return the cached catalog when retrieving the remote catalog throws an exception" do
844
787
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_raise("eh")
845
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(@catalog)
788
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(catalog)
846
789
 
847
- expect(@agent.retrieve_catalog({})).to eq(@catalog)
790
+ configurer.run
848
791
  end
849
792
 
850
793
  it "should set its cached_catalog_status to 'on_failure' when retrieving the remote catalog throws an exception" do
851
794
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_raise("eh")
852
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(@catalog)
795
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_terminus: true)).and_return(catalog)
796
+
797
+ options = {}
798
+ configurer.run(options)
853
799
 
854
- @agent.retrieve_catalog({})
855
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('on_failure')
800
+ expect(options[:report].cached_catalog_status).to eq('on_failure')
856
801
  end
857
802
 
858
803
  it "should log and return nil if no catalog can be retrieved from the server and :usecacheonfailure is disabled" do
@@ -861,120 +806,173 @@ describe Puppet::Configurer do
861
806
 
862
807
  expect(Puppet).to receive(:warning).with('Not using cache on failed catalog')
863
808
 
864
- expect(@agent.retrieve_catalog({})).to be_nil
809
+ expect(configurer.run).to be_nil
865
810
  end
866
811
 
867
812
  it "should set its cached_catalog_status to 'not_used' if no catalog can be retrieved from the server and :usecacheonfailure is disabled or fails to retrieve a catalog" do
868
813
  Puppet[:usecacheonfailure] = false
869
814
  expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true)).and_return(nil)
870
815
 
871
- @agent.retrieve_catalog({})
872
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
816
+ options = {}
817
+ configurer.run(options)
818
+
819
+ expect(options[:report].cached_catalog_status).to eq('not_used')
873
820
  end
874
821
 
875
822
  it "should return nil if no cached catalog is available and no catalog can be retrieved from the server" do
876
823
  expects_neither_new_or_cached_catalog
877
824
 
878
- expect(@agent.retrieve_catalog({})).to be_nil
825
+ expect(configurer.run).to be_nil
879
826
  end
880
827
 
881
828
  it "should return nil if its cached catalog environment doesn't match server-specified environment" do
882
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
883
- @agent.instance_variable_set(:@node_environment, 'production')
829
+ cached_catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote('second_env'))
884
830
 
885
831
  expects_fallback_to_cached_catalog(cached_catalog)
886
832
 
833
+ allow(Puppet).to receive(:err)
887
834
  expect(Puppet).to receive(:err).with("Not using cached catalog because its environment 'second_env' does not match 'production'")
888
- expect(@agent.retrieve_catalog({})).to be_nil
835
+ expect(configurer.run).to be_nil
889
836
  end
890
837
 
891
838
  it "should set its cached_catalog_status to 'not_used' if the cached catalog environment doesn't match server-specified environment" do
892
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote('second_env'))
893
- @agent.instance_variable_set(:@node_environment, 'production')
839
+ cached_catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote('second_env'))
894
840
 
895
841
  expects_fallback_to_cached_catalog(cached_catalog)
896
842
 
897
- @agent.retrieve_catalog({})
898
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('not_used')
899
- end
900
-
901
- it "should return its cached catalog if the environment matches the server-specified environment" do
902
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment]))
903
- @agent.instance_variable_set(:@node_environment, cached_catalog.environment)
904
-
905
- expects_fallback_to_cached_catalog(cached_catalog)
906
-
907
- expect(@agent.retrieve_catalog({})).to eq(cached_catalog)
843
+ options = {}
844
+ configurer.run(options)
845
+ expect(options[:report].cached_catalog_status).to eq('not_used')
908
846
  end
909
847
 
910
848
  it "should set its cached_catalog_status to 'on_failure' if the cached catalog environment matches server-specified environment" do
911
- cached_catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment]))
912
- @agent.instance_variable_set(:@node_environment, cached_catalog.environment)
913
-
914
- expects_fallback_to_cached_catalog(cached_catalog)
849
+ expects_fallback_to_cached_catalog(catalog)
915
850
 
916
- @agent.retrieve_catalog({})
917
- expect(@agent.instance_variable_get(:@cached_catalog_status)).to eq('on_failure')
851
+ options = {}
852
+ configurer.run(options)
853
+ expect(options[:report].cached_catalog_status).to eq('on_failure')
918
854
  end
919
855
 
920
856
  it "should not update the cached catalog in noop mode" do
921
857
  Puppet[:noop] = true
922
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true, ignore_cache_save: true)).and_return(@catalog)
923
858
 
924
- @agent.retrieve_catalog({})
859
+ stub_request(:post, %r{/puppet/v3/catalog}).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'})
860
+
861
+ Puppet::Resource::Catalog.indirection.cache_class = :json
862
+ path = Puppet::Resource::Catalog.indirection.cache.path(catalog.name)
863
+
864
+ expect(File).to_not be_exist(path)
865
+ configurer.run
866
+ expect(File).to_not be_exist(path)
925
867
  end
926
868
 
927
869
  it "should update the cached catalog when not in noop mode" do
928
870
  Puppet[:noop] = false
929
- expect(Puppet::Resource::Catalog.indirection).to receive(:find).with(anything, hash_including(ignore_cache: true, ignore_cache_save: false)).and_return(@catalog)
871
+ Puppet[:log_level] = 'info'
872
+
873
+ stub_request(:post, %r{/puppet/v3/catalog}).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'})
874
+
875
+ Puppet::Resource::Catalog.indirection.cache_class = :json
876
+ cache_path = Puppet::Resource::Catalog.indirection.cache.path(Puppet[:node_name_value])
877
+
878
+ expect(File).to_not be_exist(cache_path)
879
+ configurer.run
880
+ expect(File).to be_exist(cache_path)
881
+
882
+ expect(@logs).to include(an_object_having_attributes(level: :info, message: "Caching catalog for #{Puppet[:node_name_value]}"))
883
+ end
884
+
885
+ it "successfully applies the catalog without a cache" do
886
+ stub_request(:post, %r{/puppet/v3/catalog}).to_return(:status => 200, :body => catalog.render(:json), :headers => {'Content-Type' => 'application/json'})
887
+
888
+ Puppet::Resource::Catalog.indirection.cache_class = nil
889
+
890
+ expect(configurer.run).to eq(0)
891
+ end
892
+
893
+ it "should not update the cached catalog when running puppet apply" do
894
+ Puppet::Resource::Catalog.indirection.cache_class = :json
895
+ path = Puppet::Resource::Catalog.indirection.cache.path(catalog.name)
930
896
 
931
- @agent.retrieve_catalog({})
897
+ expect(File).to_not be_exist(path)
898
+ configurer.run(catalog: catalog)
899
+ expect(File).to_not be_exist(path)
932
900
  end
933
901
  end
934
902
 
935
- describe "when converting the catalog" do
936
- before do
937
- allow(Puppet.settings).to receive(:use).and_return(true)
903
+ describe "when converging the environment" do
904
+ let(:apple) { Puppet::Resource::Catalog.new(Puppet[:node_name_value], Puppet::Node::Environment.remote('apple')) }
905
+ let(:banana) { Puppet::Resource::Catalog.new(Puppet[:node_name_value], Puppet::Node::Environment.remote('banana')) }
938
906
 
939
- allow(catalog).to receive(:to_ral).and_return(ral_catalog)
907
+ before :each do
908
+ apple.add_resource(resource)
909
+ banana.add_resource(resource)
940
910
  end
941
911
 
942
- let (:catalog) { Puppet::Resource::Catalog.new('tester', Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) }
943
- let (:ral_catalog) { Puppet::Resource::Catalog.new('tester', Puppet::Node::Environment.remote(Puppet[:environment].to_sym)) }
912
+ it "converges after multiple attempts" do
913
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(apple, banana, banana)
914
+
915
+ allow(Puppet).to receive(:notice)
916
+ expect(Puppet).to receive(:notice).with("Local environment: 'production' doesn't match server specified environment 'apple', restarting agent run with environment 'apple'")
917
+ expect(Puppet).to receive(:notice).with("Local environment: 'apple' doesn't match server specified environment 'banana', restarting agent run with environment 'banana'")
944
918
 
945
- it "should convert the catalog to a RAL-formed catalog" do
946
- expect(@agent.convert_catalog(catalog, 10)).to equal(ral_catalog)
919
+ configurer.run
947
920
  end
948
921
 
949
- it "should finalize the catalog" do
950
- expect(ral_catalog).to receive(:finalize)
922
+ it "raises if it can't converge after 4 tries after the initial catalog request" do
923
+ expect(Puppet::Resource::Catalog.indirection).to receive(:find).and_return(apple, banana, apple, banana, apple)
951
924
 
952
- @agent.convert_catalog(catalog, 10)
925
+ configurer.run
926
+
927
+ expect(@logs).to include(an_object_having_attributes(level: :err, message: "Failed to apply catalog: Catalog environment didn't stabilize after 4 fetches, aborting run"))
953
928
  end
929
+ end
954
930
 
955
- it "should record the passed retrieval time with the RAL catalog" do
956
- expect(ral_catalog).to receive(:retrieval_duration=).with(10)
931
+ describe "when converting the catalog" do
932
+ it "converts Puppet::Resource into Puppet::Type::Notify" do
933
+ expect(configurer).to receive(:apply_catalog) do |ral, _|
934
+ expect(ral.resources).to contain(an_instance_of(Puppet::Type::Notify))
935
+ end
957
936
 
958
- @agent.convert_catalog(catalog, 10)
937
+ configurer.run(catalog: catalog)
959
938
  end
960
939
 
961
- it "should write the RAL catalog's class file" do
962
- expect(ral_catalog).to receive(:write_class_file)
940
+ it "adds default schedules" do
941
+ expect(configurer).to receive(:apply_catalog) do |ral, _|
942
+ expect(ral.resources.map(&:to_ref)).to contain(%w{Schedule[puppet] Schedule[hourly] Schedule[daily] Schedule[weekly] Schedule[monthly] Schedule[never]})
943
+ end
944
+
945
+ configurer.run
946
+ end
947
+
948
+ it "records the retrieval duration to the catalog" do
949
+ expect(configurer).to receive(:apply_catalog) do |ral, _|
950
+ expect(ral.retrieval_duration).to be_an_instance_of(Float)
951
+ end
963
952
 
964
- @agent.convert_catalog(catalog, 10)
953
+ configurer.run
965
954
  end
966
955
 
967
- it "should write the RAL catalog's resource file" do
968
- expect(ral_catalog).to receive(:write_resource_file)
956
+ it "writes the class file containing applied settings classes" do
957
+ expect(File).to_not be_exist(Puppet[:classfile])
958
+
959
+ configurer.run
969
960
 
970
- @agent.convert_catalog(catalog, 10)
961
+ expect(File.read(Puppet[:classfile]).chomp).to eq('settings')
971
962
  end
972
963
 
973
- it "should set catalog conversion time on the report" do
974
- report = Puppet::Transaction::Report.new
964
+ it "writes an empty resource file since no resources are 'managed'" do
965
+ expect(File).to_not be_exist(Puppet[:resourcefile])
975
966
 
976
- expect(report).to receive(:add_times).with(:convert_catalog, kind_of(Numeric))
977
- @agent.convert_catalog(catalog, 10, {:report => report})
967
+ configurer.run
968
+
969
+ expect(File.read(Puppet[:resourcefile]).chomp).to eq("")
970
+ end
971
+
972
+ it "adds the conversion time to the report" do
973
+ configurer.run(report: report)
974
+
975
+ expect(report.metrics['time']['convert_catalog']).to be_an_instance_of(Float)
978
976
  end
979
977
  end
980
978
 
@@ -995,66 +993,62 @@ describe Puppet::Configurer do
995
993
  describe "when attempting failover" do
996
994
  it "should not failover if server_list is not set" do
997
995
  Puppet.settings[:server_list] = []
998
- expect(@agent).not_to receive(:find_functional_server)
999
- @agent.run
996
+ configurer.run
1000
997
  end
1001
998
 
1002
999
  it "should not failover during an apply run" do
1003
1000
  Puppet.settings[:server_list] = ["myserver:123"]
1004
- expect(@agent).not_to receive(:find_functional_server)
1005
- catalog = Puppet::Resource::Catalog.new("tester", Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
1006
- @agent.run :catalog => catalog
1001
+ catalog = Puppet::Resource::Catalog.new(node_name, Puppet::Node::Environment.remote(Puppet[:environment].to_sym))
1002
+ configurer.run(catalog: catalog)
1007
1003
  end
1008
1004
 
1009
1005
  it "should select a server when it receives 200 OK response" do
1010
1006
  Puppet.settings[:server_list] = ["myserver:123"]
1011
- response = Net::HTTPOK.new(nil, 200, 'OK')
1012
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
1013
- allow(@agent).to receive(:run_internal)
1007
+
1008
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: 200)
1014
1009
 
1015
1010
  options = {}
1016
- @agent.run(options)
1011
+ configurer.run(options)
1017
1012
  expect(options[:report].master_used).to eq('myserver:123')
1018
1013
  end
1019
1014
 
1020
- it "queries the simple status for the 'master' service" do
1021
- Puppet.settings[:server_list] = ["myserver:123"]
1022
- response = Net::HTTPOK.new(nil, 200, 'OK')
1023
- http = double('request')
1024
- expect(http).to receive(:get).with('/status/v1/simple/master').and_return(response)
1025
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(http)
1026
- allow(@agent).to receive(:run_internal)
1027
-
1028
- @agent.run
1029
- end
1030
-
1031
1015
  it "should report when a server is unavailable" do
1032
1016
  Puppet.settings[:server_list] = ["myserver:123"]
1033
- response = Net::HTTPInternalServerError.new(nil, 500, 'Internal Server Error')
1034
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
1035
1017
 
1018
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: [500, "Internal Server Error"])
1019
+
1020
+ allow(Puppet).to receive(:debug)
1036
1021
  expect(Puppet).to receive(:debug).with("Puppet server myserver:123 is unavailable: 500 Internal Server Error")
1037
- expect{ @agent.run }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list/)
1022
+
1023
+ expect {
1024
+ configurer.run
1025
+ }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list:/)
1038
1026
  end
1039
1027
 
1040
1028
  it "should error when no servers in 'server_list' are reachable" do
1041
- Puppet.settings[:server_list] = ["myserver:123"]
1042
- error = Net::HTTPError.new(400, 'dummy server communication error')
1043
- allow(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: error))
1029
+ Puppet.settings[:server_list] = "myserver:123,someotherservername"
1044
1030
 
1045
- options = {}
1046
- expect{ @agent.run(options) }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list/)
1047
- expect(options[:report].master_used).to be_nil
1031
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: 400)
1032
+ stub_request(:get, 'https://someotherservername:8140/status/v1/simple/master').to_return(status: 400)
1033
+
1034
+ expect{
1035
+ configurer.run
1036
+ }.to raise_error(Puppet::Error, /Could not select a functional puppet master from server_list: 'myserver:123,someotherservername'/)
1048
1037
  end
1049
1038
 
1050
1039
  it "should not make multiple node requests when the server is found" do
1051
1040
  Puppet.settings[:server_list] = ["myserver:123"]
1052
- response = Net::HTTPOK.new(nil, 200, 'OK')
1053
1041
 
1054
- expect(Puppet::Network::HttpPool).to receive(:connection).with('myserver', 123, anything).and_return(double('request', get: response))
1055
- allow(@agent).to receive(:run_internal)
1042
+ Puppet::Node.indirection.terminus_class = :rest
1043
+ Puppet::Resource::Catalog.indirection.terminus_class = :rest
1044
+
1045
+ stub_request(:get, 'https://myserver:123/status/v1/simple/master').to_return(status: 200)
1046
+ stub_request(:post, %r{https://myserver:123/puppet/v3/catalog}).to_return(status: 200)
1047
+ node_request = stub_request(:get, %r{https://myserver:123/puppet/v3/node/}).to_return(status: 200)
1048
+
1049
+ configurer.run
1056
1050
 
1057
- @agent.run
1051
+ expect(node_request).to have_been_requested.once
1058
1052
  end
1059
1053
  end
1060
1054
  end