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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/README.md +31 -2
  4. data/docs/config_dsl.md +45 -0
  5. data/docs/plugins/cmdb/host_keys.md +3 -1
  6. data/docs/plugins/connector/ssh.md +1 -0
  7. data/lib/hybrid_platforms_conductor/actions_executor.rb +29 -1
  8. data/lib/hybrid_platforms_conductor/bitbucket.rb +134 -90
  9. data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
  10. data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +12 -44
  11. data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +9 -31
  12. data/lib/hybrid_platforms_conductor/config.rb +2 -0
  13. data/lib/hybrid_platforms_conductor/confluence.rb +93 -88
  14. data/lib/hybrid_platforms_conductor/connector.rb +5 -2
  15. data/lib/hybrid_platforms_conductor/credentials.rb +122 -97
  16. data/lib/hybrid_platforms_conductor/deployer.rb +7 -9
  17. data/lib/hybrid_platforms_conductor/github.rb +39 -0
  18. data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +1 -1
  19. data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +27 -17
  20. data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +13 -12
  21. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +6 -4
  22. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +1 -1
  23. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +37 -25
  24. data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +5 -6
  25. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +1 -1
  26. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +1 -1
  27. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +7 -4
  28. data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +3 -1
  29. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +3 -2
  30. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +3 -1
  31. data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -1
  32. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +17 -3
  33. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +30 -10
  34. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
  35. data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +4 -1
  36. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -2
  37. data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +1 -1
  38. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -2
  39. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +7 -3
  40. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +8 -4
  41. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -2
  42. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -2
  43. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -2
  44. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
  45. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -2
  46. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +3 -1
  47. data/lib/hybrid_platforms_conductor/logger_helpers.rb +24 -1
  48. data/lib/hybrid_platforms_conductor/test.rb +21 -7
  49. data/lib/hybrid_platforms_conductor/tests_runner.rb +7 -6
  50. data/lib/hybrid_platforms_conductor/thycotic.rb +80 -75
  51. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  52. data/spec/hybrid_platforms_conductor_test.rb +6 -0
  53. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +15 -0
  54. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -0
  55. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +87 -0
  56. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +30 -0
  57. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +10 -0
  58. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +38 -0
  59. data/spec/hybrid_platforms_conductor_test/api/actions_executor/helpers_spec.rb +195 -0
  60. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +14 -0
  61. data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +11 -0
  62. data/spec/hybrid_platforms_conductor_test/api/credentials_spec.rb +251 -0
  63. data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +215 -0
  64. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/keepass_spec.rb +280 -319
  65. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +2 -2
  66. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +49 -10
  67. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +38 -0
  68. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +49 -69
  69. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +29 -39
  70. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +5 -3
  71. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/chef_versions.yml +3 -0
  72. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/nodes/node.json +15 -0
  73. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/policyfiles/test_policy.rb +3 -0
  74. data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +134 -0
  75. data/spec/hybrid_platforms_conductor_test/test_connector.rb +2 -2
  76. 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): CmdRunner that can be used by tests
43
- # * *nodes_handler* (NodesHandler): Nodes handler that can be used by tests
44
- # * *deployer* (Deployer): Deployer that can be used by tests
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(logger, logger_stderr, config, cmd_runner, nodes_handler, deployer, name: 'unknown_test', platform: nil, node: nil, expected_failure: nil)
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
- @deployer,
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
- # Gives ways to query the Thycotic SOAP API at a given URL
9
- class Thycotic
8
+ # Mixin giving ways to query the Thycotic SOAP API at a given URL
9
+ module Thycotic
10
10
 
11
- include LoggerHelpers
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* (Thyctotic): The Thyctotic instance to use.
22
- def self.with_thycotic(thycotic_url, logger, logger_stderr, domain: ENV['hpc_domain_for_thycotic'])
23
- Credentials.with_credentials_for(:thycotic, logger, logger_stderr, url: thycotic_url) do |thycotic_user, thycotic_password|
24
- yield Thycotic.new(thycotic_url, thycotic_user, thycotic_password, domain: domain, logger: logger, logger_stderr: logger_stderr)
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
- # Constructor
29
- #
30
- # Parameters::
31
- # * *url* (String): URL of the Thycotic Secret Server
32
- # * *user* (String): User name to be used to connect to Thycotic
33
- # * *password* (String): Password to be used to connect to Thycotic
34
- # * *domain* (String): Domain to use for authentication to Thycotic [default: ENV['hpc_domain_for_thycotic']]
35
- # * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
36
- # * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
37
- def initialize(
38
- url,
39
- user,
40
- password,
41
- domain: ENV['hpc_domain_for_thycotic'],
42
- logger: Logger.new($stdout),
43
- logger_stderr: Logger.new($stderr)
44
- )
45
- init_loggers(logger, logger_stderr)
46
- # Get a token to this SOAP API
47
- @client = Savon.client(
48
- wsdl: "#{url}/webservices/SSWebservice.asmx?wsdl",
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
- @token = @client.call(
54
- :authenticate,
55
- message: {
56
- username: user,
57
- password: password,
58
- domain: domain
59
- }
60
- ).to_hash.dig(:authenticate_response, :authenticate_result, :token)
61
- raise "Unable to get token from SOAP authentication to #{url}" if @token.nil?
62
- end
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
- # Return secret corresponding to a given secret ID
65
- #
66
- # Parameters::
67
- # * *secret_id* (Object): The secret ID
68
- # Result::
69
- # * Hash: The corresponding API result
70
- def get_secret(secret_id)
71
- @client.call(
72
- :get_secret,
73
- message: {
74
- token: @token,
75
- secretId: secret_id
76
- }
77
- ).to_hash.dig(:get_secret_response, :get_secret_result)
78
- end
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,5 @@
1
1
  module HybridPlatformsConductor
2
2
 
3
- VERSION = '33.3.0'
3
+ VERSION = '33.7.0'
4
4
 
5
5
  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