hybrid_platforms_conductor 32.11.1 → 32.13.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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1115 -0
  3. data/LICENSE.md +31 -0
  4. data/README.md +395 -0
  5. data/bin/setup +1 -1
  6. data/docs/api.md +349 -0
  7. data/docs/config_dsl.md +315 -0
  8. data/docs/executables.md +226 -0
  9. data/docs/executables/check-node.md +155 -0
  10. data/docs/executables/deploy.md +198 -0
  11. data/docs/executables/dump_nodes_json.md +110 -0
  12. data/docs/executables/free_ips.md +93 -0
  13. data/docs/executables/free_veids.md +73 -0
  14. data/docs/executables/get_impacted_nodes.md +94 -0
  15. data/docs/executables/last_deploys.md +114 -0
  16. data/docs/executables/nodes_to_deploy.md +139 -0
  17. data/docs/executables/report.md +159 -0
  18. data/docs/executables/run.md +126 -0
  19. data/docs/executables/setup.md +92 -0
  20. data/docs/executables/ssh_config.md +151 -0
  21. data/docs/executables/test.md +213 -0
  22. data/docs/executables/topograph.md +139 -0
  23. data/docs/gen/mermaid/README.md-0.png +0 -0
  24. data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
  25. data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
  26. data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
  27. data/docs/gen/mermaid/docs/executables/free_veids.md-0.png +0 -0
  28. data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
  29. data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
  30. data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
  31. data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
  32. data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
  33. data/docs/gen/mermaid/docs/executables/setup.md-0.png +0 -0
  34. data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
  35. data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
  36. data/docs/install.md +161 -0
  37. data/docs/plugins.md +215 -0
  38. data/docs/plugins/action/bash.md +37 -0
  39. data/docs/plugins/action/interactive.md +37 -0
  40. data/docs/plugins/action/remote_bash.md +67 -0
  41. data/docs/plugins/action/ruby.md +69 -0
  42. data/docs/plugins/action/scp.md +61 -0
  43. data/docs/plugins/cmdb/config.md +46 -0
  44. data/docs/plugins/cmdb/host_ip.md +33 -0
  45. data/docs/plugins/cmdb/host_keys.md +33 -0
  46. data/docs/plugins/cmdb/platform_handlers.md +33 -0
  47. data/docs/plugins/connector/local.md +28 -0
  48. data/docs/plugins/connector/ssh.md +95 -0
  49. data/docs/plugins/platform_handler/yaml_inventory.md +105 -0
  50. data/docs/plugins/provisioner/docker.md +27 -0
  51. data/docs/plugins/provisioner/podman.md +27 -0
  52. data/docs/plugins/provisioner/proxmox.md +115 -0
  53. data/docs/plugins/report/confluence.md +49 -0
  54. data/docs/plugins/report/mediawiki.md +28 -0
  55. data/docs/plugins/report/stdout.md +32 -0
  56. data/docs/plugins/test/bitbucket_conf.md +97 -0
  57. data/docs/plugins/test/can_be_checked.md +27 -0
  58. data/docs/plugins/test/check_deploy_and_idempotence.md +61 -0
  59. data/docs/plugins/test/check_from_scratch.md +28 -0
  60. data/docs/plugins/test/connection.md +27 -0
  61. data/docs/plugins/test/deploy_freshness.md +27 -0
  62. data/docs/plugins/test/deploy_from_scratch.md +28 -0
  63. data/docs/plugins/test/deploy_removes_root_access.md +29 -0
  64. data/docs/plugins/test/divergence.md +41 -0
  65. data/docs/plugins/test/executables.md +26 -0
  66. data/docs/plugins/test/file_system.md +49 -0
  67. data/docs/plugins/test/file_system_hdfs.md +65 -0
  68. data/docs/plugins/test/hostname.md +27 -0
  69. data/docs/plugins/test/idempotence.md +56 -0
  70. data/docs/plugins/test/ip.md +28 -0
  71. data/docs/plugins/test/jenkins_ci_conf.md +54 -0
  72. data/docs/plugins/test/jenkins_ci_masters_ok.md +54 -0
  73. data/docs/plugins/test/linear_strategy.md +26 -0
  74. data/docs/plugins/test/local_users.md +48 -0
  75. data/docs/plugins/test/mounts.md +55 -0
  76. data/docs/plugins/test/orphan_files.md +38 -0
  77. data/docs/plugins/test/ports.md +50 -0
  78. data/docs/plugins/test/private_ips.md +27 -0
  79. data/docs/plugins/test/public_ips.md +27 -0
  80. data/docs/plugins/test/spectre.md +26 -0
  81. data/docs/plugins/test/veids.md +27 -0
  82. data/docs/plugins/test/vulnerabilities.md +65 -0
  83. data/docs/plugins/test_report/confluence.md +43 -0
  84. data/docs/plugins/test_report/stdout.md +26 -0
  85. data/docs/plugins_create.md +135 -0
  86. data/docs/tutorial.md +61 -0
  87. data/docs/tutorial/01_installation.md +131 -0
  88. data/docs/tutorial/02_first_node.md +468 -0
  89. data/docs/tutorial/03_scale.md +878 -0
  90. data/docs/tutorial/04_test.md +977 -0
  91. data/docs/tutorial/05_extend_with_plugins.md +1132 -0
  92. data/examples/bare/Gemfile +4 -0
  93. data/examples/bare/hpc_config.rb +2 -0
  94. data/examples/localhost/Gemfile +4 -0
  95. data/examples/localhost/hpc_config.rb +2 -0
  96. data/examples/localhost/inventory.yaml +4 -0
  97. data/examples/tutorial/01_installation/my-platforms/Gemfile +3 -0
  98. data/examples/tutorial/01_installation/my-platforms/hpc_config.rb +0 -0
  99. data/examples/tutorial/02_first_node/my-platforms/Gemfile +3 -0
  100. data/examples/tutorial/02_first_node/my-platforms/hpc_config.rb +1 -0
  101. data/examples/tutorial/02_first_node/my-service-conf-repo/inventory.yaml +13 -0
  102. data/examples/tutorial/02_first_node/my-service-conf-repo/my-service.conf.erb +3 -0
  103. data/examples/tutorial/02_first_node/my-service-conf-repo/service_my-service.rb +58 -0
  104. data/examples/tutorial/02_first_node/node/my-service.conf +4 -0
  105. data/examples/tutorial/03_scale/my-platforms/Gemfile +3 -0
  106. data/examples/tutorial/03_scale/my-platforms/hpc_config.rb +1 -0
  107. data/examples/tutorial/03_scale/my-platforms/my_commands.bash +2 -0
  108. data/examples/tutorial/03_scale/my-service-conf-repo/inventory.yaml +90 -0
  109. data/examples/tutorial/03_scale/my-service-conf-repo/my-service.conf.erb +3 -0
  110. data/examples/tutorial/03_scale/my-service-conf-repo/service_my-service.rb +58 -0
  111. data/examples/tutorial/03_scale/my-service-conf-repo/service_web-hello.rb +43 -0
  112. data/examples/tutorial/03_scale/node/my-service.conf +4 -0
  113. data/examples/tutorial/03_scale/web_docker_image/Dockerfile +33 -0
  114. data/examples/tutorial/03_scale/web_docker_image/hello_world.txt +1 -0
  115. data/examples/tutorial/03_scale/web_docker_image/hpc_root.key +27 -0
  116. data/examples/tutorial/03_scale/web_docker_image/hpc_root.key.pub +1 -0
  117. data/examples/tutorial/03_scale/web_docker_image/main.go +43 -0
  118. data/examples/tutorial/03_scale/web_docker_image/start.sh +7 -0
  119. data/examples/tutorial/03_scale/web_docker_image/test.bash +6 -0
  120. data/examples/tutorial/04_test/my-platforms/Gemfile +3 -0
  121. data/examples/tutorial/04_test/my-platforms/hpc_config.rb +12 -0
  122. data/examples/tutorial/04_test/my-platforms/images/debian_10/Dockerfile +13 -0
  123. data/examples/tutorial/04_test/my-platforms/my_commands.bash +2 -0
  124. data/examples/tutorial/04_test/my-service-conf-repo/inventory.yaml +100 -0
  125. data/examples/tutorial/04_test/my-service-conf-repo/my-service.conf.erb +3 -0
  126. data/examples/tutorial/04_test/my-service-conf-repo/service_my-service.rb +58 -0
  127. data/examples/tutorial/04_test/my-service-conf-repo/service_web-hello.rb +43 -0
  128. data/examples/tutorial/04_test/node/my-service.conf +4 -0
  129. data/examples/tutorial/04_test/web_docker_image/Dockerfile +33 -0
  130. data/examples/tutorial/04_test/web_docker_image/hello_world.txt +1 -0
  131. data/examples/tutorial/04_test/web_docker_image/hpc_root.key +27 -0
  132. data/examples/tutorial/04_test/web_docker_image/hpc_root.key.pub +1 -0
  133. data/examples/tutorial/04_test/web_docker_image/main.go +43 -0
  134. data/examples/tutorial/04_test/web_docker_image/start.sh +7 -0
  135. data/examples/tutorial/04_test/web_docker_image/test.bash +6 -0
  136. data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/hosts.json +12 -0
  137. data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-gcc.bash +14 -0
  138. data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-python.bash +14 -0
  139. data/examples/tutorial/05_extend_with_plugins/dev_docker_image/Dockerfile +20 -0
  140. data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key +27 -0
  141. data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key.pub +1 -0
  142. data/examples/tutorial/05_extend_with_plugins/my-platforms/Gemfile +4 -0
  143. data/examples/tutorial/05_extend_with_plugins/my-platforms/hpc_config.rb +13 -0
  144. data/examples/tutorial/05_extend_with_plugins/my-platforms/images/debian_10/Dockerfile +13 -0
  145. data/examples/tutorial/05_extend_with_plugins/my-platforms/my_commands.bash +2 -0
  146. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/inventory.yaml +100 -0
  147. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/my-service.conf.erb +3 -0
  148. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_my-service.rb +58 -0
  149. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_web-hello.rb +43 -0
  150. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/platform_handler/json_bash.rb +115 -0
  151. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/report/web_report.rb +52 -0
  152. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/test/root_space.rb +44 -0
  153. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/my_hpc_plugins.gemspec +15 -0
  154. data/examples/tutorial/05_extend_with_plugins/node/my-service.conf +4 -0
  155. data/examples/tutorial/05_extend_with_plugins/web_docker_image/Dockerfile +33 -0
  156. data/examples/tutorial/05_extend_with_plugins/web_docker_image/hello_world.txt +1 -0
  157. data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key +27 -0
  158. data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key.pub +1 -0
  159. data/examples/tutorial/05_extend_with_plugins/web_docker_image/main.go +43 -0
  160. data/examples/tutorial/05_extend_with_plugins/web_docker_image/start.sh +7 -0
  161. data/examples/tutorial/05_extend_with_plugins/web_docker_image/test.bash +6 -0
  162. data/lib/hybrid_platforms_conductor/actions_executor.rb +1 -0
  163. data/lib/hybrid_platforms_conductor/deployer.rb +3 -2
  164. data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +29 -13
  165. data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +1 -1
  166. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +98 -0
  167. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +2 -2
  168. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +15 -4
  169. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +5 -5
  170. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/yaml_inventory.rb +140 -0
  171. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +6 -3
  172. data/lib/hybrid_platforms_conductor/hpc_plugins/report/templates/confluence_inventory.html.erb +1 -1
  173. data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -4
  174. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +1 -1
  175. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +19 -17
  176. data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +3 -0
  177. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +2 -1
  178. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +2 -1
  179. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +2 -1
  180. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +4 -3
  181. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +2 -1
  182. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
  183. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +8 -7
  184. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +1 -1
  185. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/confluence.html.erb +1 -1
  186. data/lib/hybrid_platforms_conductor/json_dumper.rb +1 -1
  187. data/lib/hybrid_platforms_conductor/platform_handler.rb +1 -1
  188. data/lib/hybrid_platforms_conductor/services_handler.rb +18 -16
  189. data/lib/hybrid_platforms_conductor/tests_runner.rb +0 -1
  190. data/lib/hybrid_platforms_conductor/topographer.rb +0 -1
  191. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  192. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +16 -0
  193. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/connectable_nodes_spec.rb +30 -0
  194. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +113 -0
  195. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +6 -2
  196. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +38 -1
  197. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +37 -4
  198. data/spec/hybrid_platforms_conductor_test/docs_spec.rb +10 -0
  199. data/tools/check_md +89 -0
  200. data/tools/generate_mermaid +75 -0
  201. metadata +337 -12
@@ -0,0 +1,44 @@
1
+ module MyHpcPlugins
2
+
3
+ module HpcPlugins
4
+
5
+ module Test
6
+
7
+ # Check root space
8
+ class RootSpace < HybridPlatformsConductor::Test
9
+
10
+ # Run test using SSH commands on the node.
11
+ # Instead of executing the SSH commands directly on each node for each test, this method returns the list of commands to run and the test framework then groups them in 1 SSH connection.
12
+ # [API] - @node can be used to adapt the command with the node.
13
+ #
14
+ # Result::
15
+ # * Hash<String,Object>: For each command to execute, information regarding the assertion.
16
+ # * Values can be:
17
+ # * Proc: The code block making the test given the stdout of the command. Here is the Proc description:
18
+ # * Parameters::
19
+ # * *stdout* (Array<String>): List of lines of the stdout of the command.
20
+ # * *stderr* (Array<String>): List of lines of the stderr of the command.
21
+ # * *return_code* (Integer): The return code of the command.
22
+ # * Hash<Symbol,Object>: More complete information, that can contain the following keys:
23
+ # * *validator* (Proc): The proc containing the assertions to perform (as described above). This key is mandatory.
24
+ # * *timeout* (Integer): Timeout to wait for this command to execute.
25
+ def test_on_node
26
+ # If this method is defined, it will be used to execute SSH commands on each node that is being tested.
27
+ # For each SSH command, a validator code block will be called with the stdout of the command run remotely on the node.
28
+ # In place of a simple validator code block, a more complex structure can be used to give more info (for example timeout).
29
+ {
30
+ 'du -sk /root' => proc do |stdout|
31
+ # stdout contains the output of our du command
32
+ used_kb = stdout.first.split.first.to_i
33
+ error "Root space used is #{used_kb}KB - too much!" if used_kb > 1024
34
+ end
35
+ }
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,15 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'my_hpc_plugins'
3
+ s.version = '0.0.1'
4
+ s.date = '2021-04-29'
5
+ s.authors = ['Me myself!']
6
+ s.email = ['me-myself@my-domain.com']
7
+ s.summary = 'My awesome plugins for Hybrid Platforms Conductor'
8
+ s.files = Dir['{bin,lib,spec}/**/*']
9
+ Dir['bin/**/*'].each do |exec_name|
10
+ s.executables << File.basename(exec_name)
11
+ end
12
+ # Dependencies
13
+ # Make sure we use a compatible version of hybrid_platforms_conductor
14
+ s.add_dependency 'hybrid_platforms_conductor', '~> 32.12'
15
+ end
@@ -0,0 +1,4 @@
1
+ service-port: 1107
2
+ service-timeout: 60
3
+ service-logs: stdout
4
+
@@ -0,0 +1,33 @@
1
+ # syntax=docker/dockerfile:1
2
+ # Pull the image containing Go
3
+ FROM golang:1.16.3-buster
4
+
5
+ # Install the web server
6
+ # Create the message file to be displayed by the web server
7
+ COPY hello_world.txt /root/hello_world.txt
8
+ # Copy the code
9
+ COPY main.go /codebase/src/main.go
10
+ # Build the binary
11
+ RUN cd /codebase && go build -v -o /codebase/bin/server ./src/main.go
12
+ # Set the env which will be available at runtime
13
+ ENV PORT=80
14
+ EXPOSE 80
15
+
16
+ # Install sshd
17
+ RUN apt-get update && apt-get install -y openssh-server
18
+ RUN mkdir /var/run/sshd
19
+ # Activate root login
20
+ RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
21
+ # Speed-up considerably ssh performance and avoid huge lags and timeouts without DNS
22
+ RUN sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
23
+ EXPOSE 22
24
+
25
+ # Upload our root key for key authentication of root
26
+ COPY hpc_root.key.pub /root/.ssh/authorized_keys
27
+ RUN chmod 700 /root/.ssh
28
+ RUN chmod 400 /root/.ssh/authorized_keys
29
+
30
+ # Startup script
31
+ COPY start.sh /start.sh
32
+ RUN chmod +x /start.sh
33
+ CMD ["/start.sh"]
@@ -0,0 +1,27 @@
1
+ -----BEGIN OPENSSH PRIVATE KEY-----
2
+ b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABFwAAAAdzc2gtcn
3
+ NhAAAAAwEAAQAAAQEAu5oVFddWtHFKA8+PnRssWieXrnMUPM8+qTdQrxoMaNacFWN+pBv3
4
+ Nj61GphCANoEPBvgcm7ltgZa1EumAZh4NJFi7AqM4Z2AFsqsvzRS1HNFRClEwr576iRkMc
5
+ ECIr0JmxeOscVcDMx0/9uFSfON7DiuStOOpIJIiQfjtFBsLFpzdfsVfZ3zc18Hxugqsbq0
6
+ t0bsTZdjRKnIYeKTSXKbF2n9b/dAf2tBtpywpun1WXQul7w1z20m9zv955k4kq3rAhSIPH
7
+ aOSE+QCXlICYqwmP2KVKCG6XEqSWjF4ujzcE7PlKIK1gsXdfum6GL23X8k8njBIjRzq6a0
8
+ Uabp65tvVQAAA8hgF2y/YBdsvwAAAAdzc2gtcnNhAAABAQC7mhUV11a0cUoDz4+dGyxaJ5
9
+ eucxQ8zz6pN1CvGgxo1pwVY36kG/c2PrUamEIA2gQ8G+BybuW2BlrUS6YBmHg0kWLsCozh
10
+ nYAWyqy/NFLUc0VEKUTCvnvqJGQxwQIivQmbF46xxVwMzHT/24VJ843sOK5K046kgkiJB+
11
+ O0UGwsWnN1+xV9nfNzXwfG6CqxurS3RuxNl2NEqchh4pNJcpsXaf1v90B/a0G2nLCm6fVZ
12
+ dC6XvDXPbSb3O/3nmTiSresCFIg8do5IT5AJeUgJirCY/YpUoIbpcSpJaMXi6PNwTs+Uog
13
+ rWCxd1+6boYvbdfyTyeMEiNHOrprRRpunrm29VAAAAAwEAAQAAAQEAj5IE7vkkvuUweqgf
14
+ RWGlWL2SJIyngT4tuzy8/7SUqKsNOoUxRxCr6ZSl7tt1L8eplALVi135aIuGeZAHVJNF8x
15
+ 0Mso4EcSmi/E5RU+cMONCawuY+XDeBB5igIT+PjdxT/KBTsRLUNmtGYwSyBf1hsNVT9ang
16
+ MWAPeOdTyQv/LRUe+O/ZKQ/h/X51BEwSXqz32RmlmZdMnDacIJ0NWdbcbAEtB4JT83S20d
17
+ bycQNOxGVmyevOGjyTXfUX6FhtYT7A7zzqNUL8UstSdajWeTZvVGd0C7Ob1kxaU3tnAwFr
18
+ 0sHTPHX7FQQFGhiU8gBZHOJ/PQzo+qqcCSsM3FcJlpVw5QAAAIAPYGXt7diWFYEhZVfj3n
19
+ KA0lX7LjQms0en4CoSkN4BELQJnaaqlTkrqN7PNL/WbmeavzDqQMk1jb9Q2+gra826THX5
20
+ GGtbFPFb9TSwBNi+zsyVURKEzqNYSw28ytKIdj98VW1qqQoolgTc5qoXG1JW5f5bEPbzUT
21
+ LXPP5j+YvuCgAAAIEA8NVJc5vXzJxbdgBxOPPHaPCAZ28V15Ggy+Bj1K/9G6FHqa/SFhy0
22
+ tCpBDNB/POX2UXCQDLteTIDodj9h2Yat6PJP9RKYCC9F5+/fU/0Y/tvD/p/uNhwEuqToex
23
+ gBUoL+r7/G3qYK13n8AKwrvb2wiYgP3aUVW7AyOier1MKt4OsAAACBAMdqmcj+5fNSTuOg
24
+ iPgGylUSIYnJ0w2jjZIaX96aat/w+SgciLhenbwpcf/9E8MDYKbXyhArdQvOgkEVogEI4s
25
+ PrFG66ogawPuRUUsuZBhm/b535EEvNAlkC8fMPVuKfOIsHJs8Cwcy7QPZSZu5pyKznpnCT
26
+ UlYGT6aB0GGoeeC/AAAAEWFkbWluQGV4YW1wbGUuY29tAQ==
27
+ -----END OPENSSH PRIVATE KEY-----
@@ -0,0 +1 @@
1
+ ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7mhUV11a0cUoDz4+dGyxaJ5eucxQ8zz6pN1CvGgxo1pwVY36kG/c2PrUamEIA2gQ8G+BybuW2BlrUS6YBmHg0kWLsCozhnYAWyqy/NFLUc0VEKUTCvnvqJGQxwQIivQmbF46xxVwMzHT/24VJ843sOK5K046kgkiJB+O0UGwsWnN1+xV9nfNzXwfG6CqxurS3RuxNl2NEqchh4pNJcpsXaf1v90B/a0G2nLCm6fVZdC6XvDXPbSb3O/3nmTiSresCFIg8do5IT5AJeUgJirCY/YpUoIbpcSpJaMXi6PNwTs+UogrWCxd1+6boYvbdfyTyeMEiNHOrprRRpunrm29V admin@example.com
@@ -0,0 +1,43 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "io/ioutil"
6
+ "log"
7
+ "net/http"
8
+ "os"
9
+ )
10
+
11
+ const homepageEndPoint = "/"
12
+
13
+ // StartWebServer the webserver
14
+ func StartWebServer() {
15
+ http.HandleFunc(homepageEndPoint, handleHomepage)
16
+ port := os.Getenv("PORT")
17
+ if len(port) == 0 {
18
+ panic("Environment variable PORT is not set")
19
+ }
20
+
21
+ log.Printf("Starting web server to listen on endpoints [%s] and port %s",
22
+ homepageEndPoint, port)
23
+ if err := http.ListenAndServe(":"+port, nil); err != nil {
24
+ panic(err)
25
+ }
26
+ }
27
+
28
+ func handleHomepage(w http.ResponseWriter, r *http.Request) {
29
+ urlPath := r.URL.Path
30
+ log.Printf("Web request received on url path %s", urlPath)
31
+ content, content_err := ioutil.ReadFile("/root/hello_world.txt")
32
+ if content_err != nil {
33
+ fmt.Printf("Failed to read message to display, err: %s", content_err)
34
+ }
35
+ _, write_err := w.Write(content)
36
+ if write_err != nil {
37
+ fmt.Printf("Failed to write response, err: %s", write_err)
38
+ }
39
+ }
40
+
41
+ func main() {
42
+ StartWebServer()
43
+ }
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+
3
+ # Start sshd as a daemon
4
+ /usr/sbin/sshd
5
+
6
+ # Start web server
7
+ sh -c /codebase/bin/server
@@ -0,0 +1,6 @@
1
+ #!/bin/bash
2
+
3
+ for ((i=1;i<=10;i++));
4
+ do
5
+ echo "Container web$i: $(curl http://web$i.hpc_tutorial.org 2>/dev/null)"
6
+ done
@@ -5,6 +5,7 @@ require 'securerandom'
5
5
  require 'tmpdir'
6
6
  require 'hybrid_platforms_conductor/action'
7
7
  require 'hybrid_platforms_conductor/cmd_runner'
8
+ require 'hybrid_platforms_conductor/config'
8
9
  require 'hybrid_platforms_conductor/connector'
9
10
  require 'hybrid_platforms_conductor/io_router'
10
11
  require 'hybrid_platforms_conductor/logger_helpers'
@@ -41,7 +41,7 @@ module HybridPlatformsConductor
41
41
 
42
42
  include LoggerHelpers
43
43
 
44
- Config.extend_config_dsl_with ConfigDSLExtension, :init_nodes_handler_config
44
+ Config.extend_config_dsl_with ConfigDSLExtension, :init_deployer_config
45
45
 
46
46
  # Do we use why-run mode while deploying? [default = false]
47
47
  # Boolean
@@ -336,7 +336,8 @@ module HybridPlatformsConductor
336
336
  actions_executor.connector(:ssh).passwords[node] = 'root_pwd'
337
337
  deployer.local_environment = true
338
338
  # Ignore secrets that might have been given: in Docker containers we always use dummy secrets
339
- deployer.secrets = [JSON.parse(File.read("#{@config.hybrid_platforms_dir}/dummy_secrets.json"))]
339
+ dummy_secrets_file = "#{@config.hybrid_platforms_dir}/dummy_secrets.json"
340
+ deployer.secrets = File.exist?(dummy_secrets_file) ? [JSON.parse(File.read(dummy_secrets_file))] : []
340
341
  yield deployer, instance
341
342
  end
342
343
  rescue
@@ -14,16 +14,33 @@ module HybridPlatformsConductor
14
14
  # [API] - @actions_executor is accessible
15
15
  #
16
16
  # Parameters::
17
- # * *remote_bash* (Array< Hash<Symbol, Object> or Array<String> or String>): List of bash actions to execute. Each action can have the following properties:
18
- # * *commands* (Array<String> or String): List of bash commands to execute (can be a single one). This is the default property also that allows to not use the Hash form for brevity.
19
- # * *file* (String): Name of file from which commands should be taken.
20
- # * *env* (Hash<String, String>): Environment variables to be set before executing those commands.
17
+ # * *remote_bash* (Array or Object): List of commands (or single command) to be executed. Each command can be the following:
18
+ # * String: Simple bash command.
19
+ # * Hash<Symbol, Object>: Information about the commands to execute. Can have the following properties:
20
+ # * *commands* (Array<String> or String): List of bash commands to execute (can be a single one) [default: ''].
21
+ # * *file* (String): Name of file from which commands should be taken [optional].
22
+ # * *env* (Hash<String, String>): Environment variables to be set before executing those commands [default: {}].
21
23
  def setup(remote_bash)
22
- @remote_bash = remote_bash
23
- # Normalize the parameters
24
- @remote_bash = [@remote_bash] if @remote_bash.is_a?(String)
25
- @remote_bash = { commands: @remote_bash } if @remote_bash.is_a?(Array)
26
- @remote_bash[:commands] = [@remote_bash[:commands]] if @remote_bash[:commands].is_a?(String)
24
+ # Normalize the parameters.
25
+ # Array< Hash<Symbol,Object> >: Simple array of info:
26
+ # * *commands* (Array<String>): List of bash commands to execute.
27
+ # * *env* (Hash<String, String>): Environment variables to be set before executing those commands.
28
+ @remote_bash = (remote_bash.is_a?(Array) ? remote_bash : [remote_bash]).map do |cmd_info|
29
+ if cmd_info.is_a?(String)
30
+ {
31
+ commands: [cmd_info],
32
+ env: {}
33
+ }
34
+ else
35
+ commands = []
36
+ commands.concat(cmd_info[:commands].is_a?(String) ? [cmd_info[:commands]] : cmd_info[:commands]) if cmd_info[:commands]
37
+ commands << File.read(cmd_info[:file]) if cmd_info[:file]
38
+ {
39
+ commands: commands,
40
+ env: cmd_info[:env] || {}
41
+ }
42
+ end
43
+ end
27
44
  end
28
45
 
29
46
  # Do we need a connector to execute this action on a node?
@@ -46,10 +63,9 @@ module HybridPlatformsConductor
46
63
  # [API] - @stderr_io can be used to log stderr messages
47
64
  # [API] - run_cmd(String) method can be used to execute a command. See CmdRunner#run_cmd to know about the result's signature.
48
65
  def execute
49
- bash_commands = (@remote_bash[:env] || {}).map { |var_name, var_value| "export #{var_name}='#{var_value}'" }
50
- bash_commands.concat(@remote_bash[:commands].clone) if @remote_bash.key?(:commands)
51
- bash_commands << File.read(@remote_bash[:file]) if @remote_bash.key?(:file)
52
- bash_str = bash_commands.join("\n")
66
+ bash_str = @remote_bash.map do |cmd_info|
67
+ (cmd_info[:env].map { |var_name, var_value| "export #{var_name}='#{var_value}'" } + cmd_info[:commands]).join("\n")
68
+ end.join("\n")
53
69
  log_debug "[#{@node}] - Execute remote Bash commands \"#{bash_str}\"..."
54
70
  @connector.remote_bash bash_str
55
71
  end
@@ -16,7 +16,7 @@ module HybridPlatformsConductor
16
16
  # Parameters::
17
17
  # * *mappings* (Hash<String or Symbol, Object>): Set of couples source => destination_dir to copy files or directories from the local file system to the remote file system.
18
18
  # The following properties can also be used:
19
- # * *sudo* (Boolean): Do we use sudo to make the copy? [default: false]
19
+ # * *sudo* (Boolean): Do we use sudo on the remote to make the copy? [default: false]
20
20
  # * *owner* (String or nil): Owner to use for files, or nil to use current one [default: nil]
21
21
  # * *group* (String or nil): Group to use for files, or nil to use current one [default: nil]
22
22
  def setup(mappings)
@@ -0,0 +1,98 @@
1
+ require 'fileutils'
2
+ require 'tmpdir'
3
+
4
+ module HybridPlatformsConductor
5
+
6
+ module HpcPlugins
7
+
8
+ module Connector
9
+
10
+ # Connector executing remote commands on the local environment in dedicated workspaces (/tmp/hpc_local_workspaces)
11
+ class Local < HybridPlatformsConductor::Connector
12
+
13
+ # Select nodes where this connector can connect.
14
+ # [API] - This method is mandatory
15
+ # [API] - @cmd_runner can be used
16
+ # [API] - @nodes_handler can be used
17
+ #
18
+ # Parameters::
19
+ # * *nodes* (Array<String>): List of candidate nodes
20
+ # Result::
21
+ # * Array<String>: List of nodes we can connect to from the candidates
22
+ def connectable_nodes_from(nodes)
23
+ @nodes_handler.prefetch_metadata_of nodes, :local_node
24
+ nodes.select { |node| @nodes_handler.get_local_node_of(node) }
25
+ end
26
+
27
+ # Run bash commands on a given node.
28
+ # [API] - This method is mandatory
29
+ # [API] - If defined, then with_connection_to has been called before this method.
30
+ # [API] - @cmd_runner can be used
31
+ # [API] - @nodes_handler can be used
32
+ # [API] - @node can be used to access the node on which we execute the remote bash
33
+ # [API] - @timeout can be used to know when the action should fail
34
+ # [API] - @stdout_io can be used to send stdout output
35
+ # [API] - @stderr_io can be used to send stderr output
36
+ #
37
+ # Parameters::
38
+ # * *bash_cmds* (String): Bash commands to execute
39
+ def remote_bash(bash_cmds)
40
+ run_cmd "cd #{workspace_for(@node)} ; #{bash_cmds}"
41
+ end
42
+
43
+ # Execute an interactive shell on the remote node
44
+ # [API] - This method is mandatory
45
+ # [API] - If defined, then with_connection_to has been called before this method.
46
+ # [API] - @cmd_runner can be used
47
+ # [API] - @nodes_handler can be used
48
+ # [API] - @node can be used to access the node on which we execute the remote bash
49
+ # [API] - @timeout can be used to know when the action should fail
50
+ # [API] - @stdout_io can be used to send stdout output
51
+ # [API] - @stderr_io can be used to send stderr output
52
+ def remote_interactive
53
+ system "cd #{workspace_for(@node)} ; /bin/bash"
54
+ end
55
+
56
+ # Copy a file to the remote node in a directory
57
+ # [API] - This method is mandatory
58
+ # [API] - If defined, then with_connection_to has been called before this method.
59
+ # [API] - @cmd_runner can be used
60
+ # [API] - @nodes_handler can be used
61
+ # [API] - @node can be used to access the node on which we execute the remote bash
62
+ # [API] - @timeout can be used to know when the action should fail
63
+ # [API] - @stdout_io can be used to send stdout output
64
+ # [API] - @stderr_io can be used to send stderr output
65
+ #
66
+ # Parameters::
67
+ # * *from* (String): Local file to copy
68
+ # * *to* (String): Remote directory to copy to
69
+ # * *sudo* (Boolean): Do we use sudo to copy? [default: false]
70
+ # * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
71
+ # * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
72
+ def remote_copy(from, to, sudo: false, owner: nil, group: nil)
73
+ # If the destination is a relative path, prepend the workspace dir to it.
74
+ to = "#{workspace_for(@node)}/#{to}" unless to.start_with?('/')
75
+ FileUtils.cp_r from, to
76
+ end
77
+
78
+ private
79
+
80
+ # Create or reuse a dedicated workspace for a node
81
+ #
82
+ # Parameters::
83
+ # * *node* (String): Node for which we want a dedicated workspace
84
+ # Result::
85
+ # * String: Dedicated workspace path
86
+ def workspace_for(node)
87
+ workspace = "#{Dir.tmpdir}/hpc_local_workspaces/#{node}"
88
+ FileUtils.mkdir_p workspace
89
+ workspace
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -73,7 +73,7 @@ module HybridPlatformsConductor
73
73
  # Result::
74
74
  # * Array<String>: List of nodes we can connect to from the candidates
75
75
  def connectable_nodes_from(nodes)
76
- nodes.select { |node| @nodes_handler.get_ip_of(node) =~ /^192\.168\..+$/ }
76
+ nodes.select { |node| @nodes_handler.get_host_ip_of(node) =~ /^192\.168\..+$/ }
77
77
  end
78
78
 
79
79
  # Prepare connections to a given set of nodes.
@@ -135,7 +135,7 @@ module HybridPlatformsConductor
135
135
  # Parameters::
136
136
  # * *from* (String): Local file to copy
137
137
  # * *to* (String): Remote directory to copy to
138
- # * *sudo* (Boolean): Do we use sudo to copy? [default: false]
138
+ # * *sudo* (Boolean): Do we use sudo on the remote to copy? [default: false]
139
139
  # * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
140
140
  # * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
141
141
  def remote_copy(from, to, sudo: false, owner: nil, group: nil)
@@ -131,6 +131,10 @@ module HybridPlatformsConductor
131
131
  # Default values
132
132
  @ssh_user = ENV['hpc_ssh_user']
133
133
  @ssh_user = ENV['USER'] if @ssh_user.nil? || @ssh_user.empty?
134
+ if @ssh_user.nil? || @ssh_user.empty?
135
+ _exit_status, stdout = @cmd_runner.run_cmd 'whoami', log_to_stdout: log_debug?
136
+ @ssh_user = stdout.strip
137
+ end
134
138
  @ssh_use_control_master = true
135
139
  @ssh_strict_host_key_checking = true
136
140
  @passwords = {}
@@ -236,9 +240,9 @@ module HybridPlatformsConductor
236
240
  ssh_cmd =
237
241
  if @nodes_handler.get_ssh_session_exec_of(@node) == 'false'
238
242
  # When ExecSession is disabled we need to use stdin directly
239
- "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'EOF'\n#{bash_cmds}\nEOF"
243
+ "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
240
244
  else
241
- "#{ssh_exec} #{ssh_url} /bin/bash <<'EOF'\n#{bash_cmds}\nEOF"
245
+ "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
242
246
  end
243
247
  # Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
244
248
  # Therefore we need to make sure that if bash_cmds exceeds MAX_CMD_ARG_LENGTH bytes (considering EOF chars) then we use an intermediary shell script to store the commands.
@@ -292,13 +296,20 @@ module HybridPlatformsConductor
292
296
  # Parameters::
293
297
  # * *from* (String): Local file to copy
294
298
  # * *to* (String): Remote directory to copy to
295
- # * *sudo* (Boolean): Do we use sudo to copy? [default: false]
299
+ # * *sudo* (Boolean): Do we use sudo on the remote to copy? [default: false]
296
300
  # * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
297
301
  # * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
298
302
  def remote_copy(from, to, sudo: false, owner: nil, group: nil)
299
303
  if @nodes_handler.get_ssh_session_exec_of(@node) == 'false'
300
304
  # We don't have ExecSession, so don't use ssh, but scp instead.
301
- run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:#{to}"
305
+ if sudo
306
+ # We need to first copy the file in an accessible directory, and then sudo mv
307
+ remote_bash('mkdir -p hpc_tmp_scp')
308
+ run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:./hpc_tmp_scp"
309
+ remote_bash("#{@nodes_handler.sudo_on(@node)} mv ./hpc_tmp_scp/#{File.basename(from)} #{to}")
310
+ else
311
+ run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:#{to}"
312
+ end
302
313
  else
303
314
  run_cmd <<~EOS
304
315
  cd #{File.dirname(from)} && \