hybrid_platforms_conductor 32.5.0 → 32.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/hybrid_platforms_conductor/deployer.rb +12 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +157 -81
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +11 -9
- data/lib/hybrid_platforms_conductor/provisioner.rb +9 -0
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +67 -5
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +50 -6
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +34 -10
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +74 -10
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/{config_spec.rb → config_dsl_spec.rb} +4 -4
- data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +2 -1
- data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +33 -11
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +46 -12
- metadata +3 -3
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb
CHANGED
|
@@ -43,6 +43,41 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
it 'returns ssh transformation procs' do
|
|
47
|
+
with_test_platform(
|
|
48
|
+
{
|
|
49
|
+
nodes: {
|
|
50
|
+
'node1' => {},
|
|
51
|
+
'node2' => {},
|
|
52
|
+
'node3' => {}
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
false,
|
|
56
|
+
'
|
|
57
|
+
for_nodes(%w[node1 node3]) do
|
|
58
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
59
|
+
["#{connection}_#{node}_13", "#{connection_user}_#{node}_13", "#{gateway}_#{node}_13", "#{gateway_user}_#{node}_13"]
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
for_nodes(\'node1\') do
|
|
63
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
64
|
+
["#{connection}_#{node}_1", "#{connection_user}_#{node}_1", "#{gateway}_#{node}_1", "#{gateway_user}_#{node}_1"]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
'
|
|
68
|
+
) do
|
|
69
|
+
expect(test_config.ssh_connection_transforms.size).to eq 2
|
|
70
|
+
expect(test_config.ssh_connection_transforms[0][:nodes_selectors_stack]).to eq [%w[node1 node3]]
|
|
71
|
+
expect(test_config.ssh_connection_transforms[0][:transform].call('node1', 'test_host', 'test_user', 'test_gateway', 'test_gateway_user')).to eq [
|
|
72
|
+
'test_host_node1_13', 'test_user_node1_13', 'test_gateway_node1_13', 'test_gateway_user_node1_13'
|
|
73
|
+
]
|
|
74
|
+
expect(test_config.ssh_connection_transforms[1][:nodes_selectors_stack]).to eq ['node1']
|
|
75
|
+
expect(test_config.ssh_connection_transforms[1][:transform].call('node1', 'test_host', 'test_user', 'test_gateway', 'test_gateway_user')).to eq [
|
|
76
|
+
'test_host_node1_1', 'test_user_node1_1', 'test_gateway_node1_1', 'test_gateway_user_node1_1'
|
|
77
|
+
]
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
46
81
|
end
|
|
47
82
|
|
|
48
83
|
end
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb
CHANGED
|
@@ -28,6 +28,22 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
it 'creates an SSH master to 1 node not having Session Exec capabilities' do
|
|
32
|
+
with_test_platform(nodes: { 'node' => { meta: { host_ip: '192.168.42.42', ssh_session_exec: 'false' } } }) do
|
|
33
|
+
with_cmd_runner_mocked(
|
|
34
|
+
[
|
|
35
|
+
['which env', proc { [0, "/usr/bin/env\n", ''] }],
|
|
36
|
+
['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }]
|
|
37
|
+
] + ssh_expected_commands_for({ 'node' => { connection: '192.168.42.42', user: 'test_user' } }, with_session_exec: false)
|
|
38
|
+
) do
|
|
39
|
+
test_connector.ssh_user = 'test_user'
|
|
40
|
+
test_connector.with_connection_to(['node']) do |connected_nodes|
|
|
41
|
+
expect(connected_nodes).to eq ['node']
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
31
47
|
it 'creates SSH master to several nodes' do
|
|
32
48
|
with_test_platform(nodes: {
|
|
33
49
|
'node1' => { meta: { host_ip: '192.168.42.1' } },
|
|
@@ -52,6 +68,45 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
52
68
|
end
|
|
53
69
|
end
|
|
54
70
|
|
|
71
|
+
it 'creates SSH master to several nodes with ssh connections transformed' do
|
|
72
|
+
with_test_platform(
|
|
73
|
+
{ nodes: {
|
|
74
|
+
'node1' => { meta: { host_ip: '192.168.42.1' } },
|
|
75
|
+
'node2' => { meta: { host_ip: '192.168.42.2' } },
|
|
76
|
+
'node3' => { meta: { host_ip: '192.168.42.3' } }
|
|
77
|
+
} },
|
|
78
|
+
false,
|
|
79
|
+
'
|
|
80
|
+
for_nodes(%w[node1 node3]) do
|
|
81
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
82
|
+
["#{connection}_#{node}_13", "#{connection_user}_#{node}_13", "#{gateway}_#{node}_13", "#{gateway_user}_#{node}_13"]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
for_nodes(\'node1\') do
|
|
86
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
87
|
+
["#{connection}_#{node}_1", "#{connection_user}_#{node}_1", "#{gateway}_#{node}_1", "#{gateway_user}_#{node}_1"]
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
'
|
|
91
|
+
) do
|
|
92
|
+
with_cmd_runner_mocked(
|
|
93
|
+
[
|
|
94
|
+
['which env', proc { [0, "/usr/bin/env\n", ''] }],
|
|
95
|
+
['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }]
|
|
96
|
+
] + ssh_expected_commands_for(
|
|
97
|
+
'node1' => { ip: '192.168.42.1', connection: '192.168.42.1_node1_13_node1_1', user: 'test_user_node1_13_node1_1' },
|
|
98
|
+
'node2' => { ip: '192.168.42.2', connection: '192.168.42.2', user: 'test_user' },
|
|
99
|
+
'node3' => { ip: '192.168.42.3', connection: '192.168.42.3_node3_13', user: 'test_user_node3_13' }
|
|
100
|
+
)
|
|
101
|
+
) do
|
|
102
|
+
test_connector.ssh_user = 'test_user'
|
|
103
|
+
test_connector.with_connection_to(%w[node1 node2 node3]) do |connected_nodes|
|
|
104
|
+
expect(connected_nodes.sort).to eq %w[node1 node2 node3].sort
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
55
110
|
it 'fails when an SSH master can\'t be created' do
|
|
56
111
|
with_test_platform(nodes: {
|
|
57
112
|
'node1' => { meta: { host_ip: '192.168.42.1' } },
|
|
@@ -63,8 +118,14 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
63
118
|
['which env', proc { [0, "/usr/bin/env\n", ''] }],
|
|
64
119
|
['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }]
|
|
65
120
|
] + ssh_expected_commands_for(
|
|
66
|
-
|
|
67
|
-
|
|
121
|
+
{
|
|
122
|
+
'node1' => { connection: '192.168.42.1', user: 'test_user' },
|
|
123
|
+
'node3' => { connection: '192.168.42.3', user: 'test_user' }
|
|
124
|
+
},
|
|
125
|
+
# Here the threads for node1's and node3's ControlMasters might not trigger before the one for node2, so they will not destroy it.
|
|
126
|
+
# Sometimes they don't even have time to create the Control Masters that node2 has already failed.
|
|
127
|
+
with_control_master_create_optional: true,
|
|
128
|
+
with_control_master_destroy_optional: true
|
|
68
129
|
) + ssh_expected_commands_for(
|
|
69
130
|
{
|
|
70
131
|
'node2' => { connection: '192.168.42.2', user: 'test_user', control_master_create_error: 'Can\'t connect to 192.168.42.2' }
|
|
@@ -73,7 +134,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
73
134
|
)
|
|
74
135
|
) do
|
|
75
136
|
test_connector.ssh_user = 'test_user'
|
|
76
|
-
expect { test_connector.with_connection_to(%w[node1 node2 node3]) }.to raise_error(/^Error while starting SSH Control Master with .+\/ssh -o BatchMode=yes -o ControlMaster=yes -o ControlPersist=yes
|
|
137
|
+
expect { test_connector.with_connection_to(%w[node1 node2 node3]) }.to raise_error(/^Error while starting SSH Control Master with .+\/ssh -o BatchMode=yes -o ControlMaster=yes -o ControlPersist=yes hpc.node2 true: Can't connect to 192.168.42.2$/)
|
|
77
138
|
end
|
|
78
139
|
end
|
|
79
140
|
end
|
|
@@ -239,7 +300,8 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
239
300
|
) do
|
|
240
301
|
test_connector.ssh_use_control_master = false
|
|
241
302
|
test_connector.ssh_user = 'test_user'
|
|
242
|
-
test_connector.with_connection_to(['node']) do
|
|
303
|
+
test_connector.with_connection_to(['node']) do |connected_nodes|
|
|
304
|
+
expect(connected_nodes).to eq %w[node]
|
|
243
305
|
end
|
|
244
306
|
end
|
|
245
307
|
end
|
|
@@ -416,7 +478,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
416
478
|
['ssh -V 2>&1', proc { [0, "OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2u 20 Dec 2019\n", ''] }],
|
|
417
479
|
] +
|
|
418
480
|
[[
|
|
419
|
-
/^.+\/ssh -o BatchMode=yes -o ControlMaster=yes -o ControlPersist=yes
|
|
481
|
+
/^.+\/ssh -o BatchMode=yes -o ControlMaster=yes -o ControlPersist=yes hpc\.node true$/,
|
|
420
482
|
proc do
|
|
421
483
|
nbr_boot_messages += 1
|
|
422
484
|
[255, '', "System is booting up. See pam_nologin(8)\nAuthentication failed.\n"]
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb
CHANGED
|
@@ -35,8 +35,11 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
35
35
|
begin_marker = node.nil? ? /^Host \*$/ : /^# #{Regexp.escape(node)} - .+$/
|
|
36
36
|
start_idx = ssh_config_lines.index { |line| line =~ begin_marker }
|
|
37
37
|
return nil if start_idx.nil?
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
end_markers = [
|
|
39
|
+
/^\# \w+ - .+$/,
|
|
40
|
+
/^\#+$/
|
|
41
|
+
]
|
|
42
|
+
end_idx = ssh_config_lines[start_idx + 1..-1].index { |line| end_markers.any? { |end_marker| line =~ end_marker } }
|
|
40
43
|
end_idx = end_idx.nil? ? -1 : start_idx + end_idx
|
|
41
44
|
ssh_config_lines[start_idx..end_idx].select do |line|
|
|
42
45
|
stripped_line = line.strip
|
|
@@ -50,7 +53,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
50
53
|
expect(ssh_config_for(nil)).to eq <<~EOS
|
|
51
54
|
Host *
|
|
52
55
|
User test_user
|
|
53
|
-
ControlPath #{Dir.tmpdir}/hpc_ssh/
|
|
56
|
+
ControlPath #{Dir.tmpdir}/hpc_ssh/hpc_ssh_mux_%h_%p_%r
|
|
54
57
|
PubkeyAcceptedKeyTypes +ssh-dss
|
|
55
58
|
EOS
|
|
56
59
|
end
|
|
@@ -62,7 +65,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
62
65
|
expect(ssh_config_for(nil)).to eq <<~EOS
|
|
63
66
|
Host *
|
|
64
67
|
User test_user
|
|
65
|
-
ControlPath #{Dir.tmpdir}/hpc_ssh/
|
|
68
|
+
ControlPath #{Dir.tmpdir}/hpc_ssh/hpc_ssh_mux_%h_%p_%r
|
|
66
69
|
PubkeyAcceptedKeyTypes +ssh-dss
|
|
67
70
|
EOS
|
|
68
71
|
end
|
|
@@ -74,7 +77,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
74
77
|
expect(ssh_config_for(nil, known_hosts_file: '/path/to/known_hosts')).to eq <<~EOS
|
|
75
78
|
Host *
|
|
76
79
|
User test_user
|
|
77
|
-
ControlPath #{Dir.tmpdir}/hpc_ssh/
|
|
80
|
+
ControlPath #{Dir.tmpdir}/hpc_ssh/hpc_ssh_mux_%h_%p_%r
|
|
78
81
|
PubkeyAcceptedKeyTypes +ssh-dss
|
|
79
82
|
UserKnownHostsFile /path/to/known_hosts
|
|
80
83
|
EOS
|
|
@@ -88,7 +91,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
88
91
|
expect(ssh_config_for(nil)).to eq <<~EOS
|
|
89
92
|
Host *
|
|
90
93
|
User test_user
|
|
91
|
-
ControlPath #{Dir.tmpdir}/hpc_ssh/
|
|
94
|
+
ControlPath #{Dir.tmpdir}/hpc_ssh/hpc_ssh_mux_%h_%p_%r
|
|
92
95
|
PubkeyAcceptedKeyTypes +ssh-dss
|
|
93
96
|
StrictHostKeyChecking no
|
|
94
97
|
EOS
|
|
@@ -274,6 +277,47 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
274
277
|
end
|
|
275
278
|
end
|
|
276
279
|
|
|
280
|
+
it 'uses node transformed SSH connection' do
|
|
281
|
+
with_test_platform(
|
|
282
|
+
{ nodes: {
|
|
283
|
+
'node1' => { meta: { host_ip: '192.168.42.1', gateway: 'test_gateway1', gateway_user: 'test_gateway1_user' } },
|
|
284
|
+
'node2' => { meta: { host_ip: '192.168.42.2', gateway: 'test_gateway2', gateway_user: 'test_gateway2_user' } },
|
|
285
|
+
'node3' => { meta: { host_ip: '192.168.42.3', gateway: 'test_gateway3', gateway_user: 'test_gateway3_user' } }
|
|
286
|
+
} },
|
|
287
|
+
false,
|
|
288
|
+
'
|
|
289
|
+
for_nodes(%w[node1 node3]) do
|
|
290
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
291
|
+
["#{connection}_#{node}_13", "#{connection_user}_#{node}_13", "#{gateway}_#{node}_13", "#{gateway_user}_#{node}_13"]
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
for_nodes(\'node1\') do
|
|
295
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
296
|
+
["#{connection}_#{node}_1", "#{connection_user}_#{node}_1", "#{gateway}_#{node}_1", "#{gateway_user}_#{node}_1"]
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
') do
|
|
300
|
+
test_connector.ssh_user = 'test_user'
|
|
301
|
+
expect(ssh_config_for('node1')).to eq <<~EOS
|
|
302
|
+
Host hpc.node1
|
|
303
|
+
Hostname 192.168.42.1_node1_13_node1_1
|
|
304
|
+
User "test_user_node1_13_node1_1"
|
|
305
|
+
ProxyCommand ssh -q -W %h:%p test_gateway1_user_node1_13_node1_1@test_gateway1_node1_13_node1_1
|
|
306
|
+
EOS
|
|
307
|
+
expect(ssh_config_for('node2')).to eq <<~EOS
|
|
308
|
+
Host hpc.node2
|
|
309
|
+
Hostname 192.168.42.2
|
|
310
|
+
ProxyCommand ssh -q -W %h:%p test_gateway2_user@test_gateway2
|
|
311
|
+
EOS
|
|
312
|
+
expect(ssh_config_for('node3')).to eq <<~EOS
|
|
313
|
+
Host hpc.node3
|
|
314
|
+
Hostname 192.168.42.3_node3_13
|
|
315
|
+
User "test_user_node3_13"
|
|
316
|
+
ProxyCommand ssh -q -W %h:%p test_gateway3_user_node3_13@test_gateway3_node3_13
|
|
317
|
+
EOS
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
277
321
|
it 'generates a config compatible for passwords authentication' do
|
|
278
322
|
with_test_platform(nodes: { 'node' => { meta: { host_ip: '192.168.42.42' } } }) do
|
|
279
323
|
test_connector.passwords['node'] = 'PaSsWoRd'
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb
CHANGED
|
@@ -13,7 +13,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
13
13
|
|
|
14
14
|
it 'provides an SSH URL that can be used by other processes to connect to this node' do
|
|
15
15
|
with_test_platform_for_remote_testing do
|
|
16
|
-
expect(test_connector.ssh_url).to eq '
|
|
16
|
+
expect(test_connector.ssh_url).to eq 'hpc.node'
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb
CHANGED
|
@@ -6,7 +6,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
6
6
|
|
|
7
7
|
it 'executes bash commands remotely' do
|
|
8
8
|
with_test_platform_for_remote_testing(
|
|
9
|
-
expected_cmds: [[/.+\/ssh
|
|
9
|
+
expected_cmds: [[/.+\/ssh hpc\.node \/bin\/bash <<'EOF'\nbash_cmd.bash\nEOF/, proc { [0, 'Bash commands executed on node', ''] }]],
|
|
10
10
|
expected_stdout: 'Bash commands executed on node'
|
|
11
11
|
) do
|
|
12
12
|
test_connector.remote_bash('bash_cmd.bash')
|
|
@@ -17,7 +17,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
17
17
|
with_test_platform_for_remote_testing(
|
|
18
18
|
expected_cmds: [
|
|
19
19
|
[
|
|
20
|
-
/.+\/ssh
|
|
20
|
+
/.+\/ssh hpc\.node \/bin\/bash <<'EOF'\nbash_cmd.bash\nEOF/,
|
|
21
21
|
proc do |cmd, log_to_file: nil, log_to_stdout: true, log_stdout_to_io: nil, log_stderr_to_io: nil, expected_code: 0, timeout: nil, no_exception: false|
|
|
22
22
|
expect(timeout).to eq 5
|
|
23
23
|
[0, '', '']
|
|
@@ -33,7 +33,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
33
33
|
it 'executes interactive commands remotely' do
|
|
34
34
|
with_test_platform_for_remote_testing do
|
|
35
35
|
expect(test_connector).to receive(:system) do |cmd|
|
|
36
|
-
expect(cmd).to match /^.+\/ssh
|
|
36
|
+
expect(cmd).to match /^.+\/ssh hpc\.node$/
|
|
37
37
|
end
|
|
38
38
|
test_connector.remote_interactive
|
|
39
39
|
end
|
|
@@ -43,7 +43,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
43
43
|
with_test_platform_for_remote_testing(
|
|
44
44
|
expected_cmds: [
|
|
45
45
|
[
|
|
46
|
-
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+
|
|
46
|
+
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+hpc\.node\s+"tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
|
|
47
47
|
proc { [0, '', ''] }
|
|
48
48
|
]
|
|
49
49
|
]
|
|
@@ -56,7 +56,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
56
56
|
with_test_platform_for_remote_testing(
|
|
57
57
|
expected_cmds: [
|
|
58
58
|
[
|
|
59
|
-
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+
|
|
59
|
+
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+hpc\.node\s+"tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
|
|
60
60
|
proc do |cmd, log_to_file: nil, log_to_stdout: true, log_stdout_to_io: nil, log_stderr_to_io: nil, expected_code: 0, timeout: nil, no_exception: false|
|
|
61
61
|
expect(timeout).to eq 5
|
|
62
62
|
[0, '', '']
|
|
@@ -76,7 +76,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
76
76
|
[
|
|
77
77
|
/.+\/hpc_temp_cmds_.+\.sh$/,
|
|
78
78
|
proc do |received_cmd|
|
|
79
|
-
expect(File.read(received_cmd)).to match /.+\/ssh
|
|
79
|
+
expect(File.read(received_cmd)).to match /.+\/ssh hpc\.node \/bin\/bash <<'EOF'\n#{Regexp.escape(cmd)}\nEOF/
|
|
80
80
|
[0, 'Bash commands executed on node', '']
|
|
81
81
|
end
|
|
82
82
|
]
|
|
@@ -92,7 +92,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
92
92
|
with_test_platform_for_remote_testing(
|
|
93
93
|
expected_cmds: [
|
|
94
94
|
[
|
|
95
|
-
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+
|
|
95
|
+
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+hpc\.node\s+"sudo -u root tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
|
|
96
96
|
proc { [0, '', ''] }
|
|
97
97
|
]
|
|
98
98
|
]
|
|
@@ -105,7 +105,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
105
105
|
with_test_platform_for_remote_testing(
|
|
106
106
|
expected_cmds: [
|
|
107
107
|
[
|
|
108
|
-
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+
|
|
108
|
+
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+hpc\.node\s+"other_sudo --user root tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
|
|
109
109
|
proc { [0, '', ''] }
|
|
110
110
|
]
|
|
111
111
|
],
|
|
@@ -119,7 +119,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
119
119
|
with_test_platform_for_remote_testing(
|
|
120
120
|
expected_cmds: [
|
|
121
121
|
[
|
|
122
|
-
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+--owner remote_user\s+src.file \| \/.+\/ssh\s+
|
|
122
|
+
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+--owner remote_user\s+src.file \| \/.+\/ssh\s+hpc\.node\s+"tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
|
|
123
123
|
proc { [0, '', ''] }
|
|
124
124
|
]
|
|
125
125
|
]
|
|
@@ -132,7 +132,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
132
132
|
with_test_platform_for_remote_testing(
|
|
133
133
|
expected_cmds: [
|
|
134
134
|
[
|
|
135
|
-
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+--group remote_group\s+src.file \| \/.+\/ssh\s+
|
|
135
|
+
/cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+--group remote_group\s+src.file \| \/.+\/ssh\s+hpc\.node\s+"tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
|
|
136
136
|
proc { [0, '', ''] }
|
|
137
137
|
]
|
|
138
138
|
]
|
|
@@ -141,6 +141,30 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
141
141
|
end
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
it 'executes bash commands remotely without Session Exec capabilities' do
|
|
145
|
+
with_test_platform_for_remote_testing(
|
|
146
|
+
expected_cmds: [[/^\{ cat \| .+\/ssh hpc\.node -T; } <<'EOF'\nbash_cmd.bash\nEOF$/, proc { [0, 'Bash commands executed on node', ''] }]],
|
|
147
|
+
expected_stdout: 'Bash commands executed on node',
|
|
148
|
+
session_exec: false
|
|
149
|
+
) do
|
|
150
|
+
test_connector.remote_bash('bash_cmd.bash')
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it 'copies files remotely without Session Exec capabilities' do
|
|
155
|
+
with_test_platform_for_remote_testing(
|
|
156
|
+
expected_cmds: [
|
|
157
|
+
[
|
|
158
|
+
/^scp -S .+\/ssh \/path\/to\/src.file hpc\.node:\/remote_path\/to\/dst.dir$/,
|
|
159
|
+
proc { [0, '', ''] }
|
|
160
|
+
]
|
|
161
|
+
],
|
|
162
|
+
session_exec: false
|
|
163
|
+
) do
|
|
164
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir')
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
144
168
|
end
|
|
145
169
|
|
|
146
170
|
end
|
|
@@ -17,8 +17,8 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
17
17
|
block.call
|
|
18
18
|
end
|
|
19
19
|
provisioner = nil
|
|
20
|
-
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |
|
|
21
|
-
expect(
|
|
20
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
21
|
+
expect(sub_test_deployer.local_environment).to eq true
|
|
22
22
|
provisioner = test_instance
|
|
23
23
|
expect(test_instance.node).to eq 'node'
|
|
24
24
|
expect(test_instance.environment).to match /^#{Regexp.escape(`whoami`.strip)}_hpc_testing_provisioner_\d+_\d+_\w+$/
|
|
@@ -40,8 +40,8 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
40
40
|
block.call
|
|
41
41
|
end
|
|
42
42
|
provisioner = nil
|
|
43
|
-
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |
|
|
44
|
-
expect(
|
|
43
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
44
|
+
expect(sub_test_deployer.local_environment).to eq true
|
|
45
45
|
provisioner = test_instance
|
|
46
46
|
expect(test_instance.node).to eq 'node'
|
|
47
47
|
expect(test_instance.environment).to match /^#{Regexp.escape(`whoami`.strip)}_hpc_testing_provisioner_\d+_\d+_\w+$/
|
|
@@ -50,6 +50,70 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
it 'gives a new test instance ready to be used in place of the node without SSH transformations' do
|
|
54
|
+
with_test_platform(
|
|
55
|
+
{
|
|
56
|
+
nodes: {
|
|
57
|
+
'node1' => { meta: { host_ip: '192.168.42.1', ssh_session_exec: 'false' } },
|
|
58
|
+
'node2' => { meta: { host_ip: '192.168.42.2', ssh_session_exec: 'false' } }
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
false,
|
|
62
|
+
'
|
|
63
|
+
for_nodes(%w[node1 node2]) do
|
|
64
|
+
transform_ssh_connection do |node, connection, connection_user, gateway, gateway_user|
|
|
65
|
+
["#{connection}_#{node}", "#{connection_user}_#{node}", "#{gateway}_#{node}", "#{gateway_user}_#{node}"]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
'
|
|
69
|
+
) do |repository|
|
|
70
|
+
register_plugins(:provisioner, { test_provisioner: HybridPlatformsConductorTest::TestProvisioner })
|
|
71
|
+
File.write("#{test_config.hybrid_platforms_dir}/dummy_secrets.json", '{}')
|
|
72
|
+
HybridPlatformsConductorTest::TestProvisioner.mocked_states = %i[created created running exited]
|
|
73
|
+
HybridPlatformsConductorTest::TestProvisioner.mocked_ip = '172.17.0.1'
|
|
74
|
+
expect(Socket).to receive(:tcp).with('172.17.0.1', 22, { connect_timeout: 1 }) do |&block|
|
|
75
|
+
block.call
|
|
76
|
+
end
|
|
77
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node1', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
78
|
+
expect(sub_test_deployer.instance_eval { @nodes_handler.get_ssh_session_exec_of('node1') }).to eq 'true'
|
|
79
|
+
expect(sub_test_deployer.instance_eval { @nodes_handler.get_ssh_session_exec_of('node2') }).to eq 'false'
|
|
80
|
+
ssh_transforms = test_instance.instance_eval { @config.ssh_connection_transforms }
|
|
81
|
+
expect(ssh_transforms.size).to eq 1
|
|
82
|
+
expect(ssh_transforms[0][:nodes_selectors_stack]).to eq [%w[node2]]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'gives a new test instance ready to be used in place of the node without sudo specificities' do
|
|
88
|
+
with_test_platform(
|
|
89
|
+
{
|
|
90
|
+
nodes: {
|
|
91
|
+
'node1' => { meta: { host_ip: '192.168.42.1' } },
|
|
92
|
+
'node2' => { meta: { host_ip: '192.168.42.2' } }
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
false,
|
|
96
|
+
'
|
|
97
|
+
for_nodes(%w[node1 node2]) do
|
|
98
|
+
sudo_for { |user| "other_sudo --user #{user}" }
|
|
99
|
+
end
|
|
100
|
+
'
|
|
101
|
+
) do |repository|
|
|
102
|
+
register_plugins(:provisioner, { test_provisioner: HybridPlatformsConductorTest::TestProvisioner })
|
|
103
|
+
File.write("#{test_config.hybrid_platforms_dir}/dummy_secrets.json", '{}')
|
|
104
|
+
HybridPlatformsConductorTest::TestProvisioner.mocked_states = %i[created created running exited]
|
|
105
|
+
HybridPlatformsConductorTest::TestProvisioner.mocked_ip = '172.17.0.1'
|
|
106
|
+
expect(Socket).to receive(:tcp).with('172.17.0.1', 22, { connect_timeout: 1 }) do |&block|
|
|
107
|
+
block.call
|
|
108
|
+
end
|
|
109
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node1', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
110
|
+
sudo_procs = test_instance.instance_eval { @config.sudo_procs }
|
|
111
|
+
expect(sudo_procs.size).to eq 1
|
|
112
|
+
expect(sudo_procs[0][:nodes_selectors_stack]).to eq [%w[node2]]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
53
117
|
it 'does not destroy instances when asked to reuse' do
|
|
54
118
|
with_test_platform(
|
|
55
119
|
nodes: { 'node' => { meta: { host_ip: '192.168.42.42' } } }
|
|
@@ -62,8 +126,8 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
62
126
|
block.call
|
|
63
127
|
end
|
|
64
128
|
provisioner = nil
|
|
65
|
-
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner', reuse_instance: true) do |
|
|
66
|
-
expect(
|
|
129
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner', reuse_instance: true) do |sub_test_deployer, test_instance|
|
|
130
|
+
expect(sub_test_deployer.local_environment).to eq true
|
|
67
131
|
provisioner = test_instance
|
|
68
132
|
expect(test_instance.node).to eq 'node'
|
|
69
133
|
expect(test_instance.environment).to eq "#{`whoami`.strip}_hpc_testing_provisioner"
|
|
@@ -84,8 +148,8 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
84
148
|
block.call
|
|
85
149
|
end
|
|
86
150
|
provisioner = nil
|
|
87
|
-
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner', reuse_instance: true) do |
|
|
88
|
-
expect(
|
|
151
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner', reuse_instance: true) do |sub_test_deployer, test_instance|
|
|
152
|
+
expect(sub_test_deployer.local_environment).to eq true
|
|
89
153
|
provisioner = test_instance
|
|
90
154
|
expect(test_instance.node).to eq 'node'
|
|
91
155
|
expect(test_instance.environment).to eq "#{`whoami`.strip}_hpc_testing_provisioner"
|
|
@@ -102,7 +166,7 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
102
166
|
File.write("#{test_config.hybrid_platforms_dir}/dummy_secrets.json", '{}')
|
|
103
167
|
HybridPlatformsConductorTest::TestProvisioner.mocked_states = %i[created created created exited exited]
|
|
104
168
|
expect do
|
|
105
|
-
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |
|
|
169
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
106
170
|
end
|
|
107
171
|
end.to raise_error /\[ node\/#{Regexp.escape(`whoami`.strip)}_hpc_testing_provisioner_\d+_\d+_\w+ \] - Instance fails to be in a state among \(running\) with timeout 1\. Currently in state exited/
|
|
108
172
|
end
|
|
@@ -120,7 +184,7 @@ describe HybridPlatformsConductor::Deployer do
|
|
|
120
184
|
raise Errno::ETIMEDOUT, 'Timeout while reading from port 22'
|
|
121
185
|
end
|
|
122
186
|
expect do
|
|
123
|
-
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |
|
|
187
|
+
test_deployer.with_test_provisioned_instance(:test_provisioner, 'node', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
|
|
124
188
|
end
|
|
125
189
|
end.to raise_error /\[ node\/#{Regexp.escape(`whoami`.strip)}_hpc_testing_provisioner_\d+_\d+_\w+ \] - Instance fails to have port 22 opened with timeout 1\./
|
|
126
190
|
end
|