hybrid_platforms_conductor 32.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (244) hide show
  1. checksums.yaml +7 -0
  2. data/bin/check-node +24 -0
  3. data/bin/deploy +12 -0
  4. data/bin/dump_nodes_json +12 -0
  5. data/bin/free_ips +23 -0
  6. data/bin/free_veids +17 -0
  7. data/bin/get_impacted_nodes +43 -0
  8. data/bin/last_deploys +56 -0
  9. data/bin/nodes_to_deploy +104 -0
  10. data/bin/report +10 -0
  11. data/bin/run +39 -0
  12. data/bin/setup +11 -0
  13. data/bin/ssh_config +14 -0
  14. data/bin/test +13 -0
  15. data/bin/topograph +54 -0
  16. data/lib/hybrid_platforms_conductor/action.rb +82 -0
  17. data/lib/hybrid_platforms_conductor/actions_executor.rb +307 -0
  18. data/lib/hybrid_platforms_conductor/bitbucket.rb +123 -0
  19. data/lib/hybrid_platforms_conductor/cmd_runner.rb +188 -0
  20. data/lib/hybrid_platforms_conductor/cmdb.rb +34 -0
  21. data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +78 -0
  22. data/lib/hybrid_platforms_conductor/common_config_dsl/confluence.rb +43 -0
  23. data/lib/hybrid_platforms_conductor/common_config_dsl/file_system_tests.rb +110 -0
  24. data/lib/hybrid_platforms_conductor/common_config_dsl/idempotence_tests.rb +38 -0
  25. data/lib/hybrid_platforms_conductor/config.rb +263 -0
  26. data/lib/hybrid_platforms_conductor/confluence.rb +119 -0
  27. data/lib/hybrid_platforms_conductor/connector.rb +84 -0
  28. data/lib/hybrid_platforms_conductor/credentials.rb +127 -0
  29. data/lib/hybrid_platforms_conductor/current_dir_monitor.rb +42 -0
  30. data/lib/hybrid_platforms_conductor/deployer.rb +598 -0
  31. data/lib/hybrid_platforms_conductor/executable.rb +145 -0
  32. data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +44 -0
  33. data/lib/hybrid_platforms_conductor/hpc_plugins/action/interactive.rb +44 -0
  34. data/lib/hybrid_platforms_conductor/hpc_plugins/action/my_action.rb.sample +79 -0
  35. data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +63 -0
  36. data/lib/hybrid_platforms_conductor/hpc_plugins/action/ruby.rb +69 -0
  37. data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +61 -0
  38. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/config.rb +78 -0
  39. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_ip.rb +104 -0
  40. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +114 -0
  41. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/my_cmdb.rb.sample +129 -0
  42. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/platform_handlers.rb +66 -0
  43. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +156 -0
  44. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +702 -0
  45. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +292 -0
  46. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +148 -0
  47. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/my_provisioner.rb.sample +103 -0
  48. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +125 -0
  49. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +522 -0
  50. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/proxmox_waiter.rb +707 -0
  51. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +122 -0
  52. data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +69 -0
  53. data/lib/hybrid_platforms_conductor/hpc_plugins/report/mediawiki.rb +164 -0
  54. data/lib/hybrid_platforms_conductor/hpc_plugins/report/my_report_plugin.rb.sample +88 -0
  55. data/lib/hybrid_platforms_conductor/hpc_plugins/report/stdout.rb +61 -0
  56. data/lib/hybrid_platforms_conductor/hpc_plugins/report/templates/confluence_inventory.html.erb +33 -0
  57. data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +137 -0
  58. data/lib/hybrid_platforms_conductor/hpc_plugins/test/can_be_checked.rb +21 -0
  59. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +112 -0
  60. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_from_scratch.rb +35 -0
  61. data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +28 -0
  62. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +44 -0
  63. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_from_scratch.rb +36 -0
  64. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +49 -0
  65. data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +25 -0
  66. data/lib/hybrid_platforms_conductor/hpc_plugins/test/executables.rb +46 -0
  67. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +45 -0
  68. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system_hdfs.rb +45 -0
  69. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +25 -0
  70. data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +77 -0
  71. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +38 -0
  72. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +56 -0
  73. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +54 -0
  74. data/lib/hybrid_platforms_conductor/hpc_plugins/test/linear_strategy.rb +47 -0
  75. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +82 -0
  76. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +120 -0
  77. data/lib/hybrid_platforms_conductor/hpc_plugins/test/my_test_plugin.rb.sample +143 -0
  78. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +74 -0
  79. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +85 -0
  80. data/lib/hybrid_platforms_conductor/hpc_plugins/test/private_ips.rb +38 -0
  81. data/lib/hybrid_platforms_conductor/hpc_plugins/test/public_ips.rb +38 -0
  82. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre-meltdown-checker.sh +1930 -0
  83. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +56 -0
  84. data/lib/hybrid_platforms_conductor/hpc_plugins/test/veids.rb +31 -0
  85. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +159 -0
  86. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +122 -0
  87. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/my_test_report.rb.sample +48 -0
  88. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/stdout.rb +120 -0
  89. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_errors_status.html.erb +46 -0
  90. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_gauge.html.erb +49 -0
  91. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/confluence.html.erb +242 -0
  92. data/lib/hybrid_platforms_conductor/io_router.rb +70 -0
  93. data/lib/hybrid_platforms_conductor/json_dumper.rb +88 -0
  94. data/lib/hybrid_platforms_conductor/logger_helpers.rb +319 -0
  95. data/lib/hybrid_platforms_conductor/mutex_dir +76 -0
  96. data/lib/hybrid_platforms_conductor/nodes_handler.rb +597 -0
  97. data/lib/hybrid_platforms_conductor/parallel_threads.rb +97 -0
  98. data/lib/hybrid_platforms_conductor/platform_handler.rb +188 -0
  99. data/lib/hybrid_platforms_conductor/platforms_handler.rb +118 -0
  100. data/lib/hybrid_platforms_conductor/plugin.rb +53 -0
  101. data/lib/hybrid_platforms_conductor/plugins.rb +101 -0
  102. data/lib/hybrid_platforms_conductor/provisioner.rb +181 -0
  103. data/lib/hybrid_platforms_conductor/report.rb +31 -0
  104. data/lib/hybrid_platforms_conductor/reports_handler.rb +84 -0
  105. data/lib/hybrid_platforms_conductor/services_handler.rb +274 -0
  106. data/lib/hybrid_platforms_conductor/test.rb +141 -0
  107. data/lib/hybrid_platforms_conductor/test_by_service.rb +22 -0
  108. data/lib/hybrid_platforms_conductor/test_report.rb +282 -0
  109. data/lib/hybrid_platforms_conductor/tests_runner.rb +590 -0
  110. data/lib/hybrid_platforms_conductor/thycotic.rb +92 -0
  111. data/lib/hybrid_platforms_conductor/topographer.rb +859 -0
  112. data/lib/hybrid_platforms_conductor/topographer/plugin.rb +20 -0
  113. data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +127 -0
  114. data/lib/hybrid_platforms_conductor/topographer/plugins/json.rb +72 -0
  115. data/lib/hybrid_platforms_conductor/topographer/plugins/my_topographer_output_plugin.rb.sample +37 -0
  116. data/lib/hybrid_platforms_conductor/topographer/plugins/svg.rb +30 -0
  117. data/lib/hybrid_platforms_conductor/version.rb +5 -0
  118. data/spec/hybrid_platforms_conductor_test.rb +159 -0
  119. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +43 -0
  120. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/interactive_spec.rb +18 -0
  121. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +102 -0
  122. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/ruby_spec.rb +108 -0
  123. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/scp_spec.rb +79 -0
  124. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions_spec.rb +199 -0
  125. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connection_spec.rb +212 -0
  126. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +125 -0
  127. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +50 -0
  128. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connectable_nodes_spec.rb +28 -0
  129. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +448 -0
  130. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +313 -0
  131. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +32 -0
  132. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +134 -0
  133. data/spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb +256 -0
  134. data/spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb +338 -0
  135. data/spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb +101 -0
  136. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +165 -0
  137. data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +238 -0
  138. data/spec/hybrid_platforms_conductor_test/api/deployer/check_spec.rb +9 -0
  139. data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +243 -0
  140. data/spec/hybrid_platforms_conductor_test/api/deployer/parse_deploy_output_spec.rb +104 -0
  141. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +131 -0
  142. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker/Dockerfile +10 -0
  143. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker_spec.rb +123 -0
  144. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/podman_spec.rb +211 -0
  145. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/config_dsl_spec.rb +126 -0
  146. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/create_spec.rb +290 -0
  147. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/destroy_spec.rb +43 -0
  148. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/ip_spec.rb +60 -0
  149. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/proxmox.json +3 -0
  150. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/destroy_vm_spec.rb +82 -0
  151. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/expired_containers_spec.rb +786 -0
  152. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/ips_assignment_spec.rb +112 -0
  153. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/other_lxc_containers_resources_spec.rb +190 -0
  154. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/pve_node_resources_spec.rb +200 -0
  155. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/retries_spec.rb +35 -0
  156. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/vm_ids_assignment_spec.rb +67 -0
  157. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/start_spec.rb +79 -0
  158. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/state_spec.rb +28 -0
  159. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/stop_spec.rb +41 -0
  160. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/config_spec.rb +33 -0
  161. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_ip_spec.rb +64 -0
  162. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +133 -0
  163. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb +19 -0
  164. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +446 -0
  165. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +127 -0
  166. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +318 -0
  167. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +132 -0
  168. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb +60 -0
  169. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/several_platforms_spec.rb +58 -0
  170. data/spec/hybrid_platforms_conductor_test/api/platform_handler_spec.rb +97 -0
  171. data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +104 -0
  172. data/spec/hybrid_platforms_conductor_test/api/plugins_spec.rb +243 -0
  173. data/spec/hybrid_platforms_conductor_test/api/reports_handler_spec.rb +44 -0
  174. data/spec/hybrid_platforms_conductor_test/api/services_handler/actions_to_deploy_spec.rb +121 -0
  175. data/spec/hybrid_platforms_conductor_test/api/services_handler/deploy_allowed_spec.rb +142 -0
  176. data/spec/hybrid_platforms_conductor_test/api/services_handler/log_info_spec.rb +101 -0
  177. data/spec/hybrid_platforms_conductor_test/api/services_handler/package_spec.rb +388 -0
  178. data/spec/hybrid_platforms_conductor_test/api/services_handler/parse_deploy_output_spec.rb +274 -0
  179. data/spec/hybrid_platforms_conductor_test/api/services_handler/prepare_for_deploy_spec.rb +264 -0
  180. data/spec/hybrid_platforms_conductor_test/api/tests_runner/common_spec.rb +194 -0
  181. data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +37 -0
  182. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_check_spec.rb +194 -0
  183. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_spec.rb +137 -0
  184. data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_ssh_spec.rb +257 -0
  185. data/spec/hybrid_platforms_conductor_test/api/tests_runner/platform_spec.rb +110 -0
  186. data/spec/hybrid_platforms_conductor_test/api/tests_runner/reports_spec.rb +367 -0
  187. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +111 -0
  188. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_reports_plugins/confluence_spec.rb +29 -0
  189. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb.rb +166 -0
  190. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb2.rb +93 -0
  191. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others.rb +60 -0
  192. data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others2.rb +58 -0
  193. data/spec/hybrid_platforms_conductor_test/executables/check-node_spec.rb +35 -0
  194. data/spec/hybrid_platforms_conductor_test/executables/deploy_spec.rb +35 -0
  195. data/spec/hybrid_platforms_conductor_test/executables/get_impacted_nodes_spec.rb +158 -0
  196. data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +173 -0
  197. data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +283 -0
  198. data/spec/hybrid_platforms_conductor_test/executables/options/actions_executor_spec.rb +28 -0
  199. data/spec/hybrid_platforms_conductor_test/executables/options/cmd_runner_spec.rb +28 -0
  200. data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +67 -0
  201. data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +251 -0
  202. data/spec/hybrid_platforms_conductor_test/executables/options/nodes_handler_spec.rb +111 -0
  203. data/spec/hybrid_platforms_conductor_test/executables/options/nodes_selectors_spec.rb +71 -0
  204. data/spec/hybrid_platforms_conductor_test/executables/options/reports_handler_spec.rb +54 -0
  205. data/spec/hybrid_platforms_conductor_test/executables/options/tests_runner_spec.rb +139 -0
  206. data/spec/hybrid_platforms_conductor_test/executables/report_spec.rb +60 -0
  207. data/spec/hybrid_platforms_conductor_test/executables/run_spec.rb +173 -0
  208. data/spec/hybrid_platforms_conductor_test/executables/ssh_config_spec.rb +35 -0
  209. data/spec/hybrid_platforms_conductor_test/executables/test_spec.rb +41 -0
  210. data/spec/hybrid_platforms_conductor_test/helpers/actions_executor_helpers.rb +98 -0
  211. data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +92 -0
  212. data/spec/hybrid_platforms_conductor_test/helpers/cmdb_helpers.rb +37 -0
  213. data/spec/hybrid_platforms_conductor_test/helpers/config_helpers.rb +20 -0
  214. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +130 -0
  215. data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +149 -0
  216. data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +812 -0
  217. data/spec/hybrid_platforms_conductor_test/helpers/executables_helpers.rb +96 -0
  218. data/spec/hybrid_platforms_conductor_test/helpers/nodes_handler_helpers.rb +20 -0
  219. data/spec/hybrid_platforms_conductor_test/helpers/platform_handler_helpers.rb +35 -0
  220. data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +127 -0
  221. data/spec/hybrid_platforms_conductor_test/helpers/plugins_helpers.rb +48 -0
  222. data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +789 -0
  223. data/spec/hybrid_platforms_conductor_test/helpers/reports_handler_helpers.rb +29 -0
  224. data/spec/hybrid_platforms_conductor_test/helpers/services_handler_helpers.rb +20 -0
  225. data/spec/hybrid_platforms_conductor_test/helpers/tests_runner_helpers.rb +38 -0
  226. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id1.rb +22 -0
  227. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id2.rb +22 -0
  228. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type/test_plugin_id3.rb +26 -0
  229. data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type2/test_plugin_id4.rb +26 -0
  230. data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +225 -0
  231. data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test2.rb +11 -0
  232. data/spec/hybrid_platforms_conductor_test/report_plugin.rb +35 -0
  233. data/spec/hybrid_platforms_conductor_test/test_action.rb +66 -0
  234. data/spec/hybrid_platforms_conductor_test/test_connector.rb +151 -0
  235. data/spec/hybrid_platforms_conductor_test/test_plugins/global.rb +30 -0
  236. data/spec/hybrid_platforms_conductor_test/test_plugins/node.rb +53 -0
  237. data/spec/hybrid_platforms_conductor_test/test_plugins/node_check.rb +47 -0
  238. data/spec/hybrid_platforms_conductor_test/test_plugins/node_ssh.rb +42 -0
  239. data/spec/hybrid_platforms_conductor_test/test_plugins/platform.rb +50 -0
  240. data/spec/hybrid_platforms_conductor_test/test_plugins/several_checks.rb +50 -0
  241. data/spec/hybrid_platforms_conductor_test/test_provisioner.rb +95 -0
  242. data/spec/hybrid_platforms_conductor_test/tests_report_plugin.rb +49 -0
  243. data/spec/spec_helper.rb +111 -0
  244. metadata +566 -0
@@ -0,0 +1,149 @@
1
+ module HybridPlatformsConductorTest
2
+
3
+ module Helpers
4
+
5
+ module DeployerHelpers
6
+
7
+ # Expect a given action to be setting up the mutex on a given node
8
+ #
9
+ # Parameters::
10
+ # * *action* (Hash<Symbol,Object>): The action to check
11
+ # * *node* (String): The concerned node
12
+ # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
13
+ def expect_action_to_lock_node(action, node, sudo: true)
14
+ expect(action[:scp].size).to eq 1
15
+ expect(action[:scp].first[0]).to match /^.+\/mutex_dir$/
16
+ expect(action[:scp].first[1]).to eq '.'
17
+ expect(action[:remote_bash]).to eq "while ! #{sudo ? 'sudo ' : ''}./mutex_dir lock /tmp/hybrid_platforms_conductor_deploy_lock \"$(ps -o ppid= -p $$)\"; do echo -e 'Another deployment is running on #{node}. Waiting for it to finish to continue...' ; sleep 5 ; done"
18
+ end
19
+
20
+ # Expect a given action to be releasing the mutex on a given node
21
+ #
22
+ # Parameters::
23
+ # * *action* (Hash<Symbol,Object>): The action to check
24
+ # * *node* (String): The concerned node
25
+ # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
26
+ def expect_action_to_unlock_node(action, node, sudo: true)
27
+ expect(action).to eq(remote_bash: "#{sudo ? 'sudo ' : ''}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock")
28
+ end
29
+
30
+ # Expect a given set of actions to be a deployment
31
+ #
32
+ # Parameters::
33
+ # * *actions* (Object): Actions
34
+ # * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
35
+ # * *check* (Boolean): Is the deploy only a check? [default: false]
36
+ # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
37
+ # * *expected_actions* (Array<Object>): Additional expected actions [default: []]
38
+ # * *mocked_result* (Hash<String, [Object, String, String]>): Expected result of the actions, per node, or nil for success [default: nil]
39
+ # Result::
40
+ # * Hash<String, [Integer or Symbol, String, String] >: Expected result of those expected actions
41
+ def expect_actions_to_deploy_on(actions, nodes, check: false, sudo: true, expected_actions: [], mocked_result: nil)
42
+ nodes = [nodes] if nodes.is_a?(String)
43
+ mocked_result = Hash[nodes.map { |node| [node, [0, "#{check ? 'Check' : 'Deploy'} successful", '']] }] if mocked_result.nil?
44
+ expect(actions.size).to eq nodes.size
45
+ nodes.each do |node|
46
+ expect(actions.key?(node)).to eq true
47
+ expect(actions[node].size).to eq(2 + expected_actions.size)
48
+ expect_action_to_lock_node(actions[node][0], node, sudo: sudo)
49
+ expect(actions[node][1..-2]).to eq expected_actions
50
+ expect(actions[node][-1]).to eq(bash: "echo \"#{check ? 'Checking' : 'Deploying'} on #{node}\"")
51
+ end
52
+ mocked_result
53
+ end
54
+
55
+ # Expect a given set of actions to be unlock deployments to a list of nodes
56
+ #
57
+ # Parameters::
58
+ # * *actions* (Object): Actions
59
+ # * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
60
+ # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
61
+ def expect_actions_to_unlock(actions, nodes, sudo: true)
62
+ nodes = [nodes] if nodes.is_a?(String)
63
+ expect(actions.size).to eq nodes.size
64
+ nodes.each do |node|
65
+ expect(actions.key?(node)).to eq true
66
+ expect_action_to_unlock_node(actions[node], node, sudo: sudo)
67
+ end
68
+ Hash[nodes.map { |node| [node, [0, 'Release mutex successful', '']] }]
69
+ end
70
+
71
+ # Expect a given set of actions to upload log files on a list of nodes
72
+ #
73
+ # Parameters::
74
+ # * *actions* (Object): Actions
75
+ # * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
76
+ # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
77
+ def expect_actions_to_upload_logs(actions, nodes, sudo: true)
78
+ nodes = [nodes] if nodes.is_a?(String)
79
+ expect(actions.size).to eq nodes.size
80
+ nodes.each do |node|
81
+ expect(actions.key?(node)).to eq true
82
+ expect(actions[node][:remote_bash]).to eq "#{sudo ? 'sudo ' : ''}mkdir -p /var/log/deployments"
83
+ expect(actions[node][:scp].first[1]).to eq '/var/log/deployments'
84
+ expect(actions[node][:scp][:group]).to eq 'root'
85
+ expect(actions[node][:scp][:owner]).to eq 'root'
86
+ expect(actions[node][:scp][:sudo]).to eq sudo
87
+ end
88
+ Hash[nodes.map { |node| [node, [0, 'Logs uploaded', '']] }]
89
+ end
90
+
91
+ # Expect some logs to have the following information.
92
+ # Expected logs format:
93
+ #
94
+ # date: 2019-08-14 17:02:57
95
+ # user: muriel
96
+ # debug: Yes
97
+ # repo_name: my_remote_platform
98
+ # commit_id: c0d16b1b7ae286ae4a059185957e08f0ddc95517
99
+ # commit_message: Test commit
100
+ # diff_files:
101
+ # ===== STDOUT =====
102
+ # Deploy successful
103
+ # ===== STDERR =====
104
+ #
105
+ # Parameters::
106
+ # * *logs* (String): The logs content
107
+ # * *stdout* (String): Expected STDOUT
108
+ # * *stderr* (String): Expected STDERR
109
+ # * *properties* (Hash<Symbol, String or Regexp>): Expected properties values, per name. Values can be exact strings or regexps.
110
+ def expect_logs_to_be(logs, stdout, stderr, properties)
111
+ lines = logs.split("\n")
112
+ idx_stdout = lines.index('===== STDOUT =====')
113
+ expect(idx_stdout).not_to eq nil
114
+ idx_stderr = lines.index('===== STDERR =====')
115
+ expect(idx_stderr).not_to eq nil
116
+ logs_properties = Hash[lines[0..idx_stdout - 1].map do |property_line|
117
+ property_fields = property_line.split(': ')
118
+ [
119
+ property_fields.first.to_sym,
120
+ property_fields[1..-1].join(': ')
121
+ ]
122
+ end]
123
+ expect(logs_properties.size).to eq properties.size
124
+ properties.each do |expected_property, expected_property_value|
125
+ expect(logs_properties.key?(expected_property)).to eq true
126
+ if expected_property_value.is_a?(String)
127
+ expect(logs_properties[expected_property]).to eq expected_property_value
128
+ else
129
+ expect(logs_properties[expected_property]).to match expected_property_value
130
+ end
131
+ end
132
+ expect(lines[idx_stdout + 1..idx_stderr - 1].join("\n")).to eq stdout
133
+ expect(lines[idx_stderr + 1..-1].join("\n")).to eq stderr
134
+ end
135
+
136
+ # Get a test Deployer
137
+ #
138
+ # Result::
139
+ # * Deployer: Deployer on which we can do testing
140
+ def test_deployer
141
+ @deployer = HybridPlatformsConductor::Deployer.new logger: logger, logger_stderr: logger, config: test_config, cmd_runner: test_cmd_runner, nodes_handler: test_nodes_handler, actions_executor: test_actions_executor, services_handler: test_services_handler unless @deployer
142
+ @deployer
143
+ end
144
+
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -0,0 +1,812 @@
1
+ module HybridPlatformsConductorTest
2
+
3
+ module Helpers
4
+
5
+ module DeployerTestHelpers
6
+
7
+ # Define deployment specs that are common for check mode and real deployment
8
+ #
9
+ # Parameters::
10
+ # * *check_mode* (Boolean): Are we in check-mode? [default: true]
11
+ def deploy_specs_for(check_mode: true)
12
+ expected_deploy_result = [0, "#{check_mode ? 'Check' : 'Deploy'} successful", '']
13
+ platform_name = check_mode ? 'platform' : 'my_remote_platform'
14
+
15
+ context "testing deployment#{check_mode ? ' in why-run mode' : ''}" do
16
+
17
+ # Get expected actions for a deployment
18
+ #
19
+ # Parameters::
20
+ # * *services* (Hash<String, Array<String> >): Expected nodes that should be deployed, with their corresponding services [default: { 'node' => %w[service] }]
21
+ # * *sudo* (Boolean): Do we expect sudo to be used in commands? [default: true]
22
+ # * *check_mode* (Boolean): Are we testing in check mode? [default: @check_mode]
23
+ # * *mocked_deploy_result* (Hash or nil): Mocked result of the deployment actions, or nil to use the helper's default [default: nil]
24
+ # * *additional_expected_actions* (Array): Additional expected actions [default: []]
25
+ # * *expect_concurrent_actions* (Boolean): Are actions expected to be run in parallel? [default: false]
26
+ # * *expect_actions_timeout* (Integer or nil): Expected timeout in actions, or nil for none [default: nil]
27
+ def expected_actions_for_deploy_on(
28
+ services: { 'node' => %w[service] },
29
+ sudo: true,
30
+ check_mode: @check_mode,
31
+ mocked_deploy_result: nil,
32
+ additional_expected_actions: [],
33
+ expect_concurrent_actions: false,
34
+ expect_actions_timeout: nil
35
+ )
36
+ actions = [
37
+ # First run, we expect the mutex to be setup, and the deployment actions to be run
38
+ proc do |actions_per_nodes, timeout: nil, concurrent: false, log_to_dir: 'run_logs', log_to_stdout: true|
39
+ expect(timeout).to eq expect_actions_timeout
40
+ expect(concurrent).to eq expect_concurrent_actions
41
+ expect(log_to_dir).to eq 'run_logs'
42
+ expect_actions_to_deploy_on(
43
+ actions_per_nodes,
44
+ services.keys,
45
+ check: check_mode,
46
+ sudo: sudo,
47
+ mocked_result: mocked_deploy_result,
48
+ expected_actions: additional_expected_actions
49
+ )
50
+ end,
51
+ # Second run, we expect the mutex to be released
52
+ proc { |actions_per_nodes| expect_actions_to_unlock(actions_per_nodes, services.keys, sudo: sudo) }
53
+ ]
54
+ services.each do |node, node_services|
55
+ expect(test_services_handler).to receive(:actions_to_deploy_on).with(node, node_services, check_mode) do
56
+ [{ bash: "echo \"#{check_mode ? 'Checking' : 'Deploying'} on #{node}\"" }]
57
+ end
58
+ end
59
+ # Third run, we expect logs to be uploaded on the node (only if not check mode)
60
+ unless check_mode
61
+ services.each do |node, node_services|
62
+ expect(test_services_handler).to receive(:log_info_for).with(node, node_services) do
63
+ {
64
+ repo_name_0: 'platform',
65
+ commit_id_0: '123456',
66
+ commit_message_0: 'Test commit'
67
+ }
68
+ end
69
+ end
70
+ actions << proc { |actions_per_nodes| expect_actions_to_upload_logs(actions_per_nodes, services.keys, sudo: sudo) }
71
+ end
72
+ actions
73
+ end
74
+
75
+ # Prepare a platform ready to test deployments on.
76
+ #
77
+ # Parameters::
78
+ # * *nodes_info* (Hash): Node info to give the platform [default: 1 node having 1 service]
79
+ # * *expect_default_actions* (Boolean): Should we expect default actions? [default: true]
80
+ # * *expect_sudo* (Boolean): Do we expect sudo to be used in commands? [default: true]
81
+ # * *expect_secrets* (Hash): Secrets to be expected during deployment [default: {}]
82
+ # * *expect_local_environment* (Boolean): Expected local environment flag [default: false]
83
+ # * *expect_additional_actions* (Array): Additional expected actions [default: []]
84
+ # * *expect_concurrent_actions* (Boolean): Are actions expected to be run in parallel? [default: false]
85
+ # * *expect_actions_timeout* (Integer or nil): Expected timeout in actions, or nil for none [default: nil]
86
+ # * *check_mode* (Boolean): Are we testing in check mode? [default: @check_mode]
87
+ # * *additional_config* (String): Additional configuration to set [default: '']
88
+ # * Proc: Code called once the platform is ready for testing the deployer
89
+ # * Parameters::
90
+ # * *repository* (String): Path to the repository
91
+ def with_platform_to_deploy(
92
+ nodes_info: { nodes: { 'node' => { services: %w[service] } } },
93
+ expect_default_actions: true,
94
+ expect_sudo: true,
95
+ expect_secrets: {},
96
+ expect_local_environment: false,
97
+ expect_additional_actions: [],
98
+ expect_concurrent_actions: false,
99
+ expect_actions_timeout: nil,
100
+ check_mode: @check_mode,
101
+ additional_config: ''
102
+ )
103
+ platform_name = check_mode ? 'platform' : 'my_remote_platform'
104
+ with_test_platform(nodes_info, !check_mode, additional_config) do |repository|
105
+ with_connections_mocked_on(nodes_info[:nodes].keys) do
106
+ # Mock the ServicesHandler accesses
107
+ expect_services_to_deploy = Hash[nodes_info[:nodes].map do |node, node_info|
108
+ [node, node_info[:services]]
109
+ end]
110
+ unless check_mode
111
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
112
+ services: expect_services_to_deploy,
113
+ secrets: expect_secrets,
114
+ local_environment: expect_local_environment
115
+ ) do
116
+ nil
117
+ end
118
+ end
119
+ expect(test_services_handler).to receive(:package).with(
120
+ services: expect_services_to_deploy,
121
+ secrets: expect_secrets,
122
+ local_environment: expect_local_environment
123
+ )
124
+ expect(test_services_handler).to receive(:prepare_for_deploy).with(
125
+ services: expect_services_to_deploy,
126
+ secrets: expect_secrets,
127
+ local_environment: expect_local_environment,
128
+ why_run: check_mode
129
+ )
130
+ expect_actions_executor_runs(expected_actions_for_deploy_on(
131
+ services: expect_services_to_deploy,
132
+ check_mode: check_mode,
133
+ sudo: expect_sudo,
134
+ additional_expected_actions: expect_additional_actions,
135
+ expect_concurrent_actions: expect_concurrent_actions,
136
+ expect_actions_timeout: expect_actions_timeout
137
+ )) if expect_default_actions
138
+ test_deployer.use_why_run = true if check_mode
139
+ yield repository
140
+ end
141
+ end
142
+ end
143
+
144
+ # Prepare a directory with certificates
145
+ #
146
+ # Parameters::
147
+ # * Proc: Code called with the directory created with a mocked certificate
148
+ # * Parameters::
149
+ # * *certs_dir* (String): Directory containing certificates
150
+ def with_certs_dir
151
+ with_repository do |repository|
152
+ certs_dir = "#{repository}/certificates"
153
+ FileUtils.mkdir_p certs_dir
154
+ File.write("#{certs_dir}/test_cert.crt", 'Hello')
155
+ yield certs_dir
156
+ end
157
+ end
158
+
159
+ before :each do
160
+ @check_mode = check_mode
161
+ end
162
+
163
+ it 'deploys on 1 node' do
164
+ with_platform_to_deploy do
165
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
166
+ end
167
+ end
168
+
169
+ it 'deploys on 1 node having several services' do
170
+ with_platform_to_deploy(nodes_info: { nodes: { 'node' => { services: %w[service1 service2 service3] } } }) do
171
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
172
+ end
173
+ end
174
+
175
+ it 'deploys on 1 node in a local environment' do
176
+ with_platform_to_deploy(expect_local_environment: true) do
177
+ test_deployer.local_environment = true
178
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
179
+ expect(test_deployer.local_environment).to eq true
180
+ end
181
+ end
182
+
183
+ it 'deploys on 1 node using root' do
184
+ with_platform_to_deploy(expect_sudo: false) do
185
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
186
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
187
+ end
188
+ end
189
+
190
+ it 'deploys on 1 node using 1 secret' do
191
+ with_platform_to_deploy(expect_secrets: { 'secret1' => 'password1' }) do
192
+ test_deployer.secrets = [{ 'secret1' => 'password1' }]
193
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
194
+ end
195
+ end
196
+
197
+ it 'deploys on 1 node using several secrets' do
198
+ with_platform_to_deploy(expect_secrets: { 'secret1' => 'password1', 'secret2' => 'password2' }) do
199
+ test_deployer.secrets = [{ 'secret1' => 'password1' }, { 'secret2' => 'password2' }]
200
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
201
+ end
202
+ end
203
+
204
+ it 'deploys on 1 node in local environment with certificates to install using hpc_certificates on Debian' do
205
+ with_certs_dir do |certs_dir|
206
+ with_platform_to_deploy(
207
+ nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
208
+ expect_local_environment: true,
209
+ expect_additional_actions: [
210
+ { remote_bash: 'sudo apt update && sudo apt install -y ca-certificates' },
211
+ {
212
+ remote_bash: 'sudo update-ca-certificates',
213
+ scp: {
214
+ certs_dir => '/usr/local/share/ca-certificates',
215
+ :sudo => true
216
+ }
217
+ }
218
+ ]
219
+ ) do
220
+ ENV['hpc_certificates'] = certs_dir
221
+ test_deployer.local_environment = true
222
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
223
+ end
224
+ end
225
+ end
226
+
227
+ it 'deploys on 1 node with certificates to install using hpc_certificates on Debian but ignores them in non-local environment' do
228
+ with_certs_dir do |certs_dir|
229
+ with_platform_to_deploy(nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } }) do
230
+ ENV['hpc_certificates'] = certs_dir
231
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
232
+ end
233
+ end
234
+ end
235
+
236
+ it 'deploys on 1 node with certificates to install using hpc_certificates on Debian using root' do
237
+ with_certs_dir do |certs_dir|
238
+ with_platform_to_deploy(
239
+ nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
240
+ expect_sudo: false,
241
+ expect_local_environment: true,
242
+ expect_additional_actions: [
243
+ { remote_bash: 'apt update && apt install -y ca-certificates' },
244
+ {
245
+ remote_bash: 'update-ca-certificates',
246
+ scp: {
247
+ certs_dir => '/usr/local/share/ca-certificates',
248
+ :sudo => false
249
+ }
250
+ }
251
+ ]
252
+ ) do
253
+ ENV['hpc_certificates'] = certs_dir
254
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
255
+ test_deployer.local_environment = true
256
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
257
+ end
258
+ end
259
+ end
260
+
261
+ it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS' do
262
+ with_certs_dir do |certs_dir|
263
+ with_platform_to_deploy(
264
+ nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
265
+ expect_local_environment: true,
266
+ expect_additional_actions: [
267
+ { remote_bash: 'sudo yum install -y ca-certificates' },
268
+ {
269
+ remote_bash: ['sudo update-ca-trust enable', 'sudo update-ca-trust extract'],
270
+ scp: {
271
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
272
+ :sudo => true
273
+ }
274
+ }
275
+ ]
276
+ ) do
277
+ ENV['hpc_certificates'] = certs_dir
278
+ test_deployer.local_environment = true
279
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
280
+ end
281
+ end
282
+ end
283
+
284
+ it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS using root' do
285
+ with_certs_dir do |certs_dir|
286
+ with_platform_to_deploy(
287
+ nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
288
+ expect_sudo: false,
289
+ expect_local_environment: true,
290
+ expect_additional_actions: [
291
+ { remote_bash: 'yum install -y ca-certificates' },
292
+ {
293
+ remote_bash: ['update-ca-trust enable', 'update-ca-trust extract'],
294
+ scp: {
295
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
296
+ :sudo => false
297
+ }
298
+ }
299
+ ]
300
+ ) do
301
+ ENV['hpc_certificates'] = certs_dir
302
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
303
+ test_deployer.local_environment = true
304
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
305
+ end
306
+ end
307
+ end
308
+
309
+ it 'deploys on several nodes' do
310
+ with_platform_to_deploy(nodes_info: { nodes: {
311
+ 'node1' => { services: %w[service1] },
312
+ 'node2' => { services: %w[service2] },
313
+ 'node3' => { services: %w[service3] }
314
+ } }) do
315
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
316
+ 'node1' => expected_deploy_result,
317
+ 'node2' => expected_deploy_result,
318
+ 'node3' => expected_deploy_result
319
+ )
320
+ end
321
+ end
322
+
323
+ it 'deploys on several nodes in parallel' do
324
+ with_platform_to_deploy(
325
+ nodes_info: {
326
+ nodes: {
327
+ 'node1' => { services: %w[service1] },
328
+ 'node2' => { services: %w[service2] },
329
+ 'node3' => { services: %w[service3] }
330
+ }
331
+ },
332
+ expect_concurrent_actions: true
333
+ ) do
334
+ test_deployer.concurrent_execution = true
335
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
336
+ 'node1' => expected_deploy_result,
337
+ 'node2' => expected_deploy_result,
338
+ 'node3' => expected_deploy_result
339
+ )
340
+ end
341
+ end
342
+
343
+ it 'deploys on several nodes with timeout' do
344
+ with_platform_to_deploy(
345
+ nodes_info: {
346
+ nodes: {
347
+ 'node1' => { services: %w[service1] },
348
+ 'node2' => { services: %w[service2] },
349
+ 'node3' => { services: %w[service3] }
350
+ }
351
+ },
352
+ expect_actions_timeout: 5
353
+ ) do
354
+ test_deployer.timeout = 5
355
+ expect(test_deployer.deploy_on(%w[node1 node2 node3])).to eq(
356
+ 'node1' => expected_deploy_result,
357
+ 'node2' => expected_deploy_result,
358
+ 'node3' => expected_deploy_result
359
+ )
360
+ end
361
+ end
362
+
363
+ context 'checking deployment retries' do
364
+
365
+ # Prepare a platform ready to test deployments' retries on.
366
+ #
367
+ # Parameters::
368
+ # * *nodes_info* (Hash): Node info to give the platform [default: { nodes: { 'node' => {} } }]
369
+ # * Proc: Code called once the platform is ready for testing the deployer
370
+ # * Parameters::
371
+ # * *repository* (String): Path to the repository
372
+ def with_platform_to_retry_deploy(nodes_info: { nodes: { 'node' => { services: %w[service] } } })
373
+ with_platform_to_deploy(
374
+ nodes_info: nodes_info,
375
+ expect_default_actions: false,
376
+ additional_config: "
377
+ for_nodes([#{nodes_info[:nodes].keys.map { |node| "'#{node}'" }.join(', ')}]) do
378
+ retry_deploy_for_errors_on_stdout [
379
+ 'stdout non-deterministic error'
380
+ ]
381
+ retry_deploy_for_errors_on_stderr [
382
+ 'stderr non-deterministic error',
383
+ /stderr regexp error \\d+/
384
+ ]
385
+ end
386
+ for_nodes([#{nodes_info[:nodes].keys.map { |node| "'#{node}'" }.join(', ')}]) do
387
+ retry_deploy_for_errors_on_stdout [
388
+ /stdout regexp error \\d+/
389
+ ]
390
+ end
391
+ "
392
+ ) do |repository|
393
+ yield repository
394
+ end
395
+ end
396
+
397
+ # Mock a sequential list of deployments
398
+ #
399
+ # Parameters::
400
+ # * *statuses* (Array<Hash<String,Status> or Status>)>): List of mocked deployment statuses per node name, or just the status for the default node.
401
+ # A status is a triplet [Integer or Symbol, String, String]: exit status, stdout and stderr.
402
+ def mock_deploys_with(statuses)
403
+ expect_actions_executor_runs(statuses.map do |status|
404
+ status = { 'node' => status } if status.is_a?(Array)
405
+ expected_actions_for_deploy_on(
406
+ services: Hash[status.keys.map { |node| [node, %w[service]] }],
407
+ mocked_deploy_result: status
408
+ )
409
+ end.flatten)
410
+ end
411
+
412
+ it 'restarts deployment for a non-deterministic error' do
413
+ with_platform_to_retry_deploy do
414
+ test_deployer.nbr_retries_on_error = 1
415
+ mock_deploys_with [
416
+ [1, "Error: This is a stdout non-deterministic error\nDeploy failed\n", ''],
417
+ [0, 'Deploy ok', '']
418
+ ]
419
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
420
+ 0,
421
+ <<~EOS,
422
+ Error: This is a stdout non-deterministic error
423
+ Deploy failed
424
+
425
+ Deployment exit status code: 1
426
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
427
+ Deploy ok
428
+ EOS
429
+ <<~EOS
430
+ !!! 1 retriable errors detected in this deployment:
431
+ * stdout non-deterministic error
432
+
433
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
434
+
435
+ EOS
436
+ ])
437
+ end
438
+ end
439
+
440
+ it 'restarts deployment for a non-deterministic error matched with a Regexp' do
441
+ with_platform_to_retry_deploy do
442
+ test_deployer.nbr_retries_on_error = 1
443
+ mock_deploys_with [
444
+ [1, "Error: This is a stdout regexp error 42\nDeploy failed\n", ''],
445
+ [0, 'Deploy ok', '']
446
+ ]
447
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
448
+ 0,
449
+ <<~EOS,
450
+ Error: This is a stdout regexp error 42
451
+ Deploy failed
452
+
453
+ Deployment exit status code: 1
454
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
455
+ Deploy ok
456
+ EOS
457
+ <<~EOS
458
+ !!! 1 retriable errors detected in this deployment:
459
+ * /stdout regexp error \\d+/ matched 'stdout regexp error 42'
460
+
461
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
462
+
463
+ EOS
464
+ ])
465
+ end
466
+ end
467
+
468
+ it 'restarts deployment for a non-deterministic error on stderr' do
469
+ with_platform_to_retry_deploy do
470
+ test_deployer.nbr_retries_on_error = 1
471
+ mock_deploys_with [
472
+ [1, '', "Error: This is a stderr non-deterministic error\nDeploy failed\n"],
473
+ [0, 'Deploy ok', '']
474
+ ]
475
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
476
+ 0,
477
+ <<~EOS,
478
+
479
+ Deployment exit status code: 1
480
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
481
+ Deploy ok
482
+ EOS
483
+ <<~EOS
484
+ Error: This is a stderr non-deterministic error
485
+ Deploy failed
486
+ !!! 1 retriable errors detected in this deployment:
487
+ * stderr non-deterministic error
488
+
489
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
490
+
491
+ EOS
492
+ ])
493
+ end
494
+ end
495
+
496
+ it 'restarts deployment for a non-deterministic error on stderr matched with a Regexp' do
497
+ with_platform_to_retry_deploy do
498
+ test_deployer.nbr_retries_on_error = 1
499
+ mock_deploys_with [
500
+ [1, '', "Error: This is a stderr regexp error 42\nDeploy failed\n"],
501
+ [0, 'Deploy ok', '']
502
+ ]
503
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
504
+ 0,
505
+ <<~EOS,
506
+
507
+ Deployment exit status code: 1
508
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
509
+ Deploy ok
510
+ EOS
511
+ <<~EOS
512
+ Error: This is a stderr regexp error 42
513
+ Deploy failed
514
+ !!! 1 retriable errors detected in this deployment:
515
+ * /stderr regexp error \\d+/ matched 'stderr regexp error 42'
516
+
517
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
518
+
519
+ EOS
520
+ ])
521
+ end
522
+ end
523
+
524
+ it 'stops restarting deployments for a non-deterministic error when errors has disappeared, even if retries were remaining' do
525
+ with_platform_to_retry_deploy do
526
+ test_deployer.nbr_retries_on_error = 5
527
+ mock_deploys_with [
528
+ [1, "Error: This is a stdout non-deterministic error 1\nDeploy failed", ''],
529
+ [1, "Error: This is a stdout non-deterministic error 2\nDeploy failed", ''],
530
+ [0, 'Deploy ok', '']
531
+ ]
532
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
533
+ 0,
534
+ <<~EOS,
535
+ Error: This is a stdout non-deterministic error 1
536
+ Deploy failed
537
+ Deployment exit status code: 1
538
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
539
+ Error: This is a stdout non-deterministic error 2
540
+ Deploy failed
541
+
542
+ Deployment exit status code: 1
543
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
544
+ Deploy ok
545
+ EOS
546
+ <<~EOS
547
+ !!! 1 retriable errors detected in this deployment:
548
+ * stdout non-deterministic error
549
+
550
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
551
+ !!! 1 retriable errors detected in this deployment:
552
+ * stdout non-deterministic error
553
+
554
+
555
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
556
+
557
+ EOS
558
+ ])
559
+ end
560
+ end
561
+
562
+ it 'stops restarting deployments for a non-deterministic error that became deterministic, even if retries were remaining' do
563
+ with_platform_to_retry_deploy do
564
+ test_deployer.nbr_retries_on_error = 5
565
+ mock_deploys_with [
566
+ [1, "Error: This is a stdout non-deterministic error 1\nDeploy failed", ''],
567
+ [1, "Error: This is a stdout non-deterministic error 2\nDeploy failed", ''],
568
+ [1, "Error: This is a stdout deterministic error 3\nDeploy failed", '']
569
+ ]
570
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
571
+ 1,
572
+ <<~EOS,
573
+ Error: This is a stdout non-deterministic error 1
574
+ Deploy failed
575
+ Deployment exit status code: 1
576
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
577
+ Error: This is a stdout non-deterministic error 2
578
+ Deploy failed
579
+
580
+ Deployment exit status code: 1
581
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
582
+ Error: This is a stdout deterministic error 3
583
+ Deploy failed
584
+ EOS
585
+ <<~EOS
586
+ !!! 1 retriable errors detected in this deployment:
587
+ * stdout non-deterministic error
588
+
589
+ !!! Retry deployment due to non-deterministic error (4 remaining attempts)...
590
+ !!! 1 retriable errors detected in this deployment:
591
+ * stdout non-deterministic error
592
+
593
+
594
+ !!! Retry deployment due to non-deterministic error (3 remaining attempts)...
595
+
596
+ EOS
597
+ ])
598
+ end
599
+ end
600
+
601
+ it 'does not restart deployment for a deterministic error' do
602
+ with_platform_to_retry_deploy do
603
+ test_deployer.nbr_retries_on_error = 5
604
+ mock_deploys_with [
605
+ [1, "Error: This is a stdout deterministic error\nDeploy failed\n", '']
606
+ ]
607
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
608
+ 1,
609
+ <<~EOS,
610
+ Error: This is a stdout deterministic error
611
+ Deploy failed
612
+ EOS
613
+ ''
614
+ ])
615
+ end
616
+ end
617
+
618
+ it 'does not restart deployment for a non-deterministic error logged during a successful deploy' do
619
+ with_platform_to_retry_deploy do
620
+ test_deployer.nbr_retries_on_error = 5
621
+ mock_deploys_with [
622
+ [0, "Error: This is a stdout non-deterministic error\nDeploy failed\n", '']
623
+ ]
624
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
625
+ 0,
626
+ <<~EOS,
627
+ Error: This is a stdout non-deterministic error
628
+ Deploy failed
629
+ EOS
630
+ ''
631
+ ])
632
+ end
633
+ end
634
+
635
+ it 'does not restart deployment for a non-deterministic error if retries are 0' do
636
+ with_platform_to_retry_deploy do
637
+ test_deployer.nbr_retries_on_error = 0
638
+ mock_deploys_with [
639
+ [1, "Error: This is a stdout non-deterministic error\nDeploy failed\n", '']
640
+ ]
641
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
642
+ 1,
643
+ <<~EOS,
644
+ Error: This is a stdout non-deterministic error
645
+ Deploy failed
646
+ EOS
647
+ ''
648
+ ])
649
+ end
650
+ end
651
+
652
+ it 'restarts deployment for non-deterministic errors with a limited amount of retries' do
653
+ with_platform_to_retry_deploy do
654
+ test_deployer.nbr_retries_on_error = 2
655
+ mock_deploys_with [
656
+ [1, "Error: This is a stdout non-deterministic error 1\nDeploy failed", ''],
657
+ [1, "Error: This is a stdout non-deterministic error 2\nDeploy failed", ''],
658
+ [1, "Error: This is a stdout non-deterministic error 3\nDeploy failed", '']
659
+ ]
660
+ expect(test_deployer.deploy_on('node')).to eq('node' => [
661
+ 1,
662
+ <<~EOS,
663
+ Error: This is a stdout non-deterministic error 1
664
+ Deploy failed
665
+ Deployment exit status code: 1
666
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
667
+ Error: This is a stdout non-deterministic error 2
668
+ Deploy failed
669
+
670
+ Deployment exit status code: 1
671
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
672
+ Error: This is a stdout non-deterministic error 3
673
+ Deploy failed
674
+ EOS
675
+ <<~EOS
676
+ !!! 1 retriable errors detected in this deployment:
677
+ * stdout non-deterministic error
678
+
679
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
680
+ !!! 1 retriable errors detected in this deployment:
681
+ * stdout non-deterministic error
682
+
683
+
684
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
685
+
686
+ EOS
687
+ ])
688
+ end
689
+ end
690
+
691
+ it 'restarts deployment for non-deterministic errors only on nodes needing it' do
692
+ with_platform_to_retry_deploy(nodes_info: { nodes: {
693
+ 'node1' => { services: %w[service] },
694
+ 'node2' => { services: %w[service] },
695
+ 'node3' => { services: %w[service] },
696
+ 'node4' => { services: %w[service] }
697
+ } }) do
698
+ test_deployer.nbr_retries_on_error = 2
699
+ # Some nodes deploy successfully,
700
+ # others have deterministic errors,
701
+ # others have non-deterministic errors being corrected
702
+ # others have non-deterministic errors not being corrected
703
+ mock_deploys_with [
704
+ {
705
+ 'node1' => [1, "Error: This is a stdout non-deterministic error\n[node1] Deploy failed\n", ''],
706
+ 'node2' => [0, '[node2] Deploy ok', ''],
707
+ 'node3' => [1, "Error: This is a stdout non-deterministic error\n[node3] Deploy failed\n", ''],
708
+ 'node4' => [1, "Error: This is a stdout non-deterministic error\n[node4] Deploy failed\n", '']
709
+ },
710
+ {
711
+ 'node1' => [0, '[node1] Deploy ok', ''],
712
+ 'node3' => [1, "Error: This is a stdout deterministic error\n[node3] Deploy failed\n", ''],
713
+ 'node4' => [1, "Error: This is a stdout non-deterministic error\n[node4] Deploy failed\n", '']
714
+ },
715
+ {
716
+ 'node4' => [1, "Error: This is a stdout non-deterministic error\n[node4] Deploy failed\n", '']
717
+ }
718
+ ]
719
+ expect(test_deployer.deploy_on(%w[node1 node2 node3 node4])).to eq(
720
+ 'node1' => [
721
+ 0,
722
+ <<~EOS,
723
+ Error: This is a stdout non-deterministic error
724
+ [node1] Deploy failed
725
+
726
+ Deployment exit status code: 1
727
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
728
+ [node1] Deploy ok
729
+ EOS
730
+ <<~EOS
731
+ !!! 1 retriable errors detected in this deployment:
732
+ * stdout non-deterministic error
733
+
734
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
735
+
736
+ EOS
737
+ ],
738
+ 'node2' => [
739
+ 0,
740
+ '[node2] Deploy ok',
741
+ ''
742
+ ],
743
+ 'node3' => [
744
+ 1,
745
+ <<~EOS,
746
+ Error: This is a stdout non-deterministic error
747
+ [node3] Deploy failed
748
+
749
+ Deployment exit status code: 1
750
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
751
+ Error: This is a stdout deterministic error
752
+ [node3] Deploy failed
753
+
754
+ EOS
755
+ <<~EOS
756
+ !!! 1 retriable errors detected in this deployment:
757
+ * stdout non-deterministic error
758
+
759
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
760
+
761
+ EOS
762
+ ],
763
+ 'node4' => [
764
+ 1,
765
+ <<~EOS,
766
+ Error: This is a stdout non-deterministic error
767
+ [node4] Deploy failed
768
+
769
+ Deployment exit status code: 1
770
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
771
+ Error: This is a stdout non-deterministic error
772
+ [node4] Deploy failed
773
+
774
+
775
+ Deployment exit status code: 1
776
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
777
+ Error: This is a stdout non-deterministic error
778
+ [node4] Deploy failed
779
+
780
+ EOS
781
+ <<~EOS
782
+ !!! 1 retriable errors detected in this deployment:
783
+ * stdout non-deterministic error
784
+
785
+ !!! Retry deployment due to non-deterministic error (1 remaining attempts)...
786
+ !!! 1 retriable errors detected in this deployment:
787
+ * stdout non-deterministic error
788
+
789
+
790
+ !!! Retry deployment due to non-deterministic error (0 remaining attempts)...
791
+
792
+ EOS
793
+ ]
794
+ )
795
+ end
796
+ end
797
+
798
+ end
799
+
800
+ end
801
+
802
+ end
803
+
804
+ end
805
+
806
+ end
807
+
808
+ end
809
+
810
+ RSpec.configure do |c|
811
+ c.extend HybridPlatformsConductorTest::Helpers::DeployerTestHelpers
812
+ end