hybrid_platforms_conductor 33.4.0 → 33.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +47 -0
- data/README.md +5 -5
- data/docs/config_dsl.md +7 -5
- data/docs/plugins/cmdb/host_keys.md +3 -1
- data/docs/plugins/connector/ssh.md +1 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +29 -1
- data/lib/hybrid_platforms_conductor/bitbucket.rb +2 -2
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
- data/lib/hybrid_platforms_conductor/config.rb +2 -0
- data/lib/hybrid_platforms_conductor/confluence.rb +2 -2
- data/lib/hybrid_platforms_conductor/connector.rb +5 -2
- data/lib/hybrid_platforms_conductor/credentials.rb +20 -12
- data/lib/hybrid_platforms_conductor/deployer.rb +5 -7
- data/lib/hybrid_platforms_conductor/github.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +27 -17
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +13 -12
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +6 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +37 -25
- data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +5 -6
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +23 -14
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +3 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +17 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +30 -10
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -2
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +17 -0
- data/lib/hybrid_platforms_conductor/test.rb +21 -7
- data/lib/hybrid_platforms_conductor/tests_runner.rb +7 -6
- data/lib/hybrid_platforms_conductor/thycotic.rb +2 -2
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +15 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +87 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +30 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +10 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +38 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/helpers_spec.rb +195 -0
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +14 -0
- data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +11 -0
- data/spec/hybrid_platforms_conductor_test/api/credentials_spec.rb +8 -4
- data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +215 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +49 -10
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +64 -16
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +5 -3
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/chef_versions.yml +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/nodes/node.json +15 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/policyfiles/test_policy.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +134 -0
- data/spec/hybrid_platforms_conductor_test/test_connector.rb +2 -2
- metadata +20 -2
@@ -17,7 +17,7 @@ module HybridPlatformsConductor
|
|
17
17
|
# Flatten the paths rules so that we can spot inconsistencies in configuration
|
18
18
|
@config.aggregate_files_rules(@nodes_handler, @node).map do |path, rule_info|
|
19
19
|
[
|
20
|
-
"if #{@
|
20
|
+
"if #{@actions_executor.sudo_prefix(@node)}/bin/bash -c '[[ -d \"#{path}\" ]]' ; then echo 1 ; else echo 0 ; fi",
|
21
21
|
{
|
22
22
|
validator: proc do |stdout, stderr|
|
23
23
|
case stdout.last
|
@@ -12,8 +12,7 @@ module HybridPlatformsConductor
|
|
12
12
|
# Check my_test_plugin.rb.sample documentation for signature details.
|
13
13
|
def test_on_node
|
14
14
|
{
|
15
|
-
#
|
16
|
-
"#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}hostname -s" => proc do |stdout|
|
15
|
+
"#{@actions_executor.sudo_prefix(@node)}hostname -s" => proc do |stdout|
|
17
16
|
assert_equal stdout.first, @node, "Expected hostname to be #{@node}, but got #{stdout.first} instead."
|
18
17
|
end
|
19
18
|
}
|
@@ -27,7 +27,7 @@ module HybridPlatformsConductor
|
|
27
27
|
# System is booting up. See pam_nologin(8)
|
28
28
|
# Authentication failed.
|
29
29
|
instance.stop
|
30
|
-
instance.with_running_instance(port: 22) do
|
30
|
+
instance.with_running_instance(port: @nodes_handler.get_ssh_port_of(@node) || 22) do
|
31
31
|
# Now that the node has been deployed, use the a_testadmin user for the check-node (as root has no more access)
|
32
32
|
deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user = 'a_testadmin'
|
33
33
|
deployer.instance_variable_get(:@actions_executor).connector(:ssh).passwords.delete(@node)
|
@@ -12,8 +12,7 @@ module HybridPlatformsConductor
|
|
12
12
|
# Check my_test_plugin.rb.sample documentation for signature details.
|
13
13
|
def test_on_node
|
14
14
|
{
|
15
|
-
#
|
16
|
-
"#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}hostname -I" => proc do |stdout|
|
15
|
+
"#{@actions_executor.sudo_prefix(@node)}hostname -I" => proc do |stdout|
|
17
16
|
if stdout.first.nil?
|
18
17
|
error 'No IP returned by "hostname -I"'
|
19
18
|
else
|
@@ -26,7 +26,7 @@ module HybridPlatformsConductor
|
|
26
26
|
else
|
27
27
|
with_credentials_for(:jenkins_ci, resource: repo_info[:jenkins_ci_url]) do |jenkins_user, jenkins_password|
|
28
28
|
# Get its config
|
29
|
-
doc = Nokogiri::XML(URI.parse("#{repo_info[:jenkins_ci_url]}/config.xml").open(http_basic_authentication: [jenkins_user, jenkins_password]).read)
|
29
|
+
doc = Nokogiri::XML(URI.parse("#{repo_info[:jenkins_ci_url]}/config.xml").open(http_basic_authentication: [jenkins_user, jenkins_password&.to_unprotected]).read)
|
30
30
|
# Check that this job builds the correct Bitbucket repository
|
31
31
|
assert_equal(
|
32
32
|
doc.xpath('/org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject/sources/data/jenkins.branch.BranchSource/source/serverUrl').text,
|
@@ -34,10 +34,10 @@ module HybridPlatformsConductor
|
|
34
34
|
master_info_url = "#{repo_info[:jenkins_ci_url]}/job/master/api/json"
|
35
35
|
with_credentials_for(:jenkins_ci, resource: master_info_url) do |jenkins_user, jenkins_password|
|
36
36
|
# Get the master branch info from the API
|
37
|
-
master_info = JSON.parse(URI.parse(master_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password]).read)
|
37
|
+
master_info = JSON.parse(URI.parse(master_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password&.to_unprotected]).read)
|
38
38
|
# Get the last build's URL
|
39
39
|
last_build_info_url = "#{master_info['lastBuild']['url']}/api/json"
|
40
|
-
last_build_info = JSON.parse(URI.parse(last_build_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password]).read)
|
40
|
+
last_build_info = JSON.parse(URI.parse(last_build_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password&.to_unprotected]).read)
|
41
41
|
log_debug "Build info for #{master_info_url}:\n#{JSON.pretty_generate(last_build_info)}"
|
42
42
|
error "Last build for job #{repo_info[:project]}/#{repo_info[:name]} is in status #{last_build_info['result']}: #{master_info['lastBuild']['url']}" unless SUCCESS_STATUSES.include?(last_build_info['result'])
|
43
43
|
rescue
|
@@ -59,8 +59,7 @@ module HybridPlatformsConductor
|
|
59
59
|
# Check my_test_plugin.rb.sample documentation for signature details.
|
60
60
|
def test_on_node
|
61
61
|
{
|
62
|
-
#
|
63
|
-
"#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}cat /etc/passwd" => proc do |stdout|
|
62
|
+
"#{@actions_executor.sudo_prefix(@node)}cat /etc/passwd" => proc do |stdout|
|
64
63
|
passwd_users = stdout.map { |passwd_line| passwd_line.split(':').first }
|
65
64
|
missing_users = @nodes_handler.
|
66
65
|
select_confs_for_node(@node, @config.users_that_should_be_present).
|
@@ -63,8 +63,7 @@ module HybridPlatformsConductor
|
|
63
63
|
# Check my_test_plugin.rb.sample documentation for signature details.
|
64
64
|
def test_on_node
|
65
65
|
{
|
66
|
-
#
|
67
|
-
"#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}mount" => proc do |stdout|
|
66
|
+
"#{@actions_executor.sudo_prefix(@node)}mount" => proc do |stdout|
|
68
67
|
mounts_info = stdout.map do |line|
|
69
68
|
fields = line.split
|
70
69
|
{
|
@@ -52,8 +52,7 @@ module HybridPlatformsConductor
|
|
52
52
|
# Check my_test_plugin.rb.sample documentation for signature details.
|
53
53
|
def test_on_node
|
54
54
|
{
|
55
|
-
#
|
56
|
-
"#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}/usr/bin/find / \\( #{
|
55
|
+
"#{@actions_executor.sudo_prefix(@node)}/usr/bin/find / \\( #{
|
57
56
|
@nodes_handler.
|
58
57
|
select_confs_for_node(@node, @config.ignored_orphan_files_paths).
|
59
58
|
inject(DIRECTORIES_TO_ALWAYS_IGNORE) { |merged_paths, paths_to_ignore_info| merged_paths + paths_to_ignore_info[:ignored_paths] }.
|
@@ -18,7 +18,7 @@ module HybridPlatformsConductor
|
|
18
18
|
# Check my_test_plugin.rb.sample documentation for signature details.
|
19
19
|
def test_on_node
|
20
20
|
spectre_cmd = <<~EO_BASH
|
21
|
-
#{@
|
21
|
+
#{@actions_executor.sudo_prefix(@node)}/bin/bash <<'EOAction'
|
22
22
|
#{File.read("#{__dir__}/spectre-meltdown-checker.sh")}
|
23
23
|
EOAction
|
24
24
|
EO_BASH
|
@@ -56,8 +56,7 @@ module HybridPlatformsConductor
|
|
56
56
|
current_url
|
57
57
|
end
|
58
58
|
)
|
59
|
-
|
60
|
-
sudo = @deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "
|
59
|
+
sudo = @actions_executor.sudo_prefix(@node)
|
61
60
|
urls.map do |url|
|
62
61
|
# 1. Get the OVAL file on the node to be tested (uncompress it if needed)
|
63
62
|
# 2. Make sure oscap is installed
|
@@ -1,6 +1,23 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
require 'logger'
|
3
3
|
require 'ruby-progressbar'
|
4
|
+
require 'secret_string'
|
5
|
+
|
6
|
+
# Add colorization methods to SecretString, but always directed to the silenced string as we NEVER want to modiy/clone a secret
|
7
|
+
class SecretString
|
8
|
+
|
9
|
+
extend Colorize::ClassMethods
|
10
|
+
|
11
|
+
def_delegators :@silenced_str, *%i[
|
12
|
+
colorize
|
13
|
+
uncolorize
|
14
|
+
colorized?
|
15
|
+
]
|
16
|
+
|
17
|
+
color_methods
|
18
|
+
modes_methods
|
19
|
+
|
20
|
+
end
|
4
21
|
|
5
22
|
module HybridPlatformsConductor
|
6
23
|
|
@@ -36,20 +36,34 @@ module HybridPlatformsConductor
|
|
36
36
|
# Constructor
|
37
37
|
#
|
38
38
|
# Parameters::
|
39
|
-
# * *logger* (Logger): Logger to be used
|
40
|
-
# * *logger_stderr* (Logger): Logger to be used for stderr
|
41
|
-
# * *config* (Config): Config to be used.
|
42
|
-
# * *cmd_runner* (CmdRunner):
|
43
|
-
# * *nodes_handler* (NodesHandler): Nodes handler
|
44
|
-
# * *
|
39
|
+
# * *logger* (Logger): Logger to be used [default: Logger.new($stdout)]
|
40
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new($stderr)]
|
41
|
+
# * *config* (Config): Config to be used. [default: Config.new]
|
42
|
+
# * *cmd_runner* (CmdRunner): Command executor to be used. [default: CmdRunner.new]
|
43
|
+
# * *nodes_handler* (NodesHandler): Nodes handler to be used. [default: NodesHandler.new]
|
44
|
+
# * *actions_executor* (ActionsExecutor): Actions Executor to be used. [default: ActionsExecutor.new]
|
45
|
+
# * *deployer* (Deployer): Deployer that can be used by tests [default: Deployer.new]
|
45
46
|
# * *name* (String): Name of the test being instantiated [default: 'unknown_test']
|
46
47
|
# * *platform* (PlatformHandler): Platform handler for which the test is instantiated, or nil if global or node specific [default: nil]
|
47
48
|
# * *node* (String): Node name for which the test is instantiated, or nil if global or platform specific [default: nil]
|
48
49
|
# * *expected_failure* (String or nil): Expected failure, or nil if not expected to fail [default: nil]
|
49
|
-
def initialize(
|
50
|
+
def initialize(
|
51
|
+
logger: Logger.new($stdout),
|
52
|
+
logger_stderr: Logger.new($stderr),
|
53
|
+
config: Config.new,
|
54
|
+
cmd_runner: CmdRunner.new,
|
55
|
+
nodes_handler: NodesHandler.new,
|
56
|
+
actions_executor: ActionsExecutor.new,
|
57
|
+
deployer: Deployer.new,
|
58
|
+
name: 'unknown_test',
|
59
|
+
platform: nil,
|
60
|
+
node: nil,
|
61
|
+
expected_failure: nil
|
62
|
+
)
|
50
63
|
super(logger: logger, logger_stderr: logger_stderr, config: config)
|
51
64
|
@cmd_runner = cmd_runner
|
52
65
|
@nodes_handler = nodes_handler
|
66
|
+
@actions_executor = actions_executor
|
53
67
|
@deployer = deployer
|
54
68
|
@name = name
|
55
69
|
@platform = platform
|
@@ -274,12 +274,13 @@ module HybridPlatformsConductor
|
|
274
274
|
# * Test: Corresponding test
|
275
275
|
def new_test(test_name, platform: nil, node: nil, ignore_expected_failure: false)
|
276
276
|
(test_name.nil? ? Test : @tests_plugins[test_name]).new(
|
277
|
-
@logger,
|
278
|
-
@logger_stderr,
|
279
|
-
@config,
|
280
|
-
@cmd_runner,
|
281
|
-
@nodes_handler,
|
282
|
-
@
|
277
|
+
logger: @logger,
|
278
|
+
logger_stderr: @logger_stderr,
|
279
|
+
config: @config,
|
280
|
+
cmd_runner: @cmd_runner,
|
281
|
+
nodes_handler: @nodes_handler,
|
282
|
+
actions_executor: @actions_executor,
|
283
|
+
deployer: @deployer,
|
283
284
|
name: test_name.nil? ? :global : test_name,
|
284
285
|
platform: platform,
|
285
286
|
node: node,
|
@@ -33,7 +33,7 @@ module HybridPlatformsConductor
|
|
33
33
|
# Parameters::
|
34
34
|
# * *url* (String): URL of the Thycotic Secret Server
|
35
35
|
# * *user* (String): User name to be used to connect to Thycotic
|
36
|
-
# * *password* (
|
36
|
+
# * *password* (SecretString): Password to be used to connect to Thycotic
|
37
37
|
# * *domain* (String): Domain to use for authentication to Thycotic [default: ENV['hpc_domain_for_thycotic']]
|
38
38
|
# * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
|
39
39
|
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
@@ -57,7 +57,7 @@ module HybridPlatformsConductor
|
|
57
57
|
:authenticate,
|
58
58
|
message: {
|
59
59
|
username: user,
|
60
|
-
password: password,
|
60
|
+
password: password&.to_unprotected,
|
61
61
|
domain: domain
|
62
62
|
}
|
63
63
|
).to_hash.dig(:authenticate_response, :authenticate_result, :token)
|
@@ -17,6 +17,21 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
it 'executes local Bash code from a SecretString' do
|
21
|
+
with_test_platform_for_action_plugins do |repository|
|
22
|
+
expect(
|
23
|
+
test_actions_executor.execute_actions(
|
24
|
+
{
|
25
|
+
'node' => {
|
26
|
+
bash: SecretString.new("echo TestContent >#{repository}/test_file ; echo TestStdout ; echo TestStderr 1>&2", silenced_str: '__INVALID_BASH__')
|
27
|
+
}
|
28
|
+
}
|
29
|
+
)['node']
|
30
|
+
).to eq [0, "TestStdout\n", "TestStderr\n"]
|
31
|
+
expect(File.read("#{repository}/test_file")).to eq "TestContent\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
20
35
|
it 'executes local Bash code with timeout' do
|
21
36
|
with_test_platform_for_action_plugins do
|
22
37
|
expect(test_actions_executor.execute_actions(
|
@@ -13,6 +13,17 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'executes remote Bash code from a SecretString' do
|
17
|
+
with_test_platform_for_action_plugins do
|
18
|
+
test_actions_executor.execute_actions({ 'node' => { remote_bash: SecretString.new('remote_bash_cmd.bash', silenced_str: '__INVALID_BASH__') } })
|
19
|
+
expect(test_actions_executor.connector(:test_connector).calls).to eq [
|
20
|
+
[:connectable_nodes_from, ['node']],
|
21
|
+
[:with_connection_to, ['node'], { no_exception: true }],
|
22
|
+
[:remote_bash, 'remote_bash_cmd.bash']
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
16
27
|
it 'executes remote Bash code with timeout' do
|
17
28
|
with_test_platform_for_action_plugins do
|
18
29
|
test_actions_executor.connector(:test_connector).remote_bash_code = proc do |_stdout, _stderr, connector|
|
@@ -124,6 +135,27 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
124
135
|
end
|
125
136
|
end
|
126
137
|
|
138
|
+
it 'executes remote Bash code with environment variables set using SecretStrings' do
|
139
|
+
with_test_platform_for_action_plugins do
|
140
|
+
test_actions_executor.execute_actions(
|
141
|
+
{
|
142
|
+
'node' => { remote_bash: {
|
143
|
+
commands: 'bash_cmd.bash',
|
144
|
+
env: {
|
145
|
+
'var1' => SecretString.new('value1', silenced_str: 'SILENCED_VALUE'),
|
146
|
+
'var2' => 'value2'
|
147
|
+
}
|
148
|
+
} }
|
149
|
+
}
|
150
|
+
)
|
151
|
+
expect(test_actions_executor.connector(:test_connector).calls).to eq [
|
152
|
+
[:connectable_nodes_from, ['node']],
|
153
|
+
[:with_connection_to, ['node'], { no_exception: true }],
|
154
|
+
[:remote_bash, "export var1='value1'\nexport var2='value2'\nbash_cmd.bash"]
|
155
|
+
]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
127
159
|
end
|
128
160
|
|
129
161
|
end
|
@@ -54,6 +54,15 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
it 'executes bash commands remotely from a SecretString' do
|
58
|
+
with_test_platform_for_remote_testing(
|
59
|
+
expected_cmds: [['cd /tmp/hpc_local_workspaces/node ; bash_cmd.bash', proc { [0, 'Bash commands executed on node', ''] }]],
|
60
|
+
expected_stdout: 'Bash commands executed on node'
|
61
|
+
) do
|
62
|
+
test_connector.remote_bash(SecretString.new('bash_cmd.bash', silenced_str: '__INVALID_BASH__'))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
57
66
|
it 'executes bash commands remotely with timeout' do
|
58
67
|
with_test_platform_for_remote_testing(
|
59
68
|
expected_cmds: [
|
@@ -98,6 +107,10 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
98
107
|
it 'copies files remotely with sudo' do
|
99
108
|
with_test_platform_for_remote_testing(
|
100
109
|
expected_cmds: [
|
110
|
+
[
|
111
|
+
'whoami',
|
112
|
+
proc { [0, 'test_user', ''] }
|
113
|
+
],
|
101
114
|
[
|
102
115
|
'sudo -u root cp -r "/path/to/src.file" "/remote_path/to/dst.dir"',
|
103
116
|
proc { [0, '', ''] }
|
@@ -108,9 +121,27 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
108
121
|
end
|
109
122
|
end
|
110
123
|
|
124
|
+
it 'copies files remotely with sudo when being root' do
|
125
|
+
with_test_platform_for_remote_testing(
|
126
|
+
expected_cmds: [
|
127
|
+
[
|
128
|
+
'whoami',
|
129
|
+
proc { [0, 'root', ''] }
|
130
|
+
]
|
131
|
+
]
|
132
|
+
) do
|
133
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/remote_path/to/dst.dir')
|
134
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
111
138
|
it 'copies files remotely with a different sudo' do
|
112
139
|
with_test_platform_for_remote_testing(
|
113
140
|
expected_cmds: [
|
141
|
+
[
|
142
|
+
'whoami',
|
143
|
+
proc { [0, 'test_user', ''] }
|
144
|
+
],
|
114
145
|
[
|
115
146
|
'other_sudo --user root cp -r "/path/to/src.file" "/remote_path/to/dst.dir"',
|
116
147
|
proc { [0, '', ''] }
|
@@ -124,6 +155,23 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
124
155
|
end
|
125
156
|
end
|
126
157
|
|
158
|
+
it 'copies files remotely with a different sudo when being root' do
|
159
|
+
with_test_platform_for_remote_testing(
|
160
|
+
expected_cmds: [
|
161
|
+
[
|
162
|
+
'whoami',
|
163
|
+
proc { [0, 'root', ''] }
|
164
|
+
]
|
165
|
+
],
|
166
|
+
additional_config: <<~'EO_CONFIG'
|
167
|
+
sudo_for { |user| "other_sudo --user #{user}" }
|
168
|
+
EO_CONFIG
|
169
|
+
) do
|
170
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/remote_path/to/dst.dir')
|
171
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
127
175
|
it 'copies files remotely with timeout' do
|
128
176
|
with_test_platform_for_remote_testing(
|
129
177
|
timeout: 5
|
@@ -143,6 +191,10 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
143
191
|
it 'copies relative files remotely with sudo' do
|
144
192
|
with_test_platform_for_remote_testing(
|
145
193
|
expected_cmds: [
|
194
|
+
[
|
195
|
+
'whoami',
|
196
|
+
proc { [0, 'test_user', ''] }
|
197
|
+
],
|
146
198
|
[
|
147
199
|
'sudo -u root cp -r "/path/to/src.file" "/tmp/hpc_local_workspaces/node/to/dst.dir"',
|
148
200
|
proc { [0, '', ''] }
|
@@ -153,9 +205,27 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
153
205
|
end
|
154
206
|
end
|
155
207
|
|
208
|
+
it 'copies relative files remotely with sudo when being root' do
|
209
|
+
with_test_platform_for_remote_testing(
|
210
|
+
expected_cmds: [
|
211
|
+
[
|
212
|
+
'whoami',
|
213
|
+
proc { [0, 'root', ''] }
|
214
|
+
]
|
215
|
+
]
|
216
|
+
) do
|
217
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/tmp/hpc_local_workspaces/node/to/dst.dir')
|
218
|
+
test_connector.remote_copy('/path/to/src.file', 'to/dst.dir', sudo: true)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
156
222
|
it 'copies relative files remotely with a different sudo' do
|
157
223
|
with_test_platform_for_remote_testing(
|
158
224
|
expected_cmds: [
|
225
|
+
[
|
226
|
+
'whoami',
|
227
|
+
proc { [0, 'test_user', ''] }
|
228
|
+
],
|
159
229
|
[
|
160
230
|
'other_sudo --user root cp -r "/path/to/src.file" "/tmp/hpc_local_workspaces/node/to/dst.dir"',
|
161
231
|
proc { [0, '', ''] }
|
@@ -169,6 +239,23 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
169
239
|
end
|
170
240
|
end
|
171
241
|
|
242
|
+
it 'copies relative files remotely with a different sudo when being root' do
|
243
|
+
with_test_platform_for_remote_testing(
|
244
|
+
expected_cmds: [
|
245
|
+
[
|
246
|
+
'whoami',
|
247
|
+
proc { [0, 'root', ''] }
|
248
|
+
]
|
249
|
+
],
|
250
|
+
additional_config: <<~'EO_CONFIG'
|
251
|
+
sudo_for { |user| "other_sudo --user #{user}" }
|
252
|
+
EO_CONFIG
|
253
|
+
) do
|
254
|
+
expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/tmp/hpc_local_workspaces/node/to/dst.dir')
|
255
|
+
test_connector.remote_copy('/path/to/src.file', 'to/dst.dir', sudo: true)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
172
259
|
end
|
173
260
|
|
174
261
|
end
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb
CHANGED
@@ -132,6 +132,36 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
132
132
|
end
|
133
133
|
end
|
134
134
|
|
135
|
+
it 'creates SSH master to several nodes differing only by the SSH port' do
|
136
|
+
with_test_platform(
|
137
|
+
{
|
138
|
+
nodes: {
|
139
|
+
'node1' => { meta: { host_ip: '192.168.42.1', ssh_port: 6661 } },
|
140
|
+
'node2' => { meta: { host_ip: '192.168.42.1', ssh_port: 6662 } },
|
141
|
+
'node3' => { meta: { host_ip: '192.168.42.1', ssh_port: 6663 } }
|
142
|
+
}
|
143
|
+
}
|
144
|
+
) do
|
145
|
+
with_cmd_runner_mocked(
|
146
|
+
[
|
147
|
+
['which env', proc { [0, "/usr/bin/env\n", ''] }],
|
148
|
+
['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }]
|
149
|
+
] + ssh_expected_commands_for(
|
150
|
+
{
|
151
|
+
'node1' => { connection: '192.168.42.1', user: 'test_user', port: 6661 },
|
152
|
+
'node2' => { connection: '192.168.42.1', user: 'test_user', port: 6662 },
|
153
|
+
'node3' => { connection: '192.168.42.1', user: 'test_user', port: 6663 }
|
154
|
+
}
|
155
|
+
)
|
156
|
+
) do
|
157
|
+
test_connector.ssh_user = 'test_user'
|
158
|
+
test_connector.with_connection_to(%w[node1 node2 node3]) do |connected_nodes|
|
159
|
+
expect(connected_nodes.sort).to eq %w[node1 node2 node3].sort
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
135
165
|
it 'creates SSH master to several nodes with ssh connections transformed' do
|
136
166
|
with_test_platform(
|
137
167
|
{ nodes: {
|