hybrid_platforms_conductor 33.3.0 → 33.7.0

Sign up to get free protection for your applications and to get access to all the features.
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