hybrid_platforms_conductor 32.11.2 → 32.13.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1121 -0
- data/LICENSE.md +31 -0
- data/README.md +402 -0
- data/bin/setup +1 -1
- data/docs/api.md +349 -0
- data/docs/config_dsl.md +315 -0
- data/docs/executables.md +226 -0
- data/docs/executables/check-node.md +155 -0
- data/docs/executables/deploy.md +198 -0
- data/docs/executables/dump_nodes_json.md +110 -0
- data/docs/executables/free_ips.md +93 -0
- data/docs/executables/free_veids.md +73 -0
- data/docs/executables/get_impacted_nodes.md +94 -0
- data/docs/executables/last_deploys.md +114 -0
- data/docs/executables/nodes_to_deploy.md +139 -0
- data/docs/executables/report.md +159 -0
- data/docs/executables/run.md +126 -0
- data/docs/executables/setup.md +92 -0
- data/docs/executables/ssh_config.md +151 -0
- data/docs/executables/test.md +213 -0
- data/docs/executables/topograph.md +139 -0
- data/docs/gen/mermaid/README.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/free_veids.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/setup.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
- data/docs/install.md +161 -0
- data/docs/plugins.md +215 -0
- data/docs/plugins/action/bash.md +37 -0
- data/docs/plugins/action/interactive.md +37 -0
- data/docs/plugins/action/remote_bash.md +67 -0
- data/docs/plugins/action/ruby.md +69 -0
- data/docs/plugins/action/scp.md +61 -0
- data/docs/plugins/cmdb/config.md +46 -0
- data/docs/plugins/cmdb/host_ip.md +33 -0
- data/docs/plugins/cmdb/host_keys.md +33 -0
- data/docs/plugins/cmdb/platform_handlers.md +33 -0
- data/docs/plugins/connector/local.md +28 -0
- data/docs/plugins/connector/ssh.md +95 -0
- data/docs/plugins/platform_handler/yaml_inventory.md +105 -0
- data/docs/plugins/provisioner/docker.md +27 -0
- data/docs/plugins/provisioner/podman.md +27 -0
- data/docs/plugins/provisioner/proxmox.md +115 -0
- data/docs/plugins/report/confluence.md +49 -0
- data/docs/plugins/report/mediawiki.md +28 -0
- data/docs/plugins/report/stdout.md +32 -0
- data/docs/plugins/test/bitbucket_conf.md +97 -0
- data/docs/plugins/test/can_be_checked.md +27 -0
- data/docs/plugins/test/check_deploy_and_idempotence.md +61 -0
- data/docs/plugins/test/check_from_scratch.md +28 -0
- data/docs/plugins/test/connection.md +27 -0
- data/docs/plugins/test/deploy_freshness.md +27 -0
- data/docs/plugins/test/deploy_from_scratch.md +28 -0
- data/docs/plugins/test/deploy_removes_root_access.md +29 -0
- data/docs/plugins/test/divergence.md +41 -0
- data/docs/plugins/test/executables.md +26 -0
- data/docs/plugins/test/file_system.md +49 -0
- data/docs/plugins/test/file_system_hdfs.md +65 -0
- data/docs/plugins/test/hostname.md +27 -0
- data/docs/plugins/test/idempotence.md +56 -0
- data/docs/plugins/test/ip.md +28 -0
- data/docs/plugins/test/jenkins_ci_conf.md +54 -0
- data/docs/plugins/test/jenkins_ci_masters_ok.md +54 -0
- data/docs/plugins/test/linear_strategy.md +26 -0
- data/docs/plugins/test/local_users.md +48 -0
- data/docs/plugins/test/mounts.md +55 -0
- data/docs/plugins/test/orphan_files.md +38 -0
- data/docs/plugins/test/ports.md +50 -0
- data/docs/plugins/test/private_ips.md +27 -0
- data/docs/plugins/test/public_ips.md +27 -0
- data/docs/plugins/test/spectre.md +26 -0
- data/docs/plugins/test/veids.md +27 -0
- data/docs/plugins/test/vulnerabilities.md +65 -0
- data/docs/plugins/test_report/confluence.md +43 -0
- data/docs/plugins/test_report/stdout.md +26 -0
- data/docs/plugins_create.md +135 -0
- data/docs/tutorial.md +61 -0
- data/docs/tutorial/01_installation.md +131 -0
- data/docs/tutorial/02_first_node.md +468 -0
- data/docs/tutorial/03_scale.md +878 -0
- data/docs/tutorial/04_test.md +977 -0
- data/docs/tutorial/05_extend_with_plugins.md +1132 -0
- data/examples/bare/Gemfile +4 -0
- data/examples/bare/hpc_config.rb +2 -0
- data/examples/localhost/Gemfile +4 -0
- data/examples/localhost/hpc_config.rb +2 -0
- data/examples/localhost/inventory.yaml +4 -0
- data/examples/tutorial/01_installation/my-platforms/Gemfile +3 -0
- data/examples/tutorial/01_installation/my-platforms/hpc_config.rb +0 -0
- data/examples/tutorial/02_first_node/my-platforms/Gemfile +3 -0
- data/examples/tutorial/02_first_node/my-platforms/hpc_config.rb +1 -0
- data/examples/tutorial/02_first_node/my-service-conf-repo/inventory.yaml +13 -0
- data/examples/tutorial/02_first_node/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/02_first_node/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/02_first_node/node/my-service.conf +4 -0
- data/examples/tutorial/03_scale/my-platforms/Gemfile +3 -0
- data/examples/tutorial/03_scale/my-platforms/hpc_config.rb +1 -0
- data/examples/tutorial/03_scale/my-platforms/my_commands.bash +2 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/inventory.yaml +90 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/service_web-hello.rb +43 -0
- data/examples/tutorial/03_scale/node/my-service.conf +4 -0
- data/examples/tutorial/03_scale/web_docker_image/Dockerfile +33 -0
- data/examples/tutorial/03_scale/web_docker_image/hello_world.txt +1 -0
- data/examples/tutorial/03_scale/web_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/03_scale/web_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/03_scale/web_docker_image/main.go +43 -0
- data/examples/tutorial/03_scale/web_docker_image/start.sh +7 -0
- data/examples/tutorial/03_scale/web_docker_image/test.bash +6 -0
- data/examples/tutorial/04_test/my-platforms/Gemfile +3 -0
- data/examples/tutorial/04_test/my-platforms/hpc_config.rb +12 -0
- data/examples/tutorial/04_test/my-platforms/images/debian_10/Dockerfile +13 -0
- data/examples/tutorial/04_test/my-platforms/my_commands.bash +2 -0
- data/examples/tutorial/04_test/my-service-conf-repo/inventory.yaml +100 -0
- data/examples/tutorial/04_test/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/04_test/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/04_test/my-service-conf-repo/service_web-hello.rb +43 -0
- data/examples/tutorial/04_test/node/my-service.conf +4 -0
- data/examples/tutorial/04_test/web_docker_image/Dockerfile +33 -0
- data/examples/tutorial/04_test/web_docker_image/hello_world.txt +1 -0
- data/examples/tutorial/04_test/web_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/04_test/web_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/04_test/web_docker_image/main.go +43 -0
- data/examples/tutorial/04_test/web_docker_image/start.sh +7 -0
- data/examples/tutorial/04_test/web_docker_image/test.bash +6 -0
- data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/hosts.json +12 -0
- data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-gcc.bash +14 -0
- data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-python.bash +14 -0
- data/examples/tutorial/05_extend_with_plugins/dev_docker_image/Dockerfile +20 -0
- data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/Gemfile +4 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/hpc_config.rb +13 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/images/debian_10/Dockerfile +13 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/my_commands.bash +2 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/inventory.yaml +100 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_web-hello.rb +43 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/platform_handler/json_bash.rb +115 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/report/web_report.rb +52 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/test/root_space.rb +44 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/my_hpc_plugins.gemspec +15 -0
- data/examples/tutorial/05_extend_with_plugins/node/my-service.conf +4 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/Dockerfile +33 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/hello_world.txt +1 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/main.go +43 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/start.sh +7 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/test.bash +6 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +1 -0
- data/lib/hybrid_platforms_conductor/deployer.rb +3 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +29 -13
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +98 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +15 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +5 -5
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/yaml_inventory.rb +140 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +6 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +19 -17
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +3 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +4 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +8 -7
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +1 -1
- data/lib/hybrid_platforms_conductor/json_dumper.rb +1 -1
- data/lib/hybrid_platforms_conductor/platform_handler.rb +1 -1
- data/lib/hybrid_platforms_conductor/services_handler.rb +18 -16
- data/lib/hybrid_platforms_conductor/tests_runner.rb +0 -1
- data/lib/hybrid_platforms_conductor/topographer.rb +0 -1
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +16 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/connectable_nodes_spec.rb +30 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +113 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +6 -2
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +38 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +37 -4
- data/spec/hybrid_platforms_conductor_test/docs_spec.rb +10 -0
- data/tools/check_md +89 -0
- data/tools/generate_mermaid +75 -0
- metadata +337 -12
@@ -56,7 +56,7 @@ module HybridPlatformsConductor
|
|
56
56
|
nodes = @nodes_handler.select_nodes(nodes_selectors)
|
57
57
|
unless @skip_run
|
58
58
|
nodes.map { |node| @nodes_handler.platform_for(node) }.uniq.each.each do |platform_handler|
|
59
|
-
platform_handler.prepare_why_run_deploy_for_json_dump
|
59
|
+
platform_handler.prepare_why_run_deploy_for_json_dump if platform_handler.respond_to?(:prepare_why_run_deploy_for_json_dump)
|
60
60
|
end
|
61
61
|
@deployer.concurrent_execution = true
|
62
62
|
@deployer.use_why_run = true
|
@@ -142,7 +142,7 @@ module HybridPlatformsConductor
|
|
142
142
|
git_status = git.status
|
143
143
|
git_commit = git.log.first
|
144
144
|
{
|
145
|
-
repo_name: File.basename(git.remotes.first.url).gsub(/\.git$/, ''),
|
145
|
+
repo_name: git.remotes.empty? ? File.basename(@repository_path) : File.basename(git.remotes.first.url).gsub(/\.git$/, ''),
|
146
146
|
commit: {
|
147
147
|
id: git_commit.sha,
|
148
148
|
ref: git_commit.name,
|
@@ -108,23 +108,25 @@ module HybridPlatformsConductor
|
|
108
108
|
local_environment:
|
109
109
|
)
|
110
110
|
platforms_for(services).each do |platform, platform_services|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
}
|
119
|
-
if ServicesHandler.packaged_deployments.include?(package_id)
|
120
|
-
log_debug "Platform #{platform_name} has already been packaged for this deployment (package ID #{package_id}). Won't package it another time."
|
121
|
-
else
|
122
|
-
platform.package(
|
123
|
-
services: platform_services,
|
124
|
-
secrets: secrets,
|
111
|
+
if platform.respond_to?(:package)
|
112
|
+
platform_name = platform.name
|
113
|
+
# Compute the package ID that is unique to this packaging, so that we don't mix it with others if needed.
|
114
|
+
package_id = {
|
115
|
+
platform_name: platform_name,
|
116
|
+
services: Hash[platform_services.map { |node, node_services| [node, node_services.sort] }].sort,
|
117
|
+
secrets: secrets.sort,
|
125
118
|
local_environment: local_environment
|
126
|
-
|
127
|
-
ServicesHandler.packaged_deployments
|
119
|
+
}
|
120
|
+
if ServicesHandler.packaged_deployments.include?(package_id)
|
121
|
+
log_debug "Platform #{platform_name} has already been packaged for this deployment (package ID #{package_id}). Won't package it another time."
|
122
|
+
else
|
123
|
+
platform.package(
|
124
|
+
services: platform_services,
|
125
|
+
secrets: secrets,
|
126
|
+
local_environment: local_environment
|
127
|
+
)
|
128
|
+
ServicesHandler.packaged_deployments << package_id
|
129
|
+
end
|
128
130
|
end
|
129
131
|
end
|
130
132
|
end
|
@@ -452,7 +452,6 @@ module HybridPlatformsConductor
|
|
452
452
|
end]
|
453
453
|
section "Run test commands on #{@test_cmds.keys.size} connected nodes (timeout to #{timeout} secs)" do
|
454
454
|
start_time = Time.now
|
455
|
-
nbr_secs = nil
|
456
455
|
@actions_executor.max_threads = @max_threads_connection_on_nodes
|
457
456
|
@actions_result = @actions_executor.execute_actions(
|
458
457
|
@test_cmds,
|
@@ -110,7 +110,6 @@ module HybridPlatformsConductor
|
|
110
110
|
@skip_run = false
|
111
111
|
|
112
112
|
# Parse plugins
|
113
|
-
root_path = File.expand_path("#{File.dirname(__FILE__)}/..")
|
114
113
|
@plugins = Hash[Dir.
|
115
114
|
glob("#{File.dirname(__FILE__)}/topographer/plugins/*.rb").
|
116
115
|
map do |file_name|
|
@@ -79,6 +79,22 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
it 'executes remote Bash code both from commands and a file in sequence' do
|
83
|
+
with_test_platform_for_action_plugins do |repository|
|
84
|
+
File.write("#{repository}/commands.txt", "bash_cmd3.bash\nbash_cmd4.bash")
|
85
|
+
test_actions_executor.execute_actions('node' => { remote_bash: [
|
86
|
+
'bash_cmd1.bash',
|
87
|
+
'bash_cmd2.bash',
|
88
|
+
{ file: "#{repository}/commands.txt" }
|
89
|
+
] })
|
90
|
+
expect(test_actions_executor.connector(:test_connector).calls).to eq [
|
91
|
+
[:connectable_nodes_from, ['node']],
|
92
|
+
[:with_connection_to, ['node'], { no_exception: true }],
|
93
|
+
[:remote_bash, "bash_cmd1.bash\nbash_cmd2.bash\nbash_cmd3.bash\nbash_cmd4.bash"]
|
94
|
+
]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
82
98
|
it 'executes remote Bash code with environment variables set' do
|
83
99
|
with_test_platform_for_action_plugins do
|
84
100
|
test_actions_executor.execute_actions('node' => { remote_bash: {
|
@@ -0,0 +1,30 @@
|
|
1
|
+
describe HybridPlatformsConductor::ActionsExecutor do
|
2
|
+
|
3
|
+
context 'checking connector plugin local' do
|
4
|
+
|
5
|
+
context 'checking connectable nodes selection' do
|
6
|
+
|
7
|
+
# Return the connector to be tested
|
8
|
+
#
|
9
|
+
# Result::
|
10
|
+
# * Connector: Connector to be tested
|
11
|
+
def test_connector
|
12
|
+
test_actions_executor.connector(:local)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'selects connectable nodes correctly' do
|
16
|
+
with_test_platform(nodes: {
|
17
|
+
'node1' => { meta: { host_ip: '192.168.42.42' } },
|
18
|
+
'node2' => {},
|
19
|
+
'node3' => { meta: { host_ip: '127.0.0.1', local_node: true } },
|
20
|
+
'node4' => { meta: { local_node: true } }
|
21
|
+
}) do
|
22
|
+
expect(test_connector.connectable_nodes_from(%w[node1 node2 node3 node4]).sort).to eq %w[node3 node4].sort
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
describe HybridPlatformsConductor::ActionsExecutor do
|
2
|
+
|
3
|
+
context 'checking connector plugin local' do
|
4
|
+
|
5
|
+
context 'checking remote actions' do
|
6
|
+
|
7
|
+
# Return the connector to be tested
|
8
|
+
#
|
9
|
+
# Result::
|
10
|
+
# * Connector: Connector to be tested
|
11
|
+
def test_connector
|
12
|
+
test_actions_executor.connector(:local)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Get a test platform and the connector prepared the same way Actions Executor does before calling remote_* methods
|
16
|
+
#
|
17
|
+
# Parameters::
|
18
|
+
# * *expected_cmds* (Array< [String or Regexp, Proc] >): The expected commands that should be used, and their corresponding mocked code [default: []]
|
19
|
+
# * *expected_stdout* (String): Expected stdout after client code execution [default: '']
|
20
|
+
# * *expected_stderr* (String): Expected stderr after client code execution [default: '']
|
21
|
+
# * *timeout* (Integer or nil): Timeout to prepare the connector for [default: nil]
|
22
|
+
# * *password* (String or nil): Password to set for the node, or nil for none [default: nil]
|
23
|
+
# * *additional_config* (String): Additional config [default: '']
|
24
|
+
# * Proc: Client code to execute testing
|
25
|
+
def with_test_platform_for_remote_testing(
|
26
|
+
expected_cmds: [],
|
27
|
+
expected_stdout: '',
|
28
|
+
expected_stderr: '',
|
29
|
+
timeout: nil,
|
30
|
+
password: nil,
|
31
|
+
additional_config: ''
|
32
|
+
)
|
33
|
+
with_test_platform(
|
34
|
+
{ nodes: { 'node' => { meta: { local_node: true } } } },
|
35
|
+
false,
|
36
|
+
additional_config
|
37
|
+
) do
|
38
|
+
with_cmd_runner_mocked(expected_cmds) do
|
39
|
+
test_connector.with_connection_to(['node']) do
|
40
|
+
stdout = ''
|
41
|
+
stderr = ''
|
42
|
+
test_connector.prepare_for('node', timeout, stdout, stderr)
|
43
|
+
yield
|
44
|
+
expect(stdout).to eq expected_stdout
|
45
|
+
expect(stderr).to eq expected_stderr
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'executes bash commands remotely' do
|
52
|
+
with_test_platform_for_remote_testing(
|
53
|
+
expected_cmds: [['cd /tmp/hpc_local_workspaces/node ; bash_cmd.bash', proc { [0, 'Bash commands executed on node', ''] }]],
|
54
|
+
expected_stdout: 'Bash commands executed on node'
|
55
|
+
) do
|
56
|
+
test_connector.remote_bash('bash_cmd.bash')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'executes bash commands remotely with timeout' do
|
61
|
+
with_test_platform_for_remote_testing(
|
62
|
+
expected_cmds: [
|
63
|
+
[
|
64
|
+
'cd /tmp/hpc_local_workspaces/node ; bash_cmd.bash',
|
65
|
+
proc do |cmd, log_to_file: nil, log_to_stdout: true, log_stdout_to_io: nil, log_stderr_to_io: nil, expected_code: 0, timeout: nil, no_exception: false|
|
66
|
+
expect(timeout).to eq 5
|
67
|
+
[0, '', '']
|
68
|
+
end
|
69
|
+
]
|
70
|
+
],
|
71
|
+
timeout: 5
|
72
|
+
) do
|
73
|
+
test_connector.remote_bash('bash_cmd.bash')
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'executes interactive commands remotely' do
|
78
|
+
with_test_platform_for_remote_testing do
|
79
|
+
expect(test_connector).to receive(:system) do |cmd|
|
80
|
+
expect(cmd).to eq 'cd /tmp/hpc_local_workspaces/node ; /bin/bash'
|
81
|
+
end
|
82
|
+
test_connector.remote_interactive
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'copies files remotely' do
|
87
|
+
with_test_platform_for_remote_testing do
|
88
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/remote_path/to/dst.dir')
|
89
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir')
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'copies files remotely with timeout' do
|
94
|
+
with_test_platform_for_remote_testing(
|
95
|
+
timeout: 5
|
96
|
+
) do
|
97
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/remote_path/to/dst.dir')
|
98
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'copies relative files remotely' do
|
103
|
+
with_test_platform_for_remote_testing do
|
104
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/tmp/hpc_local_workspaces/node/to/dst.dir')
|
105
|
+
test_connector.remote_copy('/path/to/src.file', 'to/dst.dir')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb
CHANGED
@@ -97,11 +97,15 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
-
it 'fails if no user name has been given, either through environment
|
100
|
+
it 'fails if no user name has been given, either through environment, command-line or using whoami' do
|
101
101
|
ENV.delete 'hpc_ssh_user'
|
102
102
|
ENV.delete 'USER'
|
103
103
|
with_test_platform_for_cli do
|
104
|
-
|
104
|
+
with_cmd_runner_mocked([
|
105
|
+
['whoami', proc { [0, '', ''] }]
|
106
|
+
]) do
|
107
|
+
expect { run 'run', '--node', 'node', '--command', 'echo Hello' }.to raise_error(RuntimeError, 'No SSH user name specified. Please use --ssh-user option or hpc_ssh_user environment variable to set it.')
|
108
|
+
end
|
105
109
|
end
|
106
110
|
end
|
107
111
|
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb
CHANGED
@@ -47,7 +47,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
47
47
|
end.join("\n") + "\n"
|
48
48
|
end
|
49
49
|
|
50
|
-
it 'generates a global configuration with user from environment' do
|
50
|
+
it 'generates a global configuration with user from hpc_ssh_user environment variable' do
|
51
51
|
with_test_platform do
|
52
52
|
ENV['hpc_ssh_user'] = 'test_user'
|
53
53
|
expect(ssh_config_for(nil)).to eq <<~EOS
|
@@ -59,6 +59,43 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
it 'generates a global configuration with user from USER environment variable' do
|
63
|
+
with_test_platform do
|
64
|
+
ENV['USER'] = 'test_user'
|
65
|
+
expect(ssh_config_for(nil)).to eq <<~EOS
|
66
|
+
Host *
|
67
|
+
User test_user
|
68
|
+
ControlPath #{Dir.tmpdir}/hpc_ssh/hpc_ssh_mux_%h_%p_%r
|
69
|
+
PubkeyAcceptedKeyTypes +ssh-dss
|
70
|
+
EOS
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'generates a global configuration with user taken from whoami when no env variable is set' do
|
75
|
+
with_test_platform do
|
76
|
+
original_user = ENV['USER']
|
77
|
+
begin
|
78
|
+
ENV.delete 'USER'
|
79
|
+
ENV.delete 'hpc_ssh_user'
|
80
|
+
with_cmd_runner_mocked(
|
81
|
+
[
|
82
|
+
['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }],
|
83
|
+
['whoami', proc { [0, 'test_whoami_user', ''] }]
|
84
|
+
]
|
85
|
+
) do
|
86
|
+
expect(ssh_config_for(nil)).to eq <<~EOS
|
87
|
+
Host *
|
88
|
+
User test_whoami_user
|
89
|
+
ControlPath #{Dir.tmpdir}/hpc_ssh/hpc_ssh_mux_%h_%p_%r
|
90
|
+
PubkeyAcceptedKeyTypes +ssh-dss
|
91
|
+
EOS
|
92
|
+
end
|
93
|
+
ensure
|
94
|
+
ENV['USER'] = original_user
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
62
99
|
it 'generates a global configuration with user from setting' do
|
63
100
|
with_test_platform do
|
64
101
|
test_connector.ssh_user = 'test_user'
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
6
6
|
|
7
7
|
it 'executes bash commands remotely' do
|
8
8
|
with_test_platform_for_remote_testing(
|
9
|
-
expected_cmds: [[/.+\/ssh hpc\.node \/bin\/bash <<'
|
9
|
+
expected_cmds: [[/.+\/ssh hpc\.node \/bin\/bash <<'HPC_EOF'\nbash_cmd.bash\nHPC_EOF/, proc { [0, 'Bash commands executed on node', ''] }]],
|
10
10
|
expected_stdout: 'Bash commands executed on node'
|
11
11
|
) do
|
12
12
|
test_connector.remote_bash('bash_cmd.bash')
|
@@ -17,7 +17,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
17
17
|
with_test_platform_for_remote_testing(
|
18
18
|
expected_cmds: [
|
19
19
|
[
|
20
|
-
/.+\/ssh hpc\.node \/bin\/bash <<'
|
20
|
+
/.+\/ssh hpc\.node \/bin\/bash <<'HPC_EOF'\nbash_cmd.bash\nHPC_EOF/,
|
21
21
|
proc do |cmd, log_to_file: nil, log_to_stdout: true, log_stdout_to_io: nil, log_stderr_to_io: nil, expected_code: 0, timeout: nil, no_exception: false|
|
22
22
|
expect(timeout).to eq 5
|
23
23
|
[0, '', '']
|
@@ -76,7 +76,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
76
76
|
[
|
77
77
|
/.+\/hpc_temp_cmds_.+\.sh$/,
|
78
78
|
proc do |received_cmd|
|
79
|
-
expect(File.read(received_cmd)).to match /.+\/ssh hpc\.node \/bin\/bash <<'
|
79
|
+
expect(File.read(received_cmd)).to match /.+\/ssh hpc\.node \/bin\/bash <<'HPC_EOF'\n#{Regexp.escape(cmd)}\nHPC_EOF/
|
80
80
|
[0, 'Bash commands executed on node', '']
|
81
81
|
end
|
82
82
|
]
|
@@ -143,7 +143,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
143
143
|
|
144
144
|
it 'executes bash commands remotely without Session Exec capabilities' do
|
145
145
|
with_test_platform_for_remote_testing(
|
146
|
-
expected_cmds: [[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'
|
146
|
+
expected_cmds: [[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'HPC_EOF'\nbash_cmd.bash\nHPC_EOF$/, proc { [0, 'Bash commands executed on node', ''] }]],
|
147
147
|
expected_stdout: 'Bash commands executed on node',
|
148
148
|
session_exec: false
|
149
149
|
) do
|
@@ -165,6 +165,39 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
+
it 'copies files remotely without Session Exec capabilities and with sudo' do
|
169
|
+
with_test_platform_for_remote_testing(
|
170
|
+
expected_cmds: [
|
171
|
+
[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'HPC_EOF'\nmkdir -p hpc_tmp_scp\nHPC_EOF$/, proc { [0, '', ''] }],
|
172
|
+
[
|
173
|
+
/^scp -S .+\/ssh \/path\/to\/src.file hpc\.node:\.\/hpc_tmp_scp$/,
|
174
|
+
proc { [0, '', ''] }
|
175
|
+
],
|
176
|
+
[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'HPC_EOF'\nsudo -u root mv \.\/hpc_tmp_scp\/src\.file \/remote_path\/to\/dst\.dir\nHPC_EOF$/, proc { [0, '', ''] }]
|
177
|
+
],
|
178
|
+
session_exec: false
|
179
|
+
) do
|
180
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'copies files remotely without Session Exec capabilities and with a different sudo' do
|
185
|
+
with_test_platform_for_remote_testing(
|
186
|
+
expected_cmds: [
|
187
|
+
[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'HPC_EOF'\nmkdir -p hpc_tmp_scp\nHPC_EOF$/, proc { [0, '', ''] }],
|
188
|
+
[
|
189
|
+
/^scp -S .+\/ssh \/path\/to\/src.file hpc\.node:\.\/hpc_tmp_scp$/,
|
190
|
+
proc { [0, '', ''] }
|
191
|
+
],
|
192
|
+
[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'HPC_EOF'\nother_sudo --user root mv \.\/hpc_tmp_scp\/src\.file \/remote_path\/to\/dst\.dir\nHPC_EOF$/, proc { [0, '', ''] }]
|
193
|
+
],
|
194
|
+
additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }',
|
195
|
+
session_exec: false
|
196
|
+
) do
|
197
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
168
201
|
end
|
169
202
|
|
170
203
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
describe 'Documentation' do
|
2
|
+
|
3
|
+
it 'makes sure all Markdown links are valid' do
|
4
|
+
check_stdout = `bundle exec tools/check_md README.md #{Dir.glob('docs/**/*.md').join(' ')}`.split("\n")
|
5
|
+
summary_idx = check_stdout.index { |line| line =~ /^\d+ errors:$/ }
|
6
|
+
expect(summary_idx).not_to eq(nil), "Could not parse check output: #{check_stdout.join("\n")}"
|
7
|
+
expect(check_stdout[summary_idx]).to eq('0 errors:'), "Invalid links found: #{check_stdout[summary_idx..-1].join("\n")}"
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
data/tools/check_md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Parsed information, per file name.
|
4
|
+
# Information is:
|
5
|
+
# * *anchors* (Array<String>): List of anchors
|
6
|
+
# * *links* (Array<String>): List of links
|
7
|
+
@info = {}
|
8
|
+
|
9
|
+
# Get a file name from a link
|
10
|
+
#
|
11
|
+
# Parameters::
|
12
|
+
# * *link* (String): The link to find the file from
|
13
|
+
# * *file* (String): The file from which the link is taken
|
14
|
+
# Result::
|
15
|
+
# * String: Resulting file
|
16
|
+
def link_to_file(link, file)
|
17
|
+
link_file = link.split('#').first
|
18
|
+
if link_file == ''
|
19
|
+
file
|
20
|
+
elsif link_file.start_with?('/')
|
21
|
+
link_file[1..-1]
|
22
|
+
else
|
23
|
+
File.expand_path("#{File.dirname(file)}/#{link_file}").gsub("#{Dir.pwd}/", '')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Parse a Markdown file
|
28
|
+
#
|
29
|
+
# Parameters::
|
30
|
+
# * *file* (String): Markdown file to be parsed
|
31
|
+
def parse_md(file)
|
32
|
+
unless @info.key?(file)
|
33
|
+
puts "Parsing #{file}..."
|
34
|
+
content = File.read(file)
|
35
|
+
@info[file] = {
|
36
|
+
anchors: content.scan(/<a name="([^"]*)"><\/a>/).map { |(anchor)| anchor },
|
37
|
+
links: content.scan(/\[[^\]]*\]\(([^\)]*)\)/).map { |(link)| link }
|
38
|
+
}
|
39
|
+
# Parse linked files
|
40
|
+
@info[file][:links].each do |link|
|
41
|
+
puts "Found #{file} => #{link}"
|
42
|
+
end
|
43
|
+
@info[file][:links].each do |link|
|
44
|
+
unless link.start_with?('http')
|
45
|
+
linked_file = link_to_file(link, file)
|
46
|
+
parse_md(linked_file) if File.exist?(linked_file) && linked_file.end_with?('.md')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ARGV.each { |file| parse_md(file) }
|
53
|
+
|
54
|
+
# Check links
|
55
|
+
errors = []
|
56
|
+
@info.sort_by { |file, _info| file }.each do |file, info|
|
57
|
+
puts "= Links from #{file}"
|
58
|
+
info[:links].sort.uniq.each do |link|
|
59
|
+
puts "[#{
|
60
|
+
if link.start_with?('http')
|
61
|
+
'*'
|
62
|
+
else
|
63
|
+
anchor = link.split('#')[1]
|
64
|
+
linked_file = link_to_file(link, file)
|
65
|
+
if @info.key?(linked_file)
|
66
|
+
if anchor.nil?
|
67
|
+
'*'
|
68
|
+
elsif @info[linked_file][:anchors].include?(anchor)
|
69
|
+
'*'
|
70
|
+
else
|
71
|
+
errors << "[#{file} -> #{link}] - Destination has no anchor named #{anchor}"
|
72
|
+
' '
|
73
|
+
end
|
74
|
+
elsif File.exist?(linked_file)
|
75
|
+
'*'
|
76
|
+
else
|
77
|
+
errors << "[#{file} -> #{link}] - Destination file does not exist"
|
78
|
+
' '
|
79
|
+
end
|
80
|
+
end
|
81
|
+
}] #{link}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
puts
|
86
|
+
puts "#{errors.size} errors:"
|
87
|
+
errors.each do |error|
|
88
|
+
puts error
|
89
|
+
end
|