hybrid_platforms_conductor 32.3.6 → 32.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/nodes_to_deploy +11 -5
- data/lib/hybrid_platforms_conductor/deployer.rb +33 -12
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +82 -28
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +6 -7
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +7 -6
- data/lib/hybrid_platforms_conductor/nodes_handler.rb +45 -1
- data/lib/hybrid_platforms_conductor/services_handler.rb +9 -13
- 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 +41 -2
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +68 -12
- 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 +23 -9
- data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +15 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/config_dsl_spec.rb +71 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +10 -0
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +25 -0
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +17 -7
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +14 -14
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +137 -33
- data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +2 -2
- metadata +13 -11
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
|
]
|
|
@@ -101,11 +101,25 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
+
it 'copies files remotely with a different sudo' do
|
|
105
|
+
with_test_platform_for_remote_testing(
|
|
106
|
+
expected_cmds: [
|
|
107
|
+
[
|
|
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
|
+
proc { [0, '', ''] }
|
|
110
|
+
]
|
|
111
|
+
],
|
|
112
|
+
additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
|
|
113
|
+
) do
|
|
114
|
+
test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
104
118
|
it 'copies files remotely with a different owner' do
|
|
105
119
|
with_test_platform_for_remote_testing(
|
|
106
120
|
expected_cmds: [
|
|
107
121
|
[
|
|
108
|
-
/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+"/,
|
|
109
123
|
proc { [0, '', ''] }
|
|
110
124
|
]
|
|
111
125
|
]
|
|
@@ -118,7 +132,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
|
118
132
|
with_test_platform_for_remote_testing(
|
|
119
133
|
expected_cmds: [
|
|
120
134
|
[
|
|
121
|
-
/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+"/,
|
|
122
136
|
proc { [0, '', ''] }
|
|
123
137
|
]
|
|
124
138
|
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
describe HybridPlatformsConductor::Deployer do
|
|
2
|
+
|
|
3
|
+
context 'checking deployer specific config DSL' do
|
|
4
|
+
|
|
5
|
+
it 'declares a packaging timeout' do
|
|
6
|
+
with_repository do |repository|
|
|
7
|
+
with_platforms('packaging_timeout 666') do
|
|
8
|
+
expect(test_config.packaging_timeout_secs).to eq 666
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
@@ -124,4 +124,32 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
124
124
|
end
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
+
it 'computes the correct sudo for different nodes' do
|
|
128
|
+
with_test_platform(
|
|
129
|
+
{
|
|
130
|
+
nodes: {
|
|
131
|
+
'node1' => {},
|
|
132
|
+
'node2' => {},
|
|
133
|
+
'node3' => {}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
false,
|
|
137
|
+
'
|
|
138
|
+
for_nodes(%w[node1 node2]) do
|
|
139
|
+
sudo_for { |user| "alt_sudo1 -p #{user}" }
|
|
140
|
+
end
|
|
141
|
+
for_nodes(\'node2\') do
|
|
142
|
+
sudo_for { |user| "alt_sudo2 -q #{user}" }
|
|
143
|
+
end
|
|
144
|
+
'
|
|
145
|
+
) do
|
|
146
|
+
expect(test_nodes_handler.sudo_on('node1')).to eq 'alt_sudo1 -p root'
|
|
147
|
+
expect(test_nodes_handler.sudo_on('node1', 'test_user')).to eq 'alt_sudo1 -p test_user'
|
|
148
|
+
expect(test_nodes_handler.sudo_on('node2')).to eq 'alt_sudo2 -q root'
|
|
149
|
+
expect(test_nodes_handler.sudo_on('node2', 'test_user')).to eq 'alt_sudo2 -q test_user'
|
|
150
|
+
expect(test_nodes_handler.sudo_on('node3')).to eq 'sudo -u root'
|
|
151
|
+
expect(test_nodes_handler.sudo_on('node3', 'test_user')).to eq 'sudo -u test_user'
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
127
155
|
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
describe HybridPlatformsConductor::NodesHandler do
|
|
2
|
+
|
|
3
|
+
context 'checking config DSL' do
|
|
4
|
+
|
|
5
|
+
it 'adds helpers for master cmdbs' do
|
|
6
|
+
with_test_platform(
|
|
7
|
+
{
|
|
8
|
+
nodes: {
|
|
9
|
+
'node1' => {},
|
|
10
|
+
'node2' => {},
|
|
11
|
+
'node3' => {}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
false,
|
|
15
|
+
'
|
|
16
|
+
master_cmdbs(
|
|
17
|
+
test_cmdb: :property1,
|
|
18
|
+
test_cmdb2: :property2
|
|
19
|
+
)
|
|
20
|
+
for_nodes(\'node2\') do
|
|
21
|
+
master_cmdbs(test_cmdb: :property3)
|
|
22
|
+
end
|
|
23
|
+
'
|
|
24
|
+
) do
|
|
25
|
+
register_test_cmdb(%i[test_cmdb test_cmdb2])
|
|
26
|
+
expect(test_config.cmdb_masters).to eq [
|
|
27
|
+
{
|
|
28
|
+
nodes_selectors_stack: [],
|
|
29
|
+
cmdb_masters: {
|
|
30
|
+
test_cmdb: [:property1],
|
|
31
|
+
test_cmdb2: [:property2]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
nodes_selectors_stack: ['node2'],
|
|
36
|
+
cmdb_masters: {
|
|
37
|
+
test_cmdb: [:property3]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it 'adds helpers for configurable sudo' do
|
|
45
|
+
with_test_platform(
|
|
46
|
+
{
|
|
47
|
+
nodes: {
|
|
48
|
+
'node1' => {},
|
|
49
|
+
'node2' => {},
|
|
50
|
+
'node3' => {}
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
false,
|
|
54
|
+
'
|
|
55
|
+
sudo_for { |user| "alt_sudo1 -p #{user}" }
|
|
56
|
+
for_nodes(\'node2\') do
|
|
57
|
+
sudo_for { |user| "alt_sudo2 -q #{user}" }
|
|
58
|
+
end
|
|
59
|
+
'
|
|
60
|
+
) do
|
|
61
|
+
expect(test_config.sudo_procs.size).to eq 2
|
|
62
|
+
expect(test_config.sudo_procs[0][:nodes_selectors_stack]).to eq []
|
|
63
|
+
expect(test_config.sudo_procs[0][:sudo_proc].call('test_user')).to eq 'alt_sudo1 -p test_user'
|
|
64
|
+
expect(test_config.sudo_procs[1][:nodes_selectors_stack]).to eq ['node2']
|
|
65
|
+
expect(test_config.sudo_procs[1][:sudo_proc].call('test_user')).to eq 'alt_sudo2 -q test_user'
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
end
|
|
@@ -33,6 +33,16 @@ describe HybridPlatformsConductor::NodesHandler do
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
it 'fails when the commit id is invalid' do
|
|
37
|
+
with_test_platform({}, true) do
|
|
38
|
+
with_cmd_runner_mocked([
|
|
39
|
+
[/cd .+\/my_remote_platform && git --no-pager diff --no-color invalid_id/, proc { raise HybridPlatformsConductor::CmdRunner::UnexpectedExitCodeError, 'Mocked git error due to an invalid commit id' }]
|
|
40
|
+
]) do
|
|
41
|
+
expect { test_nodes_handler.impacted_nodes_from_git_diff('my_remote_platform', from_commit: 'invalid_id') }.to raise_error HybridPlatformsConductor::NodesHandler::GitError, 'Mocked git error due to an invalid commit id'
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
36
46
|
it 'diffs to another commit if asked' do
|
|
37
47
|
with_test_platform({}, true) do
|
|
38
48
|
with_cmd_runner_mocked([
|
|
@@ -106,6 +106,31 @@ describe 'nodes_to_deploy executable' do
|
|
|
106
106
|
end
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
it 'considers nodes having invalid commit ids in their logs to be deployed' do
|
|
110
|
+
with_test_platform_for_nodes_to_deploy do
|
|
111
|
+
expect_actions_executor_runs([proc do |actions|
|
|
112
|
+
expect(actions).to eq(
|
|
113
|
+
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
114
|
+
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
115
|
+
)
|
|
116
|
+
{
|
|
117
|
+
'node1' => [0, "repo_name_0: platform\nexit_status: 0\ncommit_id_0: abcdef1", ''],
|
|
118
|
+
'node2' => [0, "repo_name_0: platform\nexit_status: 0\ncommit_id_0: abcdef2", '']
|
|
119
|
+
}
|
|
120
|
+
end])
|
|
121
|
+
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') do
|
|
122
|
+
raise HybridPlatformsConductor::NodesHandler::GitError, 'Mocked git error due to an invalid commit id'
|
|
123
|
+
end
|
|
124
|
+
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[], [], [], false] }
|
|
125
|
+
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
126
|
+
expect(exit_code).to eq 0
|
|
127
|
+
expect(stdout).to eq <<~EOS
|
|
128
|
+
===== Nodes to deploy =====
|
|
129
|
+
node1
|
|
130
|
+
EOS
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
109
134
|
it 'ignores impacts if asked' do
|
|
110
135
|
with_test_platform_for_nodes_to_deploy do
|
|
111
136
|
exit_code, stdout, stderr = run 'nodes_to_deploy', '--ignore-deployed-info'
|
|
@@ -10,6 +10,7 @@ module HybridPlatformsConductorTest
|
|
|
10
10
|
# Parameters::
|
|
11
11
|
# * *nodes_connections* (Hash<String, Hash<Symbol,Object> >): Nodes' connections info, per node name:
|
|
12
12
|
# * *connection* (String): Connection string (fqdn, IP...) used by SSH
|
|
13
|
+
# * *ip* (String): IP used by SSH (can be different from connection in case of transformed SSH) [default: connection]
|
|
13
14
|
# * *user* (String): User used by SSH
|
|
14
15
|
# * *times* (Integer): Number of times this connection should be used [default: 1]
|
|
15
16
|
# * *control_master_create_error* (String or nil): Error to simulate during the SSH ControlMaster creation, or nil for none [default: nil]
|
|
@@ -33,16 +34,17 @@ module HybridPlatformsConductorTest
|
|
|
33
34
|
ssh_commands_once = []
|
|
34
35
|
ssh_commands_per_connection = []
|
|
35
36
|
if with_strict_host_key_checking
|
|
37
|
+
ip = node_connection_info[:ip] || node_connection_info[:connection]
|
|
36
38
|
ssh_commands_once.concat([
|
|
37
39
|
[
|
|
38
|
-
"ssh-keyscan #{
|
|
39
|
-
proc { [0, "#{
|
|
40
|
+
"ssh-keyscan #{ip}",
|
|
41
|
+
proc { [0, "#{ip} ssh-rsa fake_host_key_for_#{ip}", ''] }
|
|
40
42
|
]
|
|
41
43
|
])
|
|
42
44
|
end
|
|
43
45
|
if with_control_master_create
|
|
44
46
|
ssh_commands_per_connection << [
|
|
45
|
-
/^.+\/ssh #{with_batch_mode ? '-o BatchMode=yes ' : ''}-o ControlMaster=yes -o ControlPersist=yes
|
|
47
|
+
/^.+\/ssh #{with_batch_mode ? '-o BatchMode=yes ' : ''}-o ControlMaster=yes -o ControlPersist=yes hpc\.#{Regexp.escape(node)} true$/,
|
|
46
48
|
proc do
|
|
47
49
|
control_file = test_actions_executor.connector(:ssh).send(:control_master_file, node_connection_info[:connection], '22', node_connection_info[:user])
|
|
48
50
|
# Fail if the ControlMaster file already exists, as would SSH do if the file is stalled
|
|
@@ -60,13 +62,13 @@ module HybridPlatformsConductorTest
|
|
|
60
62
|
end
|
|
61
63
|
if with_control_master_check
|
|
62
64
|
ssh_commands_per_connection << [
|
|
63
|
-
/^.+\/ssh -O check
|
|
65
|
+
/^.+\/ssh -O check hpc\.#{Regexp.escape(node)}$/,
|
|
64
66
|
proc { [0, '', ''] }
|
|
65
67
|
]
|
|
66
68
|
end
|
|
67
69
|
if with_control_master_destroy
|
|
68
70
|
ssh_commands_per_connection << [
|
|
69
|
-
/^.+\/ssh -O exit
|
|
71
|
+
/^.+\/ssh -O exit hpc\.#{Regexp.escape(node)} 2>&1 \| grep -v 'Exit request sent\.'$/,
|
|
70
72
|
proc do
|
|
71
73
|
# Really mock the control file deletion
|
|
72
74
|
File.unlink(test_actions_executor.connector(:ssh).send(:control_master_file, node_connection_info[:connection], '22', node_connection_info[:user]))
|
|
@@ -94,9 +96,17 @@ module HybridPlatformsConductorTest
|
|
|
94
96
|
# * *expected_stderr* (String): Expected stderr after client code execution [default: '']
|
|
95
97
|
# * *timeout* (Integer or nil): Timeout to prepare the connector for [default: nil]
|
|
96
98
|
# * *password* (String or nil): Password to set for the node, or nil for none [default: nil]
|
|
99
|
+
# * *additional_config* (String): Additional config [default: '']
|
|
97
100
|
# * Proc: Client code to execute testing
|
|
98
|
-
def with_test_platform_for_remote_testing(
|
|
99
|
-
|
|
101
|
+
def with_test_platform_for_remote_testing(
|
|
102
|
+
expected_cmds: [],
|
|
103
|
+
expected_stdout: '',
|
|
104
|
+
expected_stderr: '',
|
|
105
|
+
timeout: nil,
|
|
106
|
+
password: nil,
|
|
107
|
+
additional_config: ''
|
|
108
|
+
)
|
|
109
|
+
with_test_platform({ nodes: { 'node' => { meta: { host_ip: '192.168.42.42' } } } }, false, additional_config) do
|
|
100
110
|
with_cmd_runner_mocked(
|
|
101
111
|
[
|
|
102
112
|
['which env', proc { [0, "/usr/bin/env\n", ''] }],
|
|
@@ -9,12 +9,12 @@ module HybridPlatformsConductorTest
|
|
|
9
9
|
# Parameters::
|
|
10
10
|
# * *action* (Hash<Symbol,Object>): The action to check
|
|
11
11
|
# * *node* (String): The concerned node
|
|
12
|
-
# * *sudo* (
|
|
13
|
-
def expect_action_to_lock_node(action, node, sudo:
|
|
12
|
+
# * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
|
|
13
|
+
def expect_action_to_lock_node(action, node, sudo: 'sudo -u root')
|
|
14
14
|
expect(action[:scp].size).to eq 1
|
|
15
15
|
expect(action[:scp].first[0]).to match /^.+\/mutex_dir$/
|
|
16
16
|
expect(action[:scp].first[1]).to eq '.'
|
|
17
|
-
expect(action[:remote_bash]).to eq "while ! #{sudo ?
|
|
17
|
+
expect(action[:remote_bash]).to eq "while ! #{sudo ? "#{sudo} " : ''}./mutex_dir lock /tmp/hybrid_platforms_conductor_deploy_lock \"$(ps -o ppid= -p $$)\"; do echo -e 'Another deployment is running on #{node}. Waiting for it to finish to continue...' ; sleep 5 ; done"
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# Expect a given action to be releasing the mutex on a given node
|
|
@@ -22,9 +22,9 @@ module HybridPlatformsConductorTest
|
|
|
22
22
|
# Parameters::
|
|
23
23
|
# * *action* (Hash<Symbol,Object>): The action to check
|
|
24
24
|
# * *node* (String): The concerned node
|
|
25
|
-
# * *sudo* (
|
|
26
|
-
def expect_action_to_unlock_node(action, node, sudo:
|
|
27
|
-
expect(action).to eq(remote_bash: "#{sudo ?
|
|
25
|
+
# * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
|
|
26
|
+
def expect_action_to_unlock_node(action, node, sudo: 'sudo -u root')
|
|
27
|
+
expect(action).to eq(remote_bash: "#{sudo ? "#{sudo} " : ''}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock")
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# Expect a given set of actions to be a deployment
|
|
@@ -33,12 +33,12 @@ module HybridPlatformsConductorTest
|
|
|
33
33
|
# * *actions* (Object): Actions
|
|
34
34
|
# * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
|
|
35
35
|
# * *check* (Boolean): Is the deploy only a check? [default: false]
|
|
36
|
-
# * *sudo* (
|
|
36
|
+
# * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
|
|
37
37
|
# * *expected_actions* (Array<Object>): Additional expected actions [default: []]
|
|
38
38
|
# * *mocked_result* (Hash<String, [Object, String, String]>): Expected result of the actions, per node, or nil for success [default: nil]
|
|
39
39
|
# Result::
|
|
40
40
|
# * Hash<String, [Integer or Symbol, String, String] >: Expected result of those expected actions
|
|
41
|
-
def expect_actions_to_deploy_on(actions, nodes, check: false, sudo:
|
|
41
|
+
def expect_actions_to_deploy_on(actions, nodes, check: false, sudo: 'sudo -u root', expected_actions: [], mocked_result: nil)
|
|
42
42
|
nodes = [nodes] if nodes.is_a?(String)
|
|
43
43
|
mocked_result = Hash[nodes.map { |node| [node, [0, "#{check ? 'Check' : 'Deploy'} successful", '']] }] if mocked_result.nil?
|
|
44
44
|
expect(actions.size).to eq nodes.size
|
|
@@ -57,8 +57,8 @@ module HybridPlatformsConductorTest
|
|
|
57
57
|
# Parameters::
|
|
58
58
|
# * *actions* (Object): Actions
|
|
59
59
|
# * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
|
|
60
|
-
# * *sudo* (
|
|
61
|
-
def expect_actions_to_unlock(actions, nodes, sudo:
|
|
60
|
+
# * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
|
|
61
|
+
def expect_actions_to_unlock(actions, nodes, sudo: 'sudo -u root')
|
|
62
62
|
nodes = [nodes] if nodes.is_a?(String)
|
|
63
63
|
expect(actions.size).to eq nodes.size
|
|
64
64
|
nodes.each do |node|
|
|
@@ -73,17 +73,17 @@ module HybridPlatformsConductorTest
|
|
|
73
73
|
# Parameters::
|
|
74
74
|
# * *actions* (Object): Actions
|
|
75
75
|
# * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
|
|
76
|
-
# * *sudo* (
|
|
77
|
-
def expect_actions_to_upload_logs(actions, nodes, sudo:
|
|
76
|
+
# * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
|
|
77
|
+
def expect_actions_to_upload_logs(actions, nodes, sudo: 'sudo -u root')
|
|
78
78
|
nodes = [nodes] if nodes.is_a?(String)
|
|
79
79
|
expect(actions.size).to eq nodes.size
|
|
80
80
|
nodes.each do |node|
|
|
81
81
|
expect(actions.key?(node)).to eq true
|
|
82
|
-
expect(actions[node][:remote_bash]).to eq "#{sudo ?
|
|
82
|
+
expect(actions[node][:remote_bash]).to eq "#{sudo ? "#{sudo} " : ''}mkdir -p /var/log/deployments"
|
|
83
83
|
expect(actions[node][:scp].first[1]).to eq '/var/log/deployments'
|
|
84
84
|
expect(actions[node][:scp][:group]).to eq 'root'
|
|
85
85
|
expect(actions[node][:scp][:owner]).to eq 'root'
|
|
86
|
-
expect(actions[node][:scp][:sudo]).to eq sudo
|
|
86
|
+
expect(actions[node][:scp][:sudo]).to eq (!sudo.nil?)
|
|
87
87
|
end
|
|
88
88
|
Hash[nodes.map { |node| [node, [0, 'Logs uploaded', '']] }]
|
|
89
89
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'timeout'
|
|
2
|
+
|
|
1
3
|
module HybridPlatformsConductorTest
|
|
2
4
|
|
|
3
5
|
module Helpers
|
|
@@ -18,7 +20,7 @@ module HybridPlatformsConductorTest
|
|
|
18
20
|
#
|
|
19
21
|
# Parameters::
|
|
20
22
|
# * *services* (Hash<String, Array<String> >): Expected nodes that should be deployed, with their corresponding services [default: { 'node' => %w[service] }]
|
|
21
|
-
# * *sudo* (
|
|
23
|
+
# * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
|
|
22
24
|
# * *check_mode* (Boolean): Are we testing in check mode? [default: @check_mode]
|
|
23
25
|
# * *mocked_deploy_result* (Hash or nil): Mocked result of the deployment actions, or nil to use the helper's default [default: nil]
|
|
24
26
|
# * *additional_expected_actions* (Array): Additional expected actions [default: []]
|
|
@@ -26,7 +28,7 @@ module HybridPlatformsConductorTest
|
|
|
26
28
|
# * *expect_actions_timeout* (Integer or nil): Expected timeout in actions, or nil for none [default: nil]
|
|
27
29
|
def expected_actions_for_deploy_on(
|
|
28
30
|
services: { 'node' => %w[service] },
|
|
29
|
-
sudo:
|
|
31
|
+
sudo: 'sudo -u root',
|
|
30
32
|
check_mode: @check_mode,
|
|
31
33
|
mocked_deploy_result: nil,
|
|
32
34
|
additional_expected_actions: [],
|
|
@@ -76,8 +78,11 @@ module HybridPlatformsConductorTest
|
|
|
76
78
|
#
|
|
77
79
|
# Parameters::
|
|
78
80
|
# * *nodes_info* (Hash): Node info to give the platform [default: 1 node having 1 service]
|
|
81
|
+
# * *expect_package* (Boolean): Should we expect packaging? [default: true]
|
|
82
|
+
# * *expect_prepare_for_deploy* (Boolean): Should we expect calls to prepare for deploy? [default: true]
|
|
83
|
+
# * *expect_connections_to_nodes* (Boolean): Should we expect connections to nodes? [default: true]
|
|
79
84
|
# * *expect_default_actions* (Boolean): Should we expect default actions? [default: true]
|
|
80
|
-
# * *expect_sudo* (
|
|
85
|
+
# * *expect_sudo* (String or nil): Expected sudo command, or nil if none [default: 'sudo -u root']
|
|
81
86
|
# * *expect_secrets* (Hash): Secrets to be expected during deployment [default: {}]
|
|
82
87
|
# * *expect_local_environment* (Boolean): Expected local environment flag [default: false]
|
|
83
88
|
# * *expect_additional_actions* (Array): Additional expected actions [default: []]
|
|
@@ -90,8 +95,11 @@ module HybridPlatformsConductorTest
|
|
|
90
95
|
# * *repository* (String): Path to the repository
|
|
91
96
|
def with_platform_to_deploy(
|
|
92
97
|
nodes_info: { nodes: { 'node' => { services: %w[service] } } },
|
|
98
|
+
expect_package: true,
|
|
99
|
+
expect_prepare_for_deploy: true,
|
|
100
|
+
expect_connections_to_nodes: true,
|
|
93
101
|
expect_default_actions: true,
|
|
94
|
-
expect_sudo:
|
|
102
|
+
expect_sudo: 'sudo -u root',
|
|
95
103
|
expect_secrets: {},
|
|
96
104
|
expect_local_environment: false,
|
|
97
105
|
expect_additional_actions: [],
|
|
@@ -102,40 +110,52 @@ module HybridPlatformsConductorTest
|
|
|
102
110
|
)
|
|
103
111
|
platform_name = check_mode ? 'platform' : 'my_remote_platform'
|
|
104
112
|
with_test_platform(nodes_info, !check_mode, additional_config) do |repository|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
nil
|
|
117
|
-
end
|
|
113
|
+
# Mock the ServicesHandler accesses
|
|
114
|
+
expect_services_to_deploy = Hash[nodes_info[:nodes].map do |node, node_info|
|
|
115
|
+
[node, node_info[:services]]
|
|
116
|
+
end]
|
|
117
|
+
unless check_mode
|
|
118
|
+
expect(test_services_handler).to receive(:deploy_allowed?).with(
|
|
119
|
+
services: expect_services_to_deploy,
|
|
120
|
+
secrets: expect_secrets,
|
|
121
|
+
local_environment: expect_local_environment
|
|
122
|
+
) do
|
|
123
|
+
nil
|
|
118
124
|
end
|
|
125
|
+
end
|
|
126
|
+
if expect_package
|
|
119
127
|
expect(test_services_handler).to receive(:package).with(
|
|
120
128
|
services: expect_services_to_deploy,
|
|
121
129
|
secrets: expect_secrets,
|
|
122
130
|
local_environment: expect_local_environment
|
|
123
131
|
)
|
|
132
|
+
else
|
|
133
|
+
expect(test_services_handler).not_to receive(:package)
|
|
134
|
+
end
|
|
135
|
+
if expect_prepare_for_deploy
|
|
124
136
|
expect(test_services_handler).to receive(:prepare_for_deploy).with(
|
|
125
137
|
services: expect_services_to_deploy,
|
|
126
138
|
secrets: expect_secrets,
|
|
127
139
|
local_environment: expect_local_environment,
|
|
128
140
|
why_run: check_mode
|
|
129
141
|
)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
else
|
|
143
|
+
expect(test_services_handler).not_to receive(:prepare_for_deploy)
|
|
144
|
+
end
|
|
145
|
+
test_deployer.use_why_run = true if check_mode
|
|
146
|
+
if expect_connections_to_nodes
|
|
147
|
+
with_connections_mocked_on(nodes_info[:nodes].keys) do
|
|
148
|
+
expect_actions_executor_runs(expected_actions_for_deploy_on(
|
|
149
|
+
services: expect_services_to_deploy,
|
|
150
|
+
check_mode: check_mode,
|
|
151
|
+
sudo: expect_sudo,
|
|
152
|
+
additional_expected_actions: expect_additional_actions,
|
|
153
|
+
expect_concurrent_actions: expect_concurrent_actions,
|
|
154
|
+
expect_actions_timeout: expect_actions_timeout
|
|
155
|
+
)) if expect_default_actions
|
|
156
|
+
yield repository
|
|
157
|
+
end
|
|
158
|
+
else
|
|
139
159
|
yield repository
|
|
140
160
|
end
|
|
141
161
|
end
|
|
@@ -181,12 +201,21 @@ module HybridPlatformsConductorTest
|
|
|
181
201
|
end
|
|
182
202
|
|
|
183
203
|
it 'deploys on 1 node using root' do
|
|
184
|
-
with_platform_to_deploy(expect_sudo:
|
|
204
|
+
with_platform_to_deploy(expect_sudo: nil) do
|
|
185
205
|
test_actions_executor.connector(:ssh).ssh_user = 'root'
|
|
186
206
|
expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
|
|
187
207
|
end
|
|
188
208
|
end
|
|
189
209
|
|
|
210
|
+
it 'deploys on 1 node using an alternate sudo' do
|
|
211
|
+
with_platform_to_deploy(
|
|
212
|
+
expect_sudo: 'other_sudo --user root',
|
|
213
|
+
additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
|
|
214
|
+
) do
|
|
215
|
+
expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
190
219
|
it 'deploys on 1 node using 1 secret' do
|
|
191
220
|
with_platform_to_deploy(expect_secrets: { 'secret1' => 'password1' }) do
|
|
192
221
|
test_deployer.secrets = [{ 'secret1' => 'password1' }]
|
|
@@ -207,9 +236,9 @@ module HybridPlatformsConductorTest
|
|
|
207
236
|
nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
|
|
208
237
|
expect_local_environment: true,
|
|
209
238
|
expect_additional_actions: [
|
|
210
|
-
{ remote_bash: 'sudo apt update && sudo apt install -y ca-certificates' },
|
|
239
|
+
{ remote_bash: 'sudo -u root apt update && sudo -u root apt install -y ca-certificates' },
|
|
211
240
|
{
|
|
212
|
-
remote_bash: 'sudo update-ca-certificates',
|
|
241
|
+
remote_bash: 'sudo -u root update-ca-certificates',
|
|
213
242
|
scp: {
|
|
214
243
|
certs_dir => '/usr/local/share/ca-certificates',
|
|
215
244
|
:sudo => true
|
|
@@ -224,6 +253,31 @@ module HybridPlatformsConductorTest
|
|
|
224
253
|
end
|
|
225
254
|
end
|
|
226
255
|
|
|
256
|
+
it 'deploys on 1 node in local environment with certificates to install using hpc_certificates on Debian and an alternate sudo' do
|
|
257
|
+
with_certs_dir do |certs_dir|
|
|
258
|
+
with_platform_to_deploy(
|
|
259
|
+
nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
|
|
260
|
+
expect_sudo: 'other_sudo --user root',
|
|
261
|
+
expect_local_environment: true,
|
|
262
|
+
expect_additional_actions: [
|
|
263
|
+
{ remote_bash: 'other_sudo --user root apt update && other_sudo --user root apt install -y ca-certificates' },
|
|
264
|
+
{
|
|
265
|
+
remote_bash: 'other_sudo --user root update-ca-certificates',
|
|
266
|
+
scp: {
|
|
267
|
+
certs_dir => '/usr/local/share/ca-certificates',
|
|
268
|
+
:sudo => true
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
|
|
273
|
+
) do
|
|
274
|
+
ENV['hpc_certificates'] = certs_dir
|
|
275
|
+
test_deployer.local_environment = true
|
|
276
|
+
expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
227
281
|
it 'deploys on 1 node with certificates to install using hpc_certificates on Debian but ignores them in non-local environment' do
|
|
228
282
|
with_certs_dir do |certs_dir|
|
|
229
283
|
with_platform_to_deploy(nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } }) do
|
|
@@ -237,7 +291,7 @@ module HybridPlatformsConductorTest
|
|
|
237
291
|
with_certs_dir do |certs_dir|
|
|
238
292
|
with_platform_to_deploy(
|
|
239
293
|
nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
|
|
240
|
-
expect_sudo:
|
|
294
|
+
expect_sudo: nil,
|
|
241
295
|
expect_local_environment: true,
|
|
242
296
|
expect_additional_actions: [
|
|
243
297
|
{ remote_bash: 'apt update && apt install -y ca-certificates' },
|
|
@@ -264,9 +318,9 @@ module HybridPlatformsConductorTest
|
|
|
264
318
|
nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
|
|
265
319
|
expect_local_environment: true,
|
|
266
320
|
expect_additional_actions: [
|
|
267
|
-
{ remote_bash: 'sudo yum install -y ca-certificates' },
|
|
321
|
+
{ remote_bash: 'sudo -u root yum install -y ca-certificates' },
|
|
268
322
|
{
|
|
269
|
-
remote_bash: ['sudo update-ca-trust enable', 'sudo update-ca-trust extract'],
|
|
323
|
+
remote_bash: ['sudo -u root update-ca-trust enable', 'sudo -u root update-ca-trust extract'],
|
|
270
324
|
scp: {
|
|
271
325
|
"#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
|
|
272
326
|
:sudo => true
|
|
@@ -281,11 +335,36 @@ module HybridPlatformsConductorTest
|
|
|
281
335
|
end
|
|
282
336
|
end
|
|
283
337
|
|
|
338
|
+
it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS and an alternate sudo' do
|
|
339
|
+
with_certs_dir do |certs_dir|
|
|
340
|
+
with_platform_to_deploy(
|
|
341
|
+
nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
|
|
342
|
+
expect_sudo: 'other_sudo --user root',
|
|
343
|
+
expect_local_environment: true,
|
|
344
|
+
expect_additional_actions: [
|
|
345
|
+
{ remote_bash: 'other_sudo --user root yum install -y ca-certificates' },
|
|
346
|
+
{
|
|
347
|
+
remote_bash: ['other_sudo --user root update-ca-trust enable', 'other_sudo --user root update-ca-trust extract'],
|
|
348
|
+
scp: {
|
|
349
|
+
"#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
|
|
350
|
+
:sudo => true
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
],
|
|
354
|
+
additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
|
|
355
|
+
) do
|
|
356
|
+
ENV['hpc_certificates'] = certs_dir
|
|
357
|
+
test_deployer.local_environment = true
|
|
358
|
+
expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
end
|
|
362
|
+
|
|
284
363
|
it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS using root' do
|
|
285
364
|
with_certs_dir do |certs_dir|
|
|
286
365
|
with_platform_to_deploy(
|
|
287
366
|
nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
|
|
288
|
-
expect_sudo:
|
|
367
|
+
expect_sudo: nil,
|
|
289
368
|
expect_local_environment: true,
|
|
290
369
|
expect_additional_actions: [
|
|
291
370
|
{ remote_bash: 'yum install -y ca-certificates' },
|
|
@@ -360,6 +439,31 @@ module HybridPlatformsConductorTest
|
|
|
360
439
|
end
|
|
361
440
|
end
|
|
362
441
|
|
|
442
|
+
it 'fails when packaging timeout has been reached while taking the futex' do
|
|
443
|
+
with_platform_to_deploy(
|
|
444
|
+
additional_config: 'packaging_timeout 1',
|
|
445
|
+
expect_package: false,
|
|
446
|
+
expect_prepare_for_deploy: false,
|
|
447
|
+
expect_connections_to_nodes: false
|
|
448
|
+
) do
|
|
449
|
+
# Simulate another process taking the packaging futex
|
|
450
|
+
futex_file = HybridPlatformsConductor::Deployer.const_get(:PACKAGING_FUTEX_FILE)
|
|
451
|
+
Futex.new(futex_file).open do
|
|
452
|
+
# Expect the error to be raised within 2 seconds (as it should timeout after 1 second)
|
|
453
|
+
begin
|
|
454
|
+
Timeout::timeout(2) {
|
|
455
|
+
expect { test_deployer.deploy_on('node') }.to raise_error(
|
|
456
|
+
Futex::CantLock,
|
|
457
|
+
/can't get exclusive access to the file #{Regexp.escape(futex_file)} because of the lock at #{Regexp.escape(futex_file)}\.lock, after 1\.\d+s of waiting/
|
|
458
|
+
)
|
|
459
|
+
}
|
|
460
|
+
rescue Timeout::Error
|
|
461
|
+
raise 'The packaging timeout (set to 1 seconds) did not fire within 2 seconds. Looks like it is not working properly.'
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
363
467
|
context 'checking deployment retries' do
|
|
364
468
|
|
|
365
469
|
# Prepare a platform ready to test deployments' retries on.
|