hybrid_platforms_conductor 33.3.0 → 33.7.0
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 +41 -0
- data/README.md +31 -2
- data/docs/config_dsl.md +45 -0
- 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 +134 -90
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
- data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +12 -44
- data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +9 -31
- data/lib/hybrid_platforms_conductor/config.rb +2 -0
- data/lib/hybrid_platforms_conductor/confluence.rb +93 -88
- data/lib/hybrid_platforms_conductor/connector.rb +5 -2
- data/lib/hybrid_platforms_conductor/credentials.rb +122 -97
- data/lib/hybrid_platforms_conductor/deployer.rb +7 -9
- data/lib/hybrid_platforms_conductor/github.rb +39 -0
- 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 +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +7 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +3 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -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/github_ci.rb +4 -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 +7 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +8 -4
- 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/hpc_plugins/test_report/confluence.rb +3 -1
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +24 -1
- 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 +80 -75
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test.rb +6 -0
- 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 +251 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +215 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/keepass_spec.rb +280 -319
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +2 -2
- 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 +38 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +49 -69
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +29 -39
- 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 +36 -2
|
@@ -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,
|
|
@@ -5,95 +5,100 @@ require 'hybrid_platforms_conductor/logger_helpers'
|
|
|
5
5
|
|
|
6
6
|
module HybridPlatformsConductor
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
|
|
8
|
+
# Mixin giving ways to query the Thycotic SOAP API at a given URL
|
|
9
|
+
module Thycotic
|
|
10
10
|
|
|
11
|
-
include
|
|
11
|
+
include Credentials
|
|
12
12
|
|
|
13
13
|
# Provide a Thycotic connector, and make sure the password is being cleaned when exiting.
|
|
14
14
|
#
|
|
15
15
|
# Parameters::
|
|
16
16
|
# * *thycotic_url* (String): The Thycotic URL
|
|
17
|
-
# * *logger* (Logger): Logger to be used
|
|
18
|
-
# * *logger_stderr* (Logger): Logger to be used for stderr
|
|
19
17
|
# * *domain* (String): Domain to use for authentication to Thycotic [default: ENV['hpc_domain_for_thycotic']]
|
|
20
18
|
# * Proc: Code called with the Thyctotic instance.
|
|
21
|
-
# * *thycotic* (
|
|
22
|
-
def
|
|
23
|
-
|
|
24
|
-
yield
|
|
19
|
+
# * *thycotic* (ThyctoticApi): The Thycotic instance to use.
|
|
20
|
+
def with_thycotic(thycotic_url, domain: ENV['hpc_domain_for_thycotic'])
|
|
21
|
+
with_credentials_for(:thycotic, resource: thycotic_url) do |thycotic_user, thycotic_password|
|
|
22
|
+
yield ThycoticApi.new(thycotic_url, thycotic_user, thycotic_password, domain: domain, logger: @logger, logger_stderr: @logger_stderr)
|
|
25
23
|
end
|
|
26
24
|
end
|
|
27
25
|
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
ssl_verify_mode: :none,
|
|
50
|
-
logger: @logger,
|
|
51
|
-
log: log_debug?
|
|
26
|
+
# Access to the Thycotic API
|
|
27
|
+
class ThycoticApi
|
|
28
|
+
|
|
29
|
+
include LoggerHelpers
|
|
30
|
+
|
|
31
|
+
# Constructor
|
|
32
|
+
#
|
|
33
|
+
# Parameters::
|
|
34
|
+
# * *url* (String): URL of the Thycotic Secret Server
|
|
35
|
+
# * *user* (String): User name to be used to connect to Thycotic
|
|
36
|
+
# * *password* (SecretString): Password to be used to connect to Thycotic
|
|
37
|
+
# * *domain* (String): Domain to use for authentication to Thycotic [default: ENV['hpc_domain_for_thycotic']]
|
|
38
|
+
# * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
|
|
39
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
|
40
|
+
def initialize(
|
|
41
|
+
url,
|
|
42
|
+
user,
|
|
43
|
+
password,
|
|
44
|
+
domain: ENV['hpc_domain_for_thycotic'],
|
|
45
|
+
logger: Logger.new($stdout),
|
|
46
|
+
logger_stderr: Logger.new($stderr)
|
|
52
47
|
)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
init_loggers(logger, logger_stderr)
|
|
49
|
+
# Get a token to this SOAP API
|
|
50
|
+
@client = Savon.client(
|
|
51
|
+
wsdl: "#{url}/webservices/SSWebservice.asmx?wsdl",
|
|
52
|
+
ssl_verify_mode: :none,
|
|
53
|
+
logger: @logger,
|
|
54
|
+
log: log_debug?
|
|
55
|
+
)
|
|
56
|
+
@token = @client.call(
|
|
57
|
+
:authenticate,
|
|
58
|
+
message: {
|
|
59
|
+
username: user,
|
|
60
|
+
password: password&.to_unprotected,
|
|
61
|
+
domain: domain
|
|
62
|
+
}
|
|
63
|
+
).to_hash.dig(:authenticate_response, :authenticate_result, :token)
|
|
64
|
+
raise "Unable to get token from SOAP authentication to #{url}" if @token.nil?
|
|
65
|
+
end
|
|
63
66
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
67
|
+
# Return secret corresponding to a given secret ID
|
|
68
|
+
#
|
|
69
|
+
# Parameters::
|
|
70
|
+
# * *secret_id* (Object): The secret ID
|
|
71
|
+
# Result::
|
|
72
|
+
# * Hash: The corresponding API result
|
|
73
|
+
def get_secret(secret_id)
|
|
74
|
+
@client.call(
|
|
75
|
+
:get_secret,
|
|
76
|
+
message: {
|
|
77
|
+
token: @token,
|
|
78
|
+
secretId: secret_id
|
|
79
|
+
}
|
|
80
|
+
).to_hash.dig(:get_secret_response, :get_secret_result)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Get a file attached to a given secret
|
|
84
|
+
#
|
|
85
|
+
# Parameters::
|
|
86
|
+
# * *secret_id* (Object): The secret ID
|
|
87
|
+
# * *secret_item_id* (Object): The secret item id
|
|
88
|
+
# Result::
|
|
89
|
+
# * String or nil: The file content, or nil if none
|
|
90
|
+
def download_file_attachment_by_item_id(secret_id, secret_item_id)
|
|
91
|
+
encoded_file = @client.call(
|
|
92
|
+
:download_file_attachment_by_item_id,
|
|
93
|
+
message: {
|
|
94
|
+
token: @token,
|
|
95
|
+
secretId: secret_id,
|
|
96
|
+
secretItemId: secret_item_id
|
|
97
|
+
}
|
|
98
|
+
).to_hash.dig(:download_file_attachment_by_item_id_response, :download_file_attachment_by_item_id_result, :file_attachment)
|
|
99
|
+
encoded_file.nil? ? nil : Base64.decode64(encoded_file)
|
|
100
|
+
end
|
|
79
101
|
|
|
80
|
-
# Get a file attached to a given secret
|
|
81
|
-
#
|
|
82
|
-
# Parameters::
|
|
83
|
-
# * *secret_id* (Object): The secret ID
|
|
84
|
-
# * *secret_item_id* (Object): The secret item id
|
|
85
|
-
# Result::
|
|
86
|
-
# * String or nil: The file content, or nil if none
|
|
87
|
-
def download_file_attachment_by_item_id(secret_id, secret_item_id)
|
|
88
|
-
encoded_file = @client.call(
|
|
89
|
-
:download_file_attachment_by_item_id,
|
|
90
|
-
message: {
|
|
91
|
-
token: @token,
|
|
92
|
-
secretId: secret_id,
|
|
93
|
-
secretItemId: secret_item_id
|
|
94
|
-
}
|
|
95
|
-
).to_hash.dig(:download_file_attachment_by_item_id_response, :download_file_attachment_by_item_id_result, :file_attachment)
|
|
96
|
-
encoded_file.nil? ? nil : Base64.decode64(encoded_file)
|
|
97
102
|
end
|
|
98
103
|
|
|
99
104
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'fileutils'
|
|
2
2
|
require 'tmpdir'
|
|
3
|
+
require 'webmock/rspec'
|
|
3
4
|
require 'hybrid_platforms_conductor/config'
|
|
4
5
|
require 'hybrid_platforms_conductor/platforms_handler'
|
|
5
6
|
require 'hybrid_platforms_conductor/actions_executor'
|
|
@@ -83,6 +84,9 @@ module HybridPlatformsConductorTest
|
|
|
83
84
|
# Make sure the tested components are being reset before each test case
|
|
84
85
|
RSpec.configure do |config|
|
|
85
86
|
config.before do
|
|
87
|
+
# We allow for connections by default.
|
|
88
|
+
# Tests that need to test specifically connections at a given point call WebMock.disable_net_connect!
|
|
89
|
+
WebMock.allow_net_connect!
|
|
86
90
|
@actions_executor = nil
|
|
87
91
|
@cmd_runner = nil
|
|
88
92
|
@config = nil
|
|
@@ -95,6 +99,8 @@ module HybridPlatformsConductorTest
|
|
|
95
99
|
ENV.delete 'hpc_platforms'
|
|
96
100
|
ENV.delete 'hpc_ssh_gateways_conf'
|
|
97
101
|
ENV.delete 'hpc_ssh_gateway_user'
|
|
102
|
+
ENV.delete 'hpc_user_for_github'
|
|
103
|
+
ENV.delete 'hpc_password_for_github'
|
|
98
104
|
ENV.delete 'hpc_user_for_proxmox'
|
|
99
105
|
ENV.delete 'hpc_password_for_proxmox'
|
|
100
106
|
ENV.delete 'hpc_realm_for_proxmox'
|
|
@@ -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
|