hybrid_platforms_conductor 32.7.2 → 32.7.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hybrid_platforms_conductor/deployer.rb +12 -1
- 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/connections_spec.rb +2 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +74 -10
- data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +5 -1
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +4 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83352b7821e41bc5b0282c693c47f0cac0f5a9915a45dfa37affd3d1fcaadd8c
|
4
|
+
data.tar.gz: fba8bf35c2569716b2b8f934a46684c8b29843e50fe49b8133d3eeae580938d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69c667f1f6c626372ecef7c21c9afdb2865a38e418ad6add2ec4d04d9a0eeda6892fed168d546d89d8805d843c31945eb885d53b0cf5208a65a7eb89ba75ea74
|
7
|
+
data.tar.gz: b9478d38660f80b7c9f62411d72d0e890e74ec509973ceb3d417721d21f5f9923ffc5dfbc96b857af6301d7bd708630638d393dc3bbf2abcd4cf7d12e22a7af6
|
@@ -311,13 +311,24 @@ module HybridPlatformsConductor
|
|
311
311
|
environment: environment,
|
312
312
|
logger: @logger,
|
313
313
|
logger_stderr: @logger_stderr,
|
314
|
-
config:
|
314
|
+
config: sub_executable.config,
|
315
315
|
cmd_runner: @cmd_runner,
|
316
316
|
# Here we use the NodesHandler that will be bound to the sub-Deployer only, as the node's metadata might be modified by the Provisioner.
|
317
317
|
nodes_handler: sub_executable.nodes_handler,
|
318
318
|
actions_executor: @actions_executor
|
319
319
|
)
|
320
320
|
instance.with_running_instance(stop_on_exit: true, destroy_on_exit: !reuse_instance, port: 22) do
|
321
|
+
# Test-provisioned nodes have SSH Session Exec capabilities
|
322
|
+
sub_executable.nodes_handler.override_metadata_of node, :ssh_session_exec, 'true'
|
323
|
+
# Test-provisioned nodes use default sudo
|
324
|
+
sub_executable.config.sudo_procs.replace(sub_executable.config.sudo_procs.map do |sudo_proc_info|
|
325
|
+
{
|
326
|
+
nodes_selectors_stack: sudo_proc_info[:nodes_selectors_stack].map do |nodes_selector|
|
327
|
+
@nodes_handler.select_nodes(nodes_selector).select { |selected_node| selected_node != node }
|
328
|
+
end,
|
329
|
+
sudo_proc: sudo_proc_info[:sudo_proc]
|
330
|
+
}
|
331
|
+
end)
|
321
332
|
actions_executor = sub_executable.actions_executor
|
322
333
|
deployer = sub_executable.deployer
|
323
334
|
# Setup test environment for this container
|
@@ -54,17 +54,19 @@ module HybridPlatformsConductor
|
|
54
54
|
instance.stop
|
55
55
|
instance.with_running_instance(port: 22) do
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
unless @nodes_handler.get_root_access_allowed_of(@node) == 'true'
|
58
|
+
# ===== Deploy removes root access
|
59
|
+
# Check that we can't connect with root
|
60
|
+
ssh_ok = false
|
61
|
+
begin
|
62
|
+
Net::SSH.start(instance.ip, 'root', password: 'root_pwd', auth_methods: ['password'], verify_host_key: :never) do |ssh|
|
63
|
+
ssh_ok = ssh.exec!('echo Works').strip == 'Works'
|
64
|
+
end
|
65
|
+
rescue
|
63
66
|
end
|
64
|
-
|
67
|
+
assert_equal ssh_ok, false, 'Root can still connect on the image after deployment'
|
68
|
+
# Even if we can connect using root, run the idempotence test
|
65
69
|
end
|
66
|
-
assert_equal ssh_ok, false, 'Root can still connect on the image after deployment'
|
67
|
-
# Even if we can connect using root, run the idempotence test
|
68
70
|
|
69
71
|
# ===== Idempotence
|
70
72
|
unless ssh_ok
|
@@ -76,6 +76,15 @@ module HybridPlatformsConductor
|
|
76
76
|
# Make sure we update it.
|
77
77
|
@nodes_handler.override_metadata_of @node, :host_ip, instance_ip
|
78
78
|
@nodes_handler.invalidate_metadata_of @node, :host_keys
|
79
|
+
# Make sure the SSH transformations don't apply to this node
|
80
|
+
@config.ssh_connection_transforms.replace(@config.ssh_connection_transforms.map do |ssh_transform_info|
|
81
|
+
{
|
82
|
+
nodes_selectors_stack: ssh_transform_info[:nodes_selectors_stack].map do |nodes_selector|
|
83
|
+
@nodes_handler.select_nodes(nodes_selector).select { |selected_node| selected_node != @node }
|
84
|
+
end,
|
85
|
+
transform: ssh_transform_info[:transform]
|
86
|
+
}
|
87
|
+
end)
|
79
88
|
end
|
80
89
|
wait_for_port!(port) if port
|
81
90
|
yield
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb
CHANGED
@@ -123,6 +123,8 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
123
123
|
'node3' => { connection: '192.168.42.3', user: 'test_user' }
|
124
124
|
},
|
125
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,
|
126
128
|
with_control_master_destroy_optional: true
|
127
129
|
) + ssh_expected_commands_for(
|
128
130
|
{
|
@@ -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
|
@@ -89,7 +89,11 @@ module HybridPlatformsConductorTest
|
|
89
89
|
remaining_expected_commands.select do |(_expected_command, _command_code, options)|
|
90
90
|
!options[:optional]
|
91
91
|
end
|
92
|
-
).to eq([]), "Expected CmdRunner commands were not run:\n#{
|
92
|
+
).to eq([]), "Expected CmdRunner commands were not run:\n#{
|
93
|
+
remaining_expected_commands.map do |(expected_command, _command_code, options)|
|
94
|
+
"#{options[:optional] ? '[Optional] ' : ''}#{expected_command}"
|
95
|
+
end.join("\n")
|
96
|
+
}"
|
93
97
|
# Un-mock the command runner
|
94
98
|
allow(cmd_runner).to receive(:run_cmd).and_call_original
|
95
99
|
end
|
@@ -15,6 +15,7 @@ module HybridPlatformsConductorTest
|
|
15
15
|
# * *times* (Integer): Number of times this connection should be used [default: 1]
|
16
16
|
# * *control_master_create_error* (String or nil): Error to simulate during the SSH ControlMaster creation, or nil for none [default: nil]
|
17
17
|
# * *with_control_master_create* (Boolean): Do we create the control master? [default: true]
|
18
|
+
# * *with_control_master_create_optional* (Boolean): If true, then consider the ControlMaster creation to be optional [default: false]
|
18
19
|
# * *with_control_master_check* (Boolean): Do we check the control master? [default: false]
|
19
20
|
# * *with_control_master_destroy* (Boolean): Do we destroy the control master? [default: true]
|
20
21
|
# * *with_control_master_destroy_optional* (Boolean): If true, then consider the ControlMaster destruction to be optional [default: false]
|
@@ -26,6 +27,7 @@ module HybridPlatformsConductorTest
|
|
26
27
|
def ssh_expected_commands_for(
|
27
28
|
nodes_connections,
|
28
29
|
with_control_master_create: true,
|
30
|
+
with_control_master_create_optional: false,
|
29
31
|
with_control_master_check: false,
|
30
32
|
with_control_master_destroy: true,
|
31
33
|
with_control_master_destroy_optional: false,
|
@@ -78,7 +80,8 @@ module HybridPlatformsConductorTest
|
|
78
80
|
else
|
79
81
|
[255, '', node_connection_info[:control_master_create_error]]
|
80
82
|
end
|
81
|
-
end
|
83
|
+
end,
|
84
|
+
{ optional: with_control_master_create_optional }
|
82
85
|
]
|
83
86
|
end
|
84
87
|
if with_control_master_check
|