hybrid_platforms_conductor 32.17.0 → 33.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/README.md +6 -3
  4. data/bin/check-node +0 -1
  5. data/bin/deploy +0 -1
  6. data/bin/get_impacted_nodes +0 -1
  7. data/bin/last_deploys +12 -8
  8. data/bin/nodes_to_deploy +6 -6
  9. data/bin/setup +6 -6
  10. data/bin/topograph +1 -1
  11. data/docs/config_dsl.md +45 -1
  12. data/docs/executables.md +6 -7
  13. data/docs/executables/check-node.md +3 -3
  14. data/docs/executables/deploy.md +3 -3
  15. data/docs/executables/dump_nodes_json.md +3 -3
  16. data/docs/executables/test.md +3 -3
  17. data/docs/executables/topograph.md +3 -3
  18. data/docs/gen/mermaid/README.md-0.png +0 -0
  19. data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
  20. data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
  21. data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
  22. data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
  23. data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
  24. data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
  25. data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
  26. data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
  27. data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
  28. data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
  29. data/docs/plugins.md +46 -0
  30. data/docs/plugins/connector/ssh.md +1 -1
  31. data/docs/plugins/log/remote_fs.md +26 -0
  32. data/docs/plugins/secrets_reader/cli.md +31 -0
  33. data/docs/plugins/secrets_reader/thycotic.md +46 -0
  34. data/docs/plugins/test/check_deploy_and_idempotence.md +1 -1
  35. data/docs/plugins/test/connection.md +1 -0
  36. data/docs/plugins/test/deploy_removes_root_access.md +1 -1
  37. data/docs/plugins/test/file_system.md +1 -0
  38. data/docs/plugins/test/hostname.md +1 -0
  39. data/docs/plugins/test/ip.md +1 -0
  40. data/docs/plugins/test/local_users.md +1 -0
  41. data/docs/plugins/test/mounts.md +1 -0
  42. data/docs/plugins/test/orphan_files.md +1 -0
  43. data/docs/plugins/test/ports.md +1 -0
  44. data/docs/plugins/test/spectre.md +1 -0
  45. data/docs/plugins/test/vulnerabilities.md +1 -0
  46. data/lib/hybrid_platforms_conductor/action.rb +4 -4
  47. data/lib/hybrid_platforms_conductor/actions_executor.rb +45 -43
  48. data/lib/hybrid_platforms_conductor/bitbucket.rb +5 -4
  49. data/lib/hybrid_platforms_conductor/cmd_runner.rb +13 -12
  50. data/lib/hybrid_platforms_conductor/cmdb.rb +2 -2
  51. data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +2 -1
  52. data/lib/hybrid_platforms_conductor/common_config_dsl/confluence.rb +2 -1
  53. data/lib/hybrid_platforms_conductor/common_config_dsl/file_system_tests.rb +5 -4
  54. data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +4 -3
  55. data/lib/hybrid_platforms_conductor/common_config_dsl/idempotence_tests.rb +2 -2
  56. data/lib/hybrid_platforms_conductor/config.rb +8 -4
  57. data/lib/hybrid_platforms_conductor/confluence.rb +1 -1
  58. data/lib/hybrid_platforms_conductor/connector.rb +5 -2
  59. data/lib/hybrid_platforms_conductor/core_extensions/cleanroom/fix_kwargs.rb +116 -0
  60. data/lib/hybrid_platforms_conductor/core_extensions/symbol/zero.rb +24 -0
  61. data/lib/hybrid_platforms_conductor/credentials.rb +39 -36
  62. data/lib/hybrid_platforms_conductor/current_dir_monitor.rb +4 -1
  63. data/lib/hybrid_platforms_conductor/deployer.rb +275 -224
  64. data/lib/hybrid_platforms_conductor/executable.rb +20 -15
  65. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/config.rb +10 -7
  66. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_ip.rb +1 -1
  67. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +2 -2
  68. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/platform_handlers.rb +4 -4
  69. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +2 -0
  70. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +45 -49
  71. data/lib/hybrid_platforms_conductor/hpc_plugins/log/my_log_plugin.rb.sample +100 -0
  72. data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +180 -0
  73. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +68 -66
  74. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +13 -0
  75. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +39 -38
  76. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/yaml_inventory.rb +5 -4
  77. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +43 -45
  78. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +18 -20
  79. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +118 -117
  80. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/proxmox_waiter.rb +39 -43
  81. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +9 -13
  82. data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +2 -2
  83. data/lib/hybrid_platforms_conductor/hpc_plugins/report/mediawiki.rb +28 -21
  84. data/lib/hybrid_platforms_conductor/hpc_plugins/report/stdout.rb +26 -22
  85. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/cli.rb +77 -0
  86. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/my_secrets_reader_plugin.rb.sample +46 -0
  87. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +90 -0
  88. data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +3 -3
  89. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +4 -2
  90. data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +3 -1
  91. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +7 -21
  92. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +21 -19
  93. data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +2 -2
  94. data/lib/hybrid_platforms_conductor/hpc_plugins/test/executables.rb +2 -2
  95. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +21 -22
  96. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system_hdfs.rb +19 -21
  97. data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +2 -3
  98. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +3 -1
  99. data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +2 -2
  100. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +4 -2
  101. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +21 -22
  102. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +10 -12
  103. data/lib/hybrid_platforms_conductor/hpc_plugins/test/linear_strategy.rb +9 -9
  104. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +5 -3
  105. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +5 -3
  106. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +13 -10
  107. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +5 -3
  108. data/lib/hybrid_platforms_conductor/hpc_plugins/test/private_ips.rb +5 -5
  109. data/lib/hybrid_platforms_conductor/hpc_plugins/test/public_ips.rb +5 -5
  110. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +7 -7
  111. data/lib/hybrid_platforms_conductor/hpc_plugins/test/veids.rb +3 -3
  112. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +27 -25
  113. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +2 -2
  114. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/stdout.rb +8 -6
  115. data/lib/hybrid_platforms_conductor/io_router.rb +14 -13
  116. data/lib/hybrid_platforms_conductor/json_dumper.rb +2 -2
  117. data/lib/hybrid_platforms_conductor/log.rb +31 -0
  118. data/lib/hybrid_platforms_conductor/logger_helpers.rb +19 -16
  119. data/lib/hybrid_platforms_conductor/nodes_handler.rb +89 -71
  120. data/lib/hybrid_platforms_conductor/parallel_threads.rb +7 -11
  121. data/lib/hybrid_platforms_conductor/platform_handler.rb +7 -7
  122. data/lib/hybrid_platforms_conductor/platforms_handler.rb +5 -3
  123. data/lib/hybrid_platforms_conductor/plugin.rb +2 -2
  124. data/lib/hybrid_platforms_conductor/plugins.rb +14 -8
  125. data/lib/hybrid_platforms_conductor/provisioner.rb +4 -4
  126. data/lib/hybrid_platforms_conductor/report.rb +2 -2
  127. data/lib/hybrid_platforms_conductor/reports_handler.rb +3 -2
  128. data/lib/hybrid_platforms_conductor/secrets_reader.rb +31 -0
  129. data/lib/hybrid_platforms_conductor/services_handler.rb +32 -29
  130. data/lib/hybrid_platforms_conductor/test_only_remote_node.rb +18 -0
  131. data/lib/hybrid_platforms_conductor/test_report.rb +15 -18
  132. data/lib/hybrid_platforms_conductor/tests_runner.rb +116 -118
  133. data/lib/hybrid_platforms_conductor/thycotic.rb +28 -19
  134. data/lib/hybrid_platforms_conductor/topographer.rb +200 -190
  135. data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +8 -8
  136. data/lib/hybrid_platforms_conductor/topographer/plugins/json.rb +4 -4
  137. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  138. data/spec/hybrid_platforms_conductor_test.rb +33 -12
  139. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +18 -11
  140. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/interactive_spec.rb +2 -2
  141. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -21
  142. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/ruby_spec.rb +75 -49
  143. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/scp_spec.rb +27 -15
  144. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions_spec.rb +90 -59
  145. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connection_spec.rb +46 -44
  146. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/connectable_nodes_spec.rb +12 -8
  147. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +4 -7
  148. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +21 -22
  149. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +23 -24
  150. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connectable_nodes_spec.rb +10 -6
  151. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +106 -75
  152. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +145 -126
  153. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +3 -3
  154. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +29 -25
  155. data/spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb +167 -142
  156. data/spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb +272 -244
  157. data/spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb +16 -16
  158. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +36 -36
  159. data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +24 -22
  160. data/spec/hybrid_platforms_conductor_test/api/deployer/check_spec.rb +4 -2
  161. data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +43 -5
  162. data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +199 -216
  163. data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +223 -0
  164. data/spec/hybrid_platforms_conductor_test/api/deployer/parse_deploy_output_spec.rb +55 -59
  165. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +36 -62
  166. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/podman_spec.rb +17 -17
  167. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/config_dsl_spec.rb +4 -4
  168. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/create_spec.rb +44 -51
  169. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/destroy_spec.rb +3 -3
  170. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/ip_spec.rb +12 -16
  171. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/destroy_vm_spec.rb +31 -19
  172. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/expired_containers_spec.rb +324 -266
  173. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/ips_assignment_spec.rb +89 -61
  174. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/other_lxc_containers_resources_spec.rb +117 -93
  175. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/pve_node_resources_spec.rb +71 -54
  176. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/retries_spec.rb +10 -8
  177. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/vm_ids_assignment_spec.rb +80 -60
  178. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/start_spec.rb +1 -1
  179. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/state_spec.rb +1 -1
  180. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/stop_spec.rb +1 -1
  181. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/cli_spec.rb +64 -0
  182. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +268 -0
  183. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/config_spec.rb +8 -10
  184. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_ip_spec.rb +33 -24
  185. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +64 -51
  186. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb +3 -3
  187. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +50 -51
  188. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +91 -81
  189. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/config_dsl_spec.rb +14 -16
  190. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +51 -75
  191. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +35 -26
  192. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb +24 -16
  193. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/several_platforms_spec.rb +29 -19
  194. data/spec/hybrid_platforms_conductor_test/api/platform_handler_spec.rb +4 -4
  195. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb +2 -2
  196. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/deploy_output_parsing_spec.rb +6 -6
  197. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +57 -99
  198. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/inventory_spec.rb +4 -4
  199. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/packaging_spec.rb +32 -35
  200. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +10 -10
  201. data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +38 -27
  202. data/spec/hybrid_platforms_conductor_test/api/plugins_spec.rb +46 -52
  203. data/spec/hybrid_platforms_conductor_test/api/reports_handler_spec.rb +2 -2
  204. data/spec/hybrid_platforms_conductor_test/api/services_handler/actions_to_deploy_spec.rb +90 -58
  205. data/spec/hybrid_platforms_conductor_test/api/services_handler/deploy_allowed_spec.rb +38 -34
  206. data/spec/hybrid_platforms_conductor_test/api/services_handler/log_info_spec.rb +11 -9
  207. data/spec/hybrid_platforms_conductor_test/api/services_handler/package_spec.rb +193 -171
  208. data/spec/hybrid_platforms_conductor_test/api/services_handler/parse_deploy_output_spec.rb +66 -54
  209. data/spec/hybrid_platforms_conductor_test/api/services_handler/prepare_for_deploy_spec.rb +147 -133
  210. data/spec/hybrid_platforms_conductor_test/api/tests_runner/common_spec.rb +69 -49
  211. data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +5 -4
  212. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_check_spec.rb +8 -5
  213. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_spec.rb +8 -5
  214. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_ssh_spec.rb +30 -27
  215. data/spec/hybrid_platforms_conductor_test/api/tests_runner/platform_spec.rb +12 -9
  216. data/spec/hybrid_platforms_conductor_test/api/tests_runner/reports_spec.rb +48 -47
  217. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +5 -5
  218. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +5 -5
  219. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_reports_plugins/confluence_spec.rb +5 -5
  220. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb.rb +9 -9
  221. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/{test_cmdb2.rb → test_cmdb_2.rb} +6 -6
  222. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others.rb +3 -3
  223. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/{test_cmdb_others2.rb → test_cmdb_others_2.rb} +2 -2
  224. data/spec/hybrid_platforms_conductor_test/docs_spec.rb +1 -1
  225. data/spec/hybrid_platforms_conductor_test/executables/{check-node_spec.rb → check_node_spec.rb} +4 -6
  226. data/spec/hybrid_platforms_conductor_test/executables/deploy_spec.rb +4 -6
  227. data/spec/hybrid_platforms_conductor_test/executables/get_impacted_nodes_spec.rb +76 -77
  228. data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +159 -113
  229. data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +299 -160
  230. data/spec/hybrid_platforms_conductor_test/executables/options/actions_executor_spec.rb +4 -6
  231. data/spec/hybrid_platforms_conductor_test/executables/options/cmd_runner_spec.rb +3 -5
  232. data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +8 -8
  233. data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +12 -196
  234. data/spec/hybrid_platforms_conductor_test/executables/options/nodes_handler_spec.rb +9 -10
  235. data/spec/hybrid_platforms_conductor_test/executables/options/nodes_selectors_spec.rb +9 -10
  236. data/spec/hybrid_platforms_conductor_test/executables/options/reports_handler_spec.rb +1 -1
  237. data/spec/hybrid_platforms_conductor_test/executables/options/tests_runner_spec.rb +22 -22
  238. data/spec/hybrid_platforms_conductor_test/executables/report_spec.rb +22 -16
  239. data/spec/hybrid_platforms_conductor_test/executables/run_spec.rb +32 -32
  240. data/spec/hybrid_platforms_conductor_test/executables/ssh_config_spec.rb +7 -9
  241. data/spec/hybrid_platforms_conductor_test/executables/test_spec.rb +3 -5
  242. data/spec/hybrid_platforms_conductor_test/helpers/actions_executor_helpers.rb +2 -2
  243. data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +4 -3
  244. data/spec/hybrid_platforms_conductor_test/helpers/cmdb_helpers.rb +2 -2
  245. data/spec/hybrid_platforms_conductor_test/helpers/config_helpers.rb +1 -1
  246. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +12 -13
  247. data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +245 -56
  248. data/spec/hybrid_platforms_conductor_test/helpers/executables_helpers.rb +11 -11
  249. data/spec/hybrid_platforms_conductor_test/helpers/nodes_handler_helpers.rb +1 -1
  250. data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +39 -28
  251. data/spec/hybrid_platforms_conductor_test/helpers/plugins_helpers.rb +1 -1
  252. data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +86 -111
  253. data/spec/hybrid_platforms_conductor_test/helpers/reports_handler_helpers.rb +1 -1
  254. data/spec/hybrid_platforms_conductor_test/helpers/serverless_chef_helpers.rb +3 -3
  255. data/spec/hybrid_platforms_conductor_test/helpers/services_handler_helpers.rb +1 -1
  256. data/spec/hybrid_platforms_conductor_test/helpers/tests_runner_helpers.rb +1 -1
  257. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/{test_plugin_id1.rb → test_plugin_id_1.rb} +0 -0
  258. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/{test_plugin_id2.rb → test_plugin_id_2.rb} +0 -0
  259. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type/{test_plugin_id3.rb → test_plugin_id_3.rb} +0 -0
  260. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/{test_plugin_type2/test_plugin_id4.rb → test_plugin_type_2/test_plugin_id_4.rb} +0 -0
  261. data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +1 -1
  262. data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/{test2.rb → test_2.rb} +0 -0
  263. data/spec/hybrid_platforms_conductor_test/rubocop_spec.rb +31 -0
  264. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json +3 -3
  265. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/nodes/node.json +3 -3
  266. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/libraries/default.rb +1 -0
  267. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/libraries/default.rb +1 -0
  268. data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +952 -0
  269. data/spec/hybrid_platforms_conductor_test/test_connector.rb +3 -3
  270. data/spec/hybrid_platforms_conductor_test/test_log_no_read_plugin.rb +84 -0
  271. data/spec/hybrid_platforms_conductor_test/test_log_plugin.rb +105 -0
  272. data/spec/hybrid_platforms_conductor_test/test_plugins/global.rb +1 -0
  273. data/spec/hybrid_platforms_conductor_test/test_plugins/node.rb +1 -0
  274. data/spec/hybrid_platforms_conductor_test/test_plugins/node_check.rb +1 -0
  275. data/spec/hybrid_platforms_conductor_test/test_plugins/platform.rb +1 -0
  276. data/spec/hybrid_platforms_conductor_test/test_plugins/several_checks.rb +2 -2
  277. data/spec/hybrid_platforms_conductor_test/test_secrets_reader_plugin.rb +45 -0
  278. data/spec/hybrid_platforms_conductor_test/tests_report_plugin.rb +5 -6
  279. data/spec/spec_helper.rb +17 -18
  280. data/tools/check_md +16 -20
  281. data/tools/generate_mermaid +1 -1
  282. metadata +195 -144
  283. data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +0 -916
@@ -18,7 +18,7 @@ module HybridPlatformsConductorTest
18
18
  # Result::
19
19
  # * ReportsHandler: ReportsHandler on which we can do testing
20
20
  def test_reports_handler
21
- @reports_handler = HybridPlatformsConductor::ReportsHandler.new logger: logger, logger_stderr: logger, config: test_config, platforms_handler: test_platforms_handler, nodes_handler: test_nodes_handler unless @reports_handler
21
+ @reports_handler ||= HybridPlatformsConductor::ReportsHandler.new logger: logger, logger_stderr: logger, config: test_config, platforms_handler: test_platforms_handler, nodes_handler: test_nodes_handler
22
22
  @reports_handler
23
23
  end
24
24
 
@@ -27,18 +27,18 @@ module HybridPlatformsConductorTest
27
27
  FileUtils.cp_r "#{__dir__}/../serverless_chef_repositories/#{names[name]}/.", repository
28
28
  end
29
29
  with_platforms(repositories.values.map { |repository| "serverless_chef_platform path: '#{repository}'\n" }.join + additional_config) do
30
- repositories = Hash[names.keys.map do |name|
30
+ repositories = names.keys.map do |name|
31
31
  [
32
32
  test_platforms_handler.platform(name),
33
33
  repositories[name]
34
34
  ]
35
- end]
35
+ end.to_h
36
36
  test_platforms_handler.inject_dependencies(
37
37
  nodes_handler: test_nodes_handler,
38
38
  actions_executor: test_actions_executor
39
39
  )
40
40
  if repositories.size == 1
41
- yield *repositories.first
41
+ yield(*repositories.first)
42
42
  else
43
43
  yield repositories
44
44
  end
@@ -9,7 +9,7 @@ module HybridPlatformsConductorTest
9
9
  # Result::
10
10
  # * ServicesHandler: ServicesHandler on which we can do testing
11
11
  def test_services_handler
12
- @services_handler = HybridPlatformsConductor::ServicesHandler.new logger: logger, logger_stderr: logger, config: test_config, cmd_runner: test_cmd_runner, platforms_handler: test_platforms_handler, nodes_handler: test_nodes_handler, actions_executor: test_actions_executor unless @services_handler
12
+ @services_handler ||= HybridPlatformsConductor::ServicesHandler.new logger: logger, logger_stderr: logger, config: test_config, cmd_runner: test_cmd_runner, platforms_handler: test_platforms_handler, nodes_handler: test_nodes_handler, actions_executor: test_actions_executor
13
13
  @services_handler
14
14
  end
15
15
 
@@ -27,7 +27,7 @@ module HybridPlatformsConductorTest
27
27
  # Result::
28
28
  # * Deployer: Tests Runner on which we can do testing
29
29
  def test_tests_runner
30
- @tests_runner = HybridPlatformsConductor::TestsRunner.new logger: logger, logger_stderr: logger, config: test_config, cmd_runner: test_cmd_runner, platforms_handler: test_platforms_handler, nodes_handler: test_nodes_handler, actions_executor: test_actions_executor, deployer: test_deployer unless @tests_runner
30
+ @tests_runner ||= HybridPlatformsConductor::TestsRunner.new logger: logger, logger_stderr: logger, config: test_config, cmd_runner: test_cmd_runner, platforms_handler: test_platforms_handler, nodes_handler: test_nodes_handler, actions_executor: test_actions_executor, deployer: test_deployer
31
31
  @tests_runner
32
32
  end
33
33
 
@@ -202,7 +202,7 @@ module HybridPlatformsConductorTest
202
202
  def platform_info
203
203
  {
204
204
  nodes: {},
205
- nodes_lists: {},
205
+ nodes_lists: {}
206
206
  }.merge(HybridPlatformsConductorTest::PlatformHandlerPlugins::Test.platforms_info[name])
207
207
  end
208
208
 
@@ -0,0 +1,31 @@
1
+ require 'json'
2
+
3
+ describe 'Coding guidelines' do
4
+
5
+ it 'makes sure code style follow Rubocop guides' do
6
+ rubocop_report = JSON.parse(`bundle exec rubocop --format json`)
7
+ expect(rubocop_report['summary']['offense_count']).to(
8
+ eq(0),
9
+ proc do
10
+ # Format a great error message to help
11
+ wrong_files = rubocop_report['files'].reject { |file_info| file_info['offenses'].empty? }
12
+ <<~EO_ERROR
13
+ #{wrong_files.size} files have Rubocop issues:
14
+ #{
15
+ wrong_files.map do |file_info|
16
+ offenses = file_info['offenses'].map { |offense_info| "L#{offense_info['location']['start_line']}: #{offense_info['cop_name']} - #{offense_info['message']}" }
17
+ "* #{file_info['path']}:#{
18
+ if offenses.size == 1
19
+ " #{offenses.first}"
20
+ else
21
+ " #{offenses.size} offenses:\n#{offenses.map { |offense| " - #{offense}" }.join("\n")}"
22
+ end
23
+ }"
24
+ end.join("\n")
25
+ }
26
+ EO_ERROR
27
+ end
28
+ )
29
+ end
30
+
31
+ end
@@ -4,10 +4,10 @@
4
4
  "description": "Single test node",
5
5
  "image": "debian_9",
6
6
  "private_ips": ["172.16.0.1"],
7
- "property1": {
8
- "property11": "value11"
7
+ "property_1": {
8
+ "property_11": "value11"
9
9
  },
10
- "property2": "value2"
10
+ "property_2": "value2"
11
11
  },
12
12
  "policy_name": "test_policy",
13
13
  "policy_group": "test_group"
@@ -4,10 +4,10 @@
4
4
  "description": "Single test node",
5
5
  "image": "debian_9",
6
6
  "private_ips": ["172.16.0.1"],
7
- "property1": {
8
- "property11": "value11"
7
+ "property_1": {
8
+ "property_11": "value11"
9
9
  },
10
- "property2": "value2"
10
+ "property_2": "value2"
11
11
  },
12
12
  "policy_name": "test_policy",
13
13
  "policy_group": "test_group"
@@ -0,0 +1,952 @@
1
+ require 'timeout'
2
+
3
+ shared_examples 'a deployer' do
4
+
5
+ let(:expected_deploy_result) { [0, "#{check_mode ? 'Check' : 'Deploy'} successful", ''] }
6
+
7
+ before do
8
+ @check_mode = check_mode
9
+ end
10
+
11
+ it 'deploys on 1 node' do
12
+ with_platform_to_deploy do
13
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
14
+ end
15
+ end
16
+
17
+ it 'deploys on 1 node having several services' do
18
+ with_platform_to_deploy(nodes_info: { nodes: { 'node' => { services: %w[service1 service2 service3] } } }) do
19
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
20
+ end
21
+ end
22
+
23
+ it 'deploys on 1 node in a local environment' do
24
+ with_platform_to_deploy(expect_local_environment: true) do
25
+ test_deployer.local_environment = true
26
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
27
+ expect(test_deployer.local_environment).to eq true
28
+ end
29
+ end
30
+
31
+ it 'deploys on 1 node using root' do
32
+ with_platform_to_deploy(expect_sudo: nil) do
33
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
34
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
35
+ end
36
+ end
37
+
38
+ it 'deploys on 1 node using an alternate sudo' do
39
+ with_platform_to_deploy(
40
+ expect_sudo: 'other_sudo --user root',
41
+ additional_config: <<~'EO_CONFIG'
42
+ sudo_for { |user| "other_sudo --user #{user}" }
43
+ EO_CONFIG
44
+ ) do
45
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
46
+ end
47
+ end
48
+
49
+ it 'deploys on 1 node using 1 secret' do
50
+ with_platform_to_deploy(expect_secrets: { 'secret1' => 'password1' }) do
51
+ test_deployer.override_secrets('secret1' => 'password1')
52
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
53
+ end
54
+ end
55
+
56
+ it 'deploys on 1 node in local environment with certificates to install using hpc_certificates on Debian' do
57
+ with_certs_dir do |certs_dir|
58
+ with_platform_to_deploy(
59
+ nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
60
+ expect_local_environment: true,
61
+ expect_additional_actions: [
62
+ { remote_bash: 'sudo -u root apt update && sudo -u root apt install -y ca-certificates' },
63
+ {
64
+ remote_bash: 'sudo -u root update-ca-certificates',
65
+ scp: {
66
+ certs_dir => '/usr/local/share/ca-certificates',
67
+ :sudo => true
68
+ }
69
+ }
70
+ ]
71
+ ) do
72
+ ENV['hpc_certificates'] = certs_dir
73
+ test_deployer.local_environment = true
74
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
75
+ end
76
+ end
77
+ end
78
+
79
+ it 'deploys on 1 node in local environment with certificates to install using hpc_certificates on Debian and an alternate sudo' do
80
+ with_certs_dir do |certs_dir|
81
+ with_platform_to_deploy(
82
+ nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
83
+ expect_sudo: 'other_sudo --user root',
84
+ expect_local_environment: true,
85
+ expect_additional_actions: [
86
+ { remote_bash: 'other_sudo --user root apt update && other_sudo --user root apt install -y ca-certificates' },
87
+ {
88
+ remote_bash: 'other_sudo --user root update-ca-certificates',
89
+ scp: {
90
+ certs_dir => '/usr/local/share/ca-certificates',
91
+ :sudo => true
92
+ }
93
+ }
94
+ ],
95
+ additional_config: <<~'EO_CONFIG'
96
+ sudo_for { |user| "other_sudo --user #{user}" }
97
+ EO_CONFIG
98
+ ) do
99
+ ENV['hpc_certificates'] = certs_dir
100
+ test_deployer.local_environment = true
101
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
102
+ end
103
+ end
104
+ end
105
+
106
+ it 'deploys on 1 node with certificates to install using hpc_certificates on Debian but ignores them in non-local environment' do
107
+ with_certs_dir do |certs_dir|
108
+ with_platform_to_deploy(nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } }) do
109
+ ENV['hpc_certificates'] = certs_dir
110
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
111
+ end
112
+ end
113
+ end
114
+
115
+ it 'deploys on 1 node with certificates to install using hpc_certificates on Debian using root' do
116
+ with_certs_dir do |certs_dir|
117
+ with_platform_to_deploy(
118
+ nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
119
+ expect_sudo: nil,
120
+ expect_local_environment: true,
121
+ expect_additional_actions: [
122
+ { remote_bash: 'apt update && apt install -y ca-certificates' },
123
+ {
124
+ remote_bash: 'update-ca-certificates',
125
+ scp: {
126
+ certs_dir => '/usr/local/share/ca-certificates',
127
+ :sudo => false
128
+ }
129
+ }
130
+ ]
131
+ ) do
132
+ ENV['hpc_certificates'] = certs_dir
133
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
134
+ test_deployer.local_environment = true
135
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
136
+ end
137
+ end
138
+ end
139
+
140
+ it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS' do
141
+ with_certs_dir do |certs_dir|
142
+ with_platform_to_deploy(
143
+ nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
144
+ expect_local_environment: true,
145
+ expect_additional_actions: [
146
+ { remote_bash: 'sudo -u root yum install -y ca-certificates' },
147
+ {
148
+ remote_bash: ['sudo -u root update-ca-trust enable', 'sudo -u root update-ca-trust extract'],
149
+ scp: {
150
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
151
+ :sudo => true
152
+ }
153
+ }
154
+ ]
155
+ ) do
156
+ ENV['hpc_certificates'] = certs_dir
157
+ test_deployer.local_environment = true
158
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
159
+ end
160
+ end
161
+ end
162
+
163
+ it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS and an alternate sudo' do
164
+ with_certs_dir do |certs_dir|
165
+ with_platform_to_deploy(
166
+ nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
167
+ expect_sudo: 'other_sudo --user root',
168
+ expect_local_environment: true,
169
+ expect_additional_actions: [
170
+ { remote_bash: 'other_sudo --user root yum install -y ca-certificates' },
171
+ {
172
+ remote_bash: ['other_sudo --user root update-ca-trust enable', 'other_sudo --user root update-ca-trust extract'],
173
+ scp: {
174
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
175
+ :sudo => true
176
+ }
177
+ }
178
+ ],
179
+ additional_config: <<~'EO_CONFIG'
180
+ sudo_for { |user| "other_sudo --user #{user}" }
181
+ EO_CONFIG
182
+ ) do
183
+ ENV['hpc_certificates'] = certs_dir
184
+ test_deployer.local_environment = true
185
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
186
+ end
187
+ end
188
+ end
189
+
190
+ it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS using root' do
191
+ with_certs_dir do |certs_dir|
192
+ with_platform_to_deploy(
193
+ nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
194
+ expect_sudo: nil,
195
+ expect_local_environment: true,
196
+ expect_additional_actions: [
197
+ { remote_bash: 'yum install -y ca-certificates' },
198
+ {
199
+ remote_bash: ['update-ca-trust enable', 'update-ca-trust extract'],
200
+ scp: {
201
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
202
+ :sudo => false
203
+ }
204
+ }
205
+ ]
206
+ ) do
207
+ ENV['hpc_certificates'] = certs_dir
208
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
209
+ test_deployer.local_environment = true
210
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
211
+ end
212
+ end
213
+ end
214
+
215
+ it 'deploys on several nodes' do
216
+ with_platform_to_deploy(
217
+ nodes_info: {
218
+ nodes: {
219
+ 'node1' => { services: %w[service1] },
220
+ 'node2' => { services: %w[service2] },
221
+ 'node3' => { services: %w[service3] }
222
+ }
223
+ }
224
+ ) do
225
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
226
+ 'node1' => expected_deploy_result,
227
+ 'node2' => expected_deploy_result,
228
+ 'node3' => expected_deploy_result
229
+ )
230
+ end
231
+ end
232
+
233
+ it 'deploys on several nodes in parallel' do
234
+ with_platform_to_deploy(
235
+ nodes_info: {
236
+ nodes: {
237
+ 'node1' => { services: %w[service1] },
238
+ 'node2' => { services: %w[service2] },
239
+ 'node3' => { services: %w[service3] }
240
+ }
241
+ },
242
+ expect_concurrent_actions: true
243
+ ) do
244
+ test_deployer.concurrent_execution = true
245
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
246
+ 'node1' => expected_deploy_result,
247
+ 'node2' => expected_deploy_result,
248
+ 'node3' => expected_deploy_result
249
+ )
250
+ end
251
+ end
252
+
253
+ it 'deploys on several nodes with timeout' do
254
+ with_platform_to_deploy(
255
+ nodes_info: {
256
+ nodes: {
257
+ 'node1' => { services: %w[service1] },
258
+ 'node2' => { services: %w[service2] },
259
+ 'node3' => { services: %w[service3] }
260
+ }
261
+ },
262
+ expect_actions_timeout: 5
263
+ ) do
264
+ test_deployer.timeout = 5
265
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
266
+ 'node1' => expected_deploy_result,
267
+ 'node2' => expected_deploy_result,
268
+ 'node3' => expected_deploy_result
269
+ )
270
+ end
271
+ end
272
+
273
+ it 'fails when packaging timeout has been reached while taking the futex' do
274
+ with_platform_to_deploy(
275
+ additional_config: 'packaging_timeout 1',
276
+ expect_package: false,
277
+ expect_prepare_for_deploy: false,
278
+ expect_connections_to_nodes: false
279
+ ) do
280
+ # Simulate another process taking the packaging futex
281
+ futex_file = HybridPlatformsConductor::Deployer.const_get(:PACKAGING_FUTEX_FILE)
282
+ Futex.new(futex_file).open do
283
+ # Expect the error to be raised within 2 seconds (as it should timeout after 1 second)
284
+ Timeout.timeout(2) do
285
+ expect { test_deployer.deploy_on('node') }.to raise_error(
286
+ Futex::CantLock,
287
+ /can't get exclusive access to the file #{Regexp.escape(futex_file)} because of the lock at #{Regexp.escape(futex_file)}\.lock, after 1\.\d+s of waiting/
288
+ )
289
+ end
290
+ rescue Timeout::Error
291
+ raise 'The packaging timeout (set to 1 seconds) did not fire within 2 seconds. Looks like it is not working properly.'
292
+ end
293
+ end
294
+ end
295
+
296
+ context 'when checking deployment retries' do
297
+
298
+ it 'restarts deployment for a non-deterministic error' do
299
+ with_platform_to_retry_deploy do
300
+ test_deployer.nbr_retries_on_error = 1
301
+ mock_deploys_with [
302
+ [1, "Error: This is a stdout non-deterministic error\nDeploy failed\n", ''],
303
+ [0, 'Deploy ok', '']
304
+ ]
305
+ expect(test_deployer.deploy_on('node')).to eq(
306
+ 'node' => [
307
+ 0,
308
+ <<~EO_STDOUT,
309
+ Error: This is a stdout non-deterministic error
310
+ Deploy failed
311
+
312
+ Deployment exit status code: 1
313
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
314
+ Deploy ok
315
+ EO_STDOUT
316
+ <<~EO_STDERR
317
+ !!! 1 retriable errors detected in this deployment:
318
+ * stdout non-deterministic error
319
+
320
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
321
+
322
+ EO_STDERR
323
+ ]
324
+ )
325
+ end
326
+ end
327
+
328
+ it 'restarts deployment for a non-deterministic error matched with a Regexp' do
329
+ with_platform_to_retry_deploy do
330
+ test_deployer.nbr_retries_on_error = 1
331
+ mock_deploys_with [
332
+ [1, "Error: This is a stdout regexp error 42\nDeploy failed\n", ''],
333
+ [0, 'Deploy ok', '']
334
+ ]
335
+ expect(test_deployer.deploy_on('node')).to eq(
336
+ 'node' => [
337
+ 0,
338
+ <<~EO_STDOUT,
339
+ Error: This is a stdout regexp error 42
340
+ Deploy failed
341
+
342
+ Deployment exit status code: 1
343
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
344
+ Deploy ok
345
+ EO_STDOUT
346
+ <<~EO_STDERR
347
+ !!! 1 retriable errors detected in this deployment:
348
+ * /stdout regexp error \\d+/ matched 'stdout regexp error 42'
349
+
350
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
351
+
352
+ EO_STDERR
353
+ ]
354
+ )
355
+ end
356
+ end
357
+
358
+ it 'restarts deployment for a non-deterministic error on stderr' do
359
+ with_platform_to_retry_deploy do
360
+ test_deployer.nbr_retries_on_error = 1
361
+ mock_deploys_with [
362
+ [1, '', "Error: This is a stderr non-deterministic error\nDeploy failed\n"],
363
+ [0, 'Deploy ok', '']
364
+ ]
365
+ expect(test_deployer.deploy_on('node')).to eq(
366
+ 'node' => [
367
+ 0,
368
+ <<~EO_STDOUT,
369
+
370
+ Deployment exit status code: 1
371
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
372
+ Deploy ok
373
+ EO_STDOUT
374
+ <<~EO_STDERR
375
+ Error: This is a stderr non-deterministic error
376
+ Deploy failed
377
+ !!! 1 retriable errors detected in this deployment:
378
+ * stderr non-deterministic error
379
+
380
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
381
+
382
+ EO_STDERR
383
+ ]
384
+ )
385
+ end
386
+ end
387
+
388
+ it 'restarts deployment for a non-deterministic error on stderr matched with a Regexp' do
389
+ with_platform_to_retry_deploy do
390
+ test_deployer.nbr_retries_on_error = 1
391
+ mock_deploys_with [
392
+ [1, '', "Error: This is a stderr regexp error 42\nDeploy failed\n"],
393
+ [0, 'Deploy ok', '']
394
+ ]
395
+ expect(test_deployer.deploy_on('node')).to eq(
396
+ 'node' => [
397
+ 0,
398
+ <<~EO_STDOUT,
399
+
400
+ Deployment exit status code: 1
401
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
402
+ Deploy ok
403
+ EO_STDOUT
404
+ <<~EO_STDERR
405
+ Error: This is a stderr regexp error 42
406
+ Deploy failed
407
+ !!! 1 retriable errors detected in this deployment:
408
+ * /stderr regexp error \\d+/ matched 'stderr regexp error 42'
409
+
410
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
411
+
412
+ EO_STDERR
413
+ ]
414
+ )
415
+ end
416
+ end
417
+
418
+ it 'stops restarting deployments for a non-deterministic error when errors has disappeared, even if retries were remaining' do
419
+ with_platform_to_retry_deploy do
420
+ test_deployer.nbr_retries_on_error = 5
421
+ mock_deploys_with [
422
+ [1, "Error: This is a stdout non-deterministic error 1\nDeploy failed", ''],
423
+ [1, "Error: This is a stdout non-deterministic error 2\nDeploy failed", ''],
424
+ [0, 'Deploy ok', '']
425
+ ]
426
+ expect(test_deployer.deploy_on('node')).to eq(
427
+ 'node' => [
428
+ 0,
429
+ <<~EO_STDOUT,
430
+ Error: This is a stdout non-deterministic error 1
431
+ Deploy failed
432
+ Deployment exit status code: 1
433
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
434
+ Error: This is a stdout non-deterministic error 2
435
+ Deploy failed
436
+
437
+ Deployment exit status code: 1
438
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
439
+ Deploy ok
440
+ EO_STDOUT
441
+ <<~EO_STDERR
442
+ !!! 1 retriable errors detected in this deployment:
443
+ * stdout non-deterministic error
444
+
445
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
446
+ !!! 1 retriable errors detected in this deployment:
447
+ * stdout non-deterministic error
448
+
449
+
450
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
451
+
452
+ EO_STDERR
453
+ ]
454
+ )
455
+ end
456
+ end
457
+
458
+ it 'stops restarting deployments for a non-deterministic error that became deterministic, even if retries were remaining' do
459
+ with_platform_to_retry_deploy do
460
+ test_deployer.nbr_retries_on_error = 5
461
+ mock_deploys_with [
462
+ [1, "Error: This is a stdout non-deterministic error 1\nDeploy failed", ''],
463
+ [1, "Error: This is a stdout non-deterministic error 2\nDeploy failed", ''],
464
+ [1, "Error: This is a stdout deterministic error 3\nDeploy failed", '']
465
+ ]
466
+ expect(test_deployer.deploy_on('node')).to eq(
467
+ 'node' => [
468
+ 1,
469
+ <<~EO_STDOUT,
470
+ Error: This is a stdout non-deterministic error 1
471
+ Deploy failed
472
+ Deployment exit status code: 1
473
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
474
+ Error: This is a stdout non-deterministic error 2
475
+ Deploy failed
476
+
477
+ Deployment exit status code: 1
478
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
479
+ Error: This is a stdout deterministic error 3
480
+ Deploy failed
481
+ EO_STDOUT
482
+ <<~EO_STDERR
483
+ !!! 1 retriable errors detected in this deployment:
484
+ * stdout non-deterministic error
485
+
486
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
487
+ !!! 1 retriable errors detected in this deployment:
488
+ * stdout non-deterministic error
489
+
490
+
491
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
492
+
493
+ EO_STDERR
494
+ ]
495
+ )
496
+ end
497
+ end
498
+
499
+ it 'does not restart deployment for a deterministic error' do
500
+ with_platform_to_retry_deploy do
501
+ test_deployer.nbr_retries_on_error = 5
502
+ mock_deploys_with [
503
+ [1, "Error: This is a stdout deterministic error\nDeploy failed\n", '']
504
+ ]
505
+ expect(test_deployer.deploy_on('node')).to eq(
506
+ 'node' => [
507
+ 1,
508
+ <<~EO_STDOUT,
509
+ Error: This is a stdout deterministic error
510
+ Deploy failed
511
+ EO_STDOUT
512
+ ''
513
+ ]
514
+ )
515
+ end
516
+ end
517
+
518
+ it 'does not restart deployment for a non-deterministic error logged during a successful deploy' do
519
+ with_platform_to_retry_deploy do
520
+ test_deployer.nbr_retries_on_error = 5
521
+ mock_deploys_with [
522
+ [0, "Error: This is a stdout non-deterministic error\nDeploy failed\n", '']
523
+ ]
524
+ expect(test_deployer.deploy_on('node')).to eq(
525
+ 'node' => [
526
+ 0,
527
+ <<~EO_STDOUT,
528
+ Error: This is a stdout non-deterministic error
529
+ Deploy failed
530
+ EO_STDOUT
531
+ ''
532
+ ]
533
+ )
534
+ end
535
+ end
536
+
537
+ it 'does not restart deployment for a non-deterministic error if retries are 0' do
538
+ with_platform_to_retry_deploy do
539
+ test_deployer.nbr_retries_on_error = 0
540
+ mock_deploys_with [
541
+ [1, "Error: This is a stdout non-deterministic error\nDeploy failed\n", '']
542
+ ]
543
+ expect(test_deployer.deploy_on('node')).to eq(
544
+ 'node' => [
545
+ 1,
546
+ <<~EO_STDOUT,
547
+ Error: This is a stdout non-deterministic error
548
+ Deploy failed
549
+ EO_STDOUT
550
+ ''
551
+ ]
552
+ )
553
+ end
554
+ end
555
+
556
+ it 'restarts deployment for non-deterministic errors with a limited amount of retries' do
557
+ with_platform_to_retry_deploy do
558
+ test_deployer.nbr_retries_on_error = 2
559
+ mock_deploys_with [
560
+ [1, "Error: This is a stdout non-deterministic error 1\nDeploy failed", ''],
561
+ [1, "Error: This is a stdout non-deterministic error 2\nDeploy failed", ''],
562
+ [1, "Error: This is a stdout non-deterministic error 3\nDeploy failed", '']
563
+ ]
564
+ expect(test_deployer.deploy_on('node')).to eq(
565
+ 'node' => [
566
+ 1,
567
+ <<~EO_STDOUT,
568
+ Error: This is a stdout non-deterministic error 1
569
+ Deploy failed
570
+ Deployment exit status code: 1
571
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
572
+ Error: This is a stdout non-deterministic error 2
573
+ Deploy failed
574
+
575
+ Deployment exit status code: 1
576
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
577
+ Error: This is a stdout non-deterministic error 3
578
+ Deploy failed
579
+ EO_STDOUT
580
+ <<~EO_STDERR
581
+ !!! 1 retriable errors detected in this deployment:
582
+ * stdout non-deterministic error
583
+
584
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
585
+ !!! 1 retriable errors detected in this deployment:
586
+ * stdout non-deterministic error
587
+
588
+
589
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
590
+
591
+ EO_STDERR
592
+ ]
593
+ )
594
+ end
595
+ end
596
+
597
+ it 'restarts deployment for non-deterministic errors only on nodes needing it' do
598
+ with_platform_to_retry_deploy(
599
+ nodes_info: {
600
+ nodes: {
601
+ 'node1' => { services: %w[service] },
602
+ 'node2' => { services: %w[service] },
603
+ 'node3' => { services: %w[service] },
604
+ 'node4' => { services: %w[service] }
605
+ }
606
+ }
607
+ ) do
608
+ test_deployer.nbr_retries_on_error = 2
609
+ # Some nodes deploy successfully,
610
+ # others have deterministic errors,
611
+ # others have non-deterministic errors being corrected
612
+ # others have non-deterministic errors not being corrected
613
+ mock_deploys_with [
614
+ {
615
+ 'node1' => [1, "Error: This is a stdout non-deterministic error\n[node1] Deploy failed\n", ''],
616
+ 'node2' => [0, '[node2] Deploy ok', ''],
617
+ 'node3' => [1, "Error: This is a stdout non-deterministic error\n[node3] Deploy failed\n", ''],
618
+ 'node4' => [1, "Error: This is a stdout non-deterministic error\n[node4] Deploy failed\n", '']
619
+ },
620
+ {
621
+ 'node1' => [0, '[node1] Deploy ok', ''],
622
+ 'node3' => [1, "Error: This is a stdout deterministic error\n[node3] Deploy failed\n", ''],
623
+ 'node4' => [1, "Error: This is a stdout non-deterministic error\n[node4] Deploy failed\n", '']
624
+ },
625
+ {
626
+ 'node4' => [1, "Error: This is a stdout non-deterministic error\n[node4] Deploy failed\n", '']
627
+ }
628
+ ]
629
+ expect(test_deployer.deploy_on(%w[node1 node2 node3 node4])).to eq(
630
+ 'node1' => [
631
+ 0,
632
+ <<~EO_STDOUT,
633
+ Error: This is a stdout non-deterministic error
634
+ [node1] Deploy failed
635
+
636
+ Deployment exit status code: 1
637
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
638
+ [node1] Deploy ok
639
+ EO_STDOUT
640
+ <<~EO_STDERR
641
+ !!! 1 retriable errors detected in this deployment:
642
+ * stdout non-deterministic error
643
+
644
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
645
+
646
+ EO_STDERR
647
+ ],
648
+ 'node2' => [
649
+ 0,
650
+ '[node2] Deploy ok',
651
+ ''
652
+ ],
653
+ 'node3' => [
654
+ 1,
655
+ <<~EO_STDOUT,
656
+ Error: This is a stdout non-deterministic error
657
+ [node3] Deploy failed
658
+
659
+ Deployment exit status code: 1
660
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
661
+ Error: This is a stdout deterministic error
662
+ [node3] Deploy failed
663
+
664
+ EO_STDOUT
665
+ <<~EO_STDERR
666
+ !!! 1 retriable errors detected in this deployment:
667
+ * stdout non-deterministic error
668
+
669
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
670
+
671
+ EO_STDERR
672
+ ],
673
+ 'node4' => [
674
+ 1,
675
+ <<~EO_STDOUT,
676
+ Error: This is a stdout non-deterministic error
677
+ [node4] Deploy failed
678
+
679
+ Deployment exit status code: 1
680
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
681
+ Error: This is a stdout non-deterministic error
682
+ [node4] Deploy failed
683
+
684
+
685
+ Deployment exit status code: 1
686
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
687
+ Error: This is a stdout non-deterministic error
688
+ [node4] Deploy failed
689
+
690
+ EO_STDOUT
691
+ <<~EO_STDERR
692
+ !!! 1 retriable errors detected in this deployment:
693
+ * stdout non-deterministic error
694
+
695
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
696
+ !!! 1 retriable errors detected in this deployment:
697
+ * stdout non-deterministic error
698
+
699
+
700
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
701
+
702
+ EO_STDERR
703
+ ]
704
+ )
705
+ end
706
+ end
707
+
708
+ end
709
+
710
+ context 'when checking secrets handling' do
711
+
712
+ it 'calls secrets readers only for nodes and services to be deployed and merges their secrets' do
713
+ register_plugins(
714
+ :secrets_reader,
715
+ {
716
+ secrets_reader_1: HybridPlatformsConductorTest::TestSecretsReaderPlugin,
717
+ secrets_reader_2: HybridPlatformsConductorTest::TestSecretsReaderPlugin,
718
+ secrets_reader_3: HybridPlatformsConductorTest::TestSecretsReaderPlugin
719
+ }
720
+ )
721
+ with_platform_to_deploy(
722
+ nodes_info: {
723
+ nodes: {
724
+ 'node1' => { services: %w[service1 service2] },
725
+ 'node2' => { services: %w[service2 service3] },
726
+ 'node3' => { services: %w[service3] },
727
+ 'node4' => { services: %w[service1 service3] }
728
+ }
729
+ },
730
+ expect_services_to_deploy: {
731
+ 'node1' => %w[service1 service2],
732
+ 'node2' => %w[service2 service3],
733
+ 'node3' => %w[service3]
734
+ },
735
+ expect_secrets: {
736
+ 'node1' => {
737
+ 'service1' => {
738
+ 'secrets_reader_1' => 'Secret value',
739
+ 'secrets_reader_2' => 'Secret value'
740
+ },
741
+ 'service2' => {
742
+ 'secrets_reader_1' => 'Secret value',
743
+ 'secrets_reader_2' => 'Secret value'
744
+ }
745
+ },
746
+ 'node2' => {
747
+ 'service2' => {
748
+ 'secrets_reader_1' => 'Secret value',
749
+ 'secrets_reader_2' => 'Secret value',
750
+ 'secrets_reader_3' => 'Secret value'
751
+ },
752
+ 'service3' => {
753
+ 'secrets_reader_1' => 'Secret value',
754
+ 'secrets_reader_2' => 'Secret value',
755
+ 'secrets_reader_3' => 'Secret value'
756
+ }
757
+ },
758
+ 'node3' => {
759
+ 'service3' => {
760
+ 'secrets_reader_1' => 'Secret value',
761
+ 'secrets_reader_2' => 'Secret value'
762
+ }
763
+ }
764
+ },
765
+ additional_config: <<~EO_CONFIG
766
+ read_secrets_from %i[secrets_reader_1 secrets_reader_2]
767
+ for_nodes('node2') { read_secrets_from :secrets_reader_3 }
768
+ EO_CONFIG
769
+ ) do
770
+ HybridPlatformsConductorTest::TestSecretsReaderPlugin.deployer = test_deployer
771
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
772
+ 'node1' => expected_deploy_result,
773
+ 'node2' => expected_deploy_result,
774
+ 'node3' => expected_deploy_result
775
+ )
776
+ expect(HybridPlatformsConductorTest::TestSecretsReaderPlugin.calls).to eq [
777
+ { instance: :secrets_reader_1, node: 'node1', service: 'service1' },
778
+ { instance: :secrets_reader_1, node: 'node1', service: 'service2' },
779
+ { instance: :secrets_reader_2, node: 'node1', service: 'service1' },
780
+ { instance: :secrets_reader_2, node: 'node1', service: 'service2' },
781
+ { instance: :secrets_reader_1, node: 'node2', service: 'service2' },
782
+ { instance: :secrets_reader_1, node: 'node2', service: 'service3' },
783
+ { instance: :secrets_reader_2, node: 'node2', service: 'service2' },
784
+ { instance: :secrets_reader_2, node: 'node2', service: 'service3' },
785
+ { instance: :secrets_reader_3, node: 'node2', service: 'service2' },
786
+ { instance: :secrets_reader_3, node: 'node2', service: 'service3' },
787
+ { instance: :secrets_reader_1, node: 'node3', service: 'service3' },
788
+ { instance: :secrets_reader_2, node: 'node3', service: 'service3' }
789
+ ]
790
+ end
791
+ end
792
+
793
+ it 'merges secrets having same values' do
794
+ register_plugins(
795
+ :secrets_reader,
796
+ {
797
+ secrets_reader_1: HybridPlatformsConductorTest::TestSecretsReaderPlugin,
798
+ secrets_reader_2: HybridPlatformsConductorTest::TestSecretsReaderPlugin
799
+ }
800
+ )
801
+ with_platform_to_deploy(
802
+ nodes_info: {
803
+ nodes: {
804
+ 'node1' => { services: %w[service1] },
805
+ 'node2' => { services: %w[service2] }
806
+ }
807
+ },
808
+ expect_secrets: {
809
+ 'global1' => 'value1',
810
+ 'global2' => 'value2',
811
+ 'global3' => 'value3',
812
+ 'global4' => 'value4'
813
+ },
814
+ additional_config: <<~EO_CONFIG
815
+ read_secrets_from :secrets_reader_1
816
+ for_nodes('node2') { read_secrets_from :secrets_reader_2 }
817
+ EO_CONFIG
818
+ ) do
819
+ HybridPlatformsConductorTest::TestSecretsReaderPlugin.deployer = test_deployer
820
+ HybridPlatformsConductorTest::TestSecretsReaderPlugin.mocked_secrets = {
821
+ 'node1' => {
822
+ 'service1' => {
823
+ secrets_reader_1: {
824
+ 'global1' => 'value1',
825
+ 'global2' => 'value2'
826
+ }
827
+ }
828
+ },
829
+ 'node2' => {
830
+ 'service2' => {
831
+ secrets_reader_1: {
832
+ 'global2' => 'value2',
833
+ 'global3' => 'value3'
834
+ },
835
+ secrets_reader_2: {
836
+ 'global3' => 'value3',
837
+ 'global4' => 'value4'
838
+ }
839
+ }
840
+ }
841
+ }
842
+ expect(test_deployer.deploy_on(%w[node1 node2])).to eq(
843
+ 'node1' => expected_deploy_result,
844
+ 'node2' => expected_deploy_result
845
+ )
846
+ expect(HybridPlatformsConductorTest::TestSecretsReaderPlugin.calls).to eq [
847
+ { instance: :secrets_reader_1, node: 'node1', service: 'service1' },
848
+ { instance: :secrets_reader_1, node: 'node2', service: 'service2' },
849
+ { instance: :secrets_reader_2, node: 'node2', service: 'service2' }
850
+ ]
851
+ end
852
+ end
853
+
854
+ it 'fails when merging secrets having different values' do
855
+ register_plugins(
856
+ :secrets_reader,
857
+ {
858
+ secrets_reader_1: HybridPlatformsConductorTest::TestSecretsReaderPlugin,
859
+ secrets_reader_2: HybridPlatformsConductorTest::TestSecretsReaderPlugin
860
+ }
861
+ )
862
+ with_platform_to_deploy(
863
+ nodes_info: {
864
+ nodes: {
865
+ 'node1' => { services: %w[service1] },
866
+ 'node2' => { services: %w[service2] }
867
+ }
868
+ },
869
+ expect_deploy_allowed: false,
870
+ expect_package: false,
871
+ expect_prepare_for_deploy: false,
872
+ expect_connections_to_nodes: false,
873
+ additional_config: <<~EO_CONFIG
874
+ read_secrets_from :secrets_reader_1
875
+ for_nodes('node2') { read_secrets_from :secrets_reader_2 }
876
+ EO_CONFIG
877
+ ) do
878
+ HybridPlatformsConductorTest::TestSecretsReaderPlugin.deployer = test_deployer
879
+ HybridPlatformsConductorTest::TestSecretsReaderPlugin.mocked_secrets = {
880
+ 'node1' => {
881
+ 'service1' => {
882
+ secrets_reader_1: {
883
+ 'global1' => 'value1',
884
+ 'global2' => 'value2'
885
+ }
886
+ }
887
+ },
888
+ 'node2' => {
889
+ 'service2' => {
890
+ secrets_reader_1: {
891
+ 'global2' => 'value2',
892
+ 'global3' => {
893
+ 'sub_key' => 'value3'
894
+ }
895
+ },
896
+ secrets_reader_2: {
897
+ 'global3' => {
898
+ 'sub_key' => 'Other value'
899
+ },
900
+ 'global4' => 'value4'
901
+ }
902
+ }
903
+ }
904
+ }
905
+ expect { test_deployer.deploy_on(%w[node1 node2]) }.to raise_error 'Secret set at path global3->sub_key by secrets_reader_2 for service service2 on node node2 has conflicting values (set debug for value details).'
906
+ expect(HybridPlatformsConductorTest::TestSecretsReaderPlugin.calls).to eq [
907
+ { instance: :secrets_reader_1, node: 'node1', service: 'service1' },
908
+ { instance: :secrets_reader_1, node: 'node2', service: 'service2' },
909
+ { instance: :secrets_reader_2, node: 'node2', service: 'service2' }
910
+ ]
911
+ end
912
+ end
913
+
914
+ it 'does not call secrets readers when secrets are overridden' do
915
+ register_plugins(
916
+ :secrets_reader,
917
+ {
918
+ secrets_reader_1: HybridPlatformsConductorTest::TestSecretsReaderPlugin,
919
+ secrets_reader_2: HybridPlatformsConductorTest::TestSecretsReaderPlugin,
920
+ secrets_reader_3: HybridPlatformsConductorTest::TestSecretsReaderPlugin
921
+ }
922
+ )
923
+ with_platform_to_deploy(
924
+ nodes_info: {
925
+ nodes: {
926
+ 'node1' => { services: %w[service1] },
927
+ 'node2' => { services: %w[service2] },
928
+ 'node3' => { services: %w[service3] }
929
+ }
930
+ },
931
+ expect_secrets: {
932
+ 'overridden_secrets' => 'value'
933
+ },
934
+ additional_config: <<~EO_CONFIG
935
+ read_secrets_from %i[secrets_reader_1 secrets_reader_2]
936
+ for_nodes('node2') { read_secrets_from :secrets_reader_3 }
937
+ EO_CONFIG
938
+ ) do
939
+ HybridPlatformsConductorTest::TestSecretsReaderPlugin.deployer = test_deployer
940
+ test_deployer.override_secrets('overridden_secrets' => 'value')
941
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
942
+ 'node1' => expected_deploy_result,
943
+ 'node2' => expected_deploy_result,
944
+ 'node3' => expected_deploy_result
945
+ )
946
+ expect(HybridPlatformsConductorTest::TestSecretsReaderPlugin.calls).to eq []
947
+ end
948
+ end
949
+
950
+ end
951
+
952
+ end