hybrid_platforms_conductor 33.4.0 → 33.7.1
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/CHANGELOG.md +47 -0
- data/README.md +5 -5
- data/docs/config_dsl.md +7 -5
- data/docs/plugins/cmdb/host_keys.md +3 -1
- data/docs/plugins/connector/ssh.md +1 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +29 -1
- data/lib/hybrid_platforms_conductor/bitbucket.rb +2 -2
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
- data/lib/hybrid_platforms_conductor/config.rb +2 -0
- data/lib/hybrid_platforms_conductor/confluence.rb +2 -2
- data/lib/hybrid_platforms_conductor/connector.rb +5 -2
- data/lib/hybrid_platforms_conductor/credentials.rb +20 -12
- data/lib/hybrid_platforms_conductor/deployer.rb +5 -7
- data/lib/hybrid_platforms_conductor/github.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +27 -17
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +13 -12
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +6 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +37 -25
- data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +5 -6
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +23 -14
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +3 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +17 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +30 -10
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -2
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +17 -0
- data/lib/hybrid_platforms_conductor/test.rb +21 -7
- data/lib/hybrid_platforms_conductor/tests_runner.rb +7 -6
- data/lib/hybrid_platforms_conductor/thycotic.rb +2 -2
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +15 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +87 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +30 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +10 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +38 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/helpers_spec.rb +195 -0
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +14 -0
- data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +11 -0
- data/spec/hybrid_platforms_conductor_test/api/credentials_spec.rb +8 -4
- data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +215 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +49 -10
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +64 -16
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +5 -3
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/chef_versions.yml +3 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/nodes/node.json +15 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/policyfiles/test_policy.rb +3 -0
- data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +134 -0
- data/spec/hybrid_platforms_conductor_test/test_connector.rb +2 -2
- metadata +20 -2
|
@@ -24,7 +24,7 @@ module HybridPlatformsConductor
|
|
|
24
24
|
# * Hash<Symbol, Symbol or Array<Symbol> >: The list of necessary properties (or single one) that should be set, per property name (:others can also be used here)
|
|
25
25
|
def property_dependencies
|
|
26
26
|
{
|
|
27
|
-
host_keys: %i[hostname host_ip]
|
|
27
|
+
host_keys: %i[hostname host_ip ssh_port]
|
|
28
28
|
}
|
|
29
29
|
end
|
|
30
30
|
|
|
@@ -41,19 +41,20 @@ module HybridPlatformsConductor
|
|
|
41
41
|
# Nodes for which the property can't be fetched can be ommitted.
|
|
42
42
|
def get_host_keys(_nodes, metadata)
|
|
43
43
|
updated_metadata = {}
|
|
44
|
-
# Get the list of nodes, per hostname (just in case several nodes share the same hostname)
|
|
45
|
-
# Hash<String, Array<String> >
|
|
44
|
+
# Get the list of nodes, per [hostname, port] (just in case several nodes share the same hostname and port)
|
|
45
|
+
# Hash<[String, Integer], Array<String> >
|
|
46
46
|
hostnames = Hash.new { |hash, key| hash[key] = [] }
|
|
47
47
|
metadata.each do |node, node_metadata|
|
|
48
|
+
ssh_port = node_metadata[:ssh_port] || 22
|
|
48
49
|
if node_metadata[:host_ip]
|
|
49
|
-
hostnames[node_metadata[:host_ip]] << node
|
|
50
|
+
hostnames[[node_metadata[:host_ip], ssh_port]] << node
|
|
50
51
|
elsif node_metadata[:hostname]
|
|
51
|
-
hostnames[node_metadata[:hostname]] << node
|
|
52
|
+
hostnames[[node_metadata[:hostname], ssh_port]] << node
|
|
52
53
|
end
|
|
53
54
|
end
|
|
54
55
|
unless hostnames.empty?
|
|
55
|
-
host_keys_for(*hostnames.keys).each do |
|
|
56
|
-
hostnames[
|
|
56
|
+
host_keys_for(*hostnames.keys).each do |host_id, ip|
|
|
57
|
+
hostnames[host_id].each do |node|
|
|
57
58
|
updated_metadata[node] = ip
|
|
58
59
|
end
|
|
59
60
|
end
|
|
@@ -71,7 +72,7 @@ module HybridPlatformsConductor
|
|
|
71
72
|
# Discover the host keys associated to a list of hosts.
|
|
72
73
|
#
|
|
73
74
|
# Parameters::
|
|
74
|
-
# * *hosts* (Array<String>): The hosts to check for
|
|
75
|
+
# * *hosts* (Array<[String, Integer]>): The hosts to check for ([hostname, port])
|
|
75
76
|
# Result::
|
|
76
77
|
# * Hash<String, Array<String> >: The corresponding host keys, per host name
|
|
77
78
|
def host_keys_for(*hosts)
|
|
@@ -82,9 +83,9 @@ module HybridPlatformsConductor
|
|
|
82
83
|
parallel: true,
|
|
83
84
|
nbr_threads_max: MAX_THREADS_SSH_KEY_SCAN,
|
|
84
85
|
progress: log_debug? ? 'Gather host keys' : nil
|
|
85
|
-
) do |host|
|
|
86
|
+
) do |(host, ssh_port)|
|
|
86
87
|
exit_status, stdout, _stderr = @cmd_runner.run_cmd(
|
|
87
|
-
"ssh-keyscan #{host}",
|
|
88
|
+
"ssh-keyscan -p #{ssh_port} #{host}",
|
|
88
89
|
timeout: TIMEOUT_SSH_KEYSCAN,
|
|
89
90
|
log_to_stdout: log_debug?,
|
|
90
91
|
no_exception: true
|
|
@@ -97,9 +98,9 @@ module HybridPlatformsConductor
|
|
|
97
98
|
found_keys << "#{type} #{key}"
|
|
98
99
|
end
|
|
99
100
|
end
|
|
100
|
-
results[host] = found_keys.sort unless found_keys.empty?
|
|
101
|
+
results[[host, ssh_port]] = found_keys.sort unless found_keys.empty?
|
|
101
102
|
else
|
|
102
|
-
log_warn "Unable to get host key for #{host}. Ignoring it. Accessing #{host} might require manual acceptance of its host key."
|
|
103
|
+
log_warn "Unable to get host key for #{host} (port #{ssh_port}). Ignoring it. Accessing #{host} might require manual acceptance of its host key."
|
|
103
104
|
end
|
|
104
105
|
end
|
|
105
106
|
results
|
|
@@ -35,9 +35,11 @@ module HybridPlatformsConductor
|
|
|
35
35
|
# [API] - @stderr_io can be used to send stderr output
|
|
36
36
|
#
|
|
37
37
|
# Parameters::
|
|
38
|
-
# * *bash_cmds* (String): Bash commands to execute
|
|
38
|
+
# * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
|
|
39
39
|
def remote_bash(bash_cmds)
|
|
40
|
-
|
|
40
|
+
SecretString.protect("cd #{workspace_for(@node)} ; #{bash_cmds.to_unprotected}", silenced_str: "cd #{workspace_for(@node)} ; #{bash_cmds}") do |cmd|
|
|
41
|
+
run_cmd cmd, force_bash: true
|
|
42
|
+
end
|
|
41
43
|
end
|
|
42
44
|
|
|
43
45
|
# Execute an interactive shell on the remote node
|
|
@@ -75,8 +77,8 @@ module HybridPlatformsConductor
|
|
|
75
77
|
def remote_copy(from, to, sudo: false, owner: nil, group: nil)
|
|
76
78
|
# If the destination is a relative path, prepend the workspace dir to it.
|
|
77
79
|
to = "#{workspace_for(@node)}/#{to}" unless to.start_with?('/')
|
|
78
|
-
if sudo
|
|
79
|
-
run_cmd "#{@
|
|
80
|
+
if sudo && !@actions_executor.privileged_access?(@node)
|
|
81
|
+
run_cmd "#{@actions_executor.sudo_prefix(@node)}cp -r \"#{from}\" \"#{to}\""
|
|
80
82
|
else
|
|
81
83
|
FileUtils.cp_r from, to unless @cmd_runner.dry_run
|
|
82
84
|
end
|
|
@@ -104,7 +104,7 @@ module HybridPlatformsConductor
|
|
|
104
104
|
# [API] - @stderr_io can be used to send stderr output
|
|
105
105
|
#
|
|
106
106
|
# Parameters::
|
|
107
|
-
# * *bash_cmds* (String): Bash commands to execute
|
|
107
|
+
# * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
|
|
108
108
|
def remote_bash(bash_cmds)
|
|
109
109
|
MyConnectLib.connect_to(@nodes_handler.get_host_ip_of(@node)).run_bash(bash_cmds)
|
|
110
110
|
end
|
|
@@ -236,31 +236,40 @@ module HybridPlatformsConductor
|
|
|
236
236
|
# [API] - @stderr_io can be used to send stderr output
|
|
237
237
|
#
|
|
238
238
|
# Parameters::
|
|
239
|
-
# * *bash_cmds* (String): Bash commands to execute
|
|
239
|
+
# * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
|
|
240
240
|
def remote_bash(bash_cmds)
|
|
241
|
-
|
|
241
|
+
SecretString.protect(
|
|
242
242
|
if @nodes_handler.get_ssh_session_exec_of(@node) == false
|
|
243
243
|
# When ExecSession is disabled we need to use stdin directly
|
|
244
|
-
"{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
|
|
244
|
+
"{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds.to_unprotected}\nHPC_EOF"
|
|
245
245
|
else
|
|
246
|
-
"#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
246
|
+
"#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds.to_unprotected}\nHPC_EOF"
|
|
247
|
+
end,
|
|
248
|
+
silenced_str:
|
|
249
|
+
if @nodes_handler.get_ssh_session_exec_of(@node) == false
|
|
250
|
+
# When ExecSession is disabled we need to use stdin directly
|
|
251
|
+
"{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
|
|
252
|
+
else
|
|
253
|
+
"#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
|
|
254
|
+
end
|
|
255
|
+
) do |ssh_cmd|
|
|
256
|
+
# Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
|
|
257
|
+
# Therefore we need to make sure that if bash_cmds exceeds MAX_CMD_ARG_LENGTH bytes (considering EOF chars) then we use an intermediary shell script to store the commands.
|
|
258
|
+
if bash_cmds.to_unprotected.size > MAX_CMD_ARG_LENGTH
|
|
259
|
+
# Write the commands in a file
|
|
260
|
+
temp_file = "#{Dir.tmpdir}/hpc_temp_cmds_#{Digest::MD5.hexdigest(bash_cmds.to_unprotected)}.sh"
|
|
261
|
+
File.open(temp_file, 'w+') do |file|
|
|
262
|
+
file.write ssh_cmd.to_unprotected
|
|
263
|
+
file.chmod 0o700
|
|
264
|
+
end
|
|
265
|
+
begin
|
|
266
|
+
run_cmd(temp_file)
|
|
267
|
+
ensure
|
|
268
|
+
File.unlink(temp_file)
|
|
269
|
+
end
|
|
270
|
+
else
|
|
271
|
+
run_cmd ssh_cmd
|
|
261
272
|
end
|
|
262
|
-
else
|
|
263
|
-
run_cmd ssh_cmd
|
|
264
273
|
end
|
|
265
274
|
end
|
|
266
275
|
|
|
@@ -301,13 +310,14 @@ module HybridPlatformsConductor
|
|
|
301
310
|
# * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
|
|
302
311
|
# * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
|
|
303
312
|
def remote_copy(from, to, sudo: false, owner: nil, group: nil)
|
|
313
|
+
need_sudo = sudo && !@actions_executor.privileged_access?(@node)
|
|
304
314
|
if @nodes_handler.get_ssh_session_exec_of(@node) == false
|
|
305
315
|
# We don't have ExecSession, so don't use ssh, but scp instead.
|
|
306
|
-
if
|
|
316
|
+
if need_sudo
|
|
307
317
|
# We need to first copy the file in an accessible directory, and then sudo mv
|
|
308
318
|
remote_bash('mkdir -p hpc_tmp_scp')
|
|
309
319
|
run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:./hpc_tmp_scp"
|
|
310
|
-
remote_bash("#{@
|
|
320
|
+
remote_bash("#{@actions_executor.sudo_prefix(@node)}mv ./hpc_tmp_scp/#{File.basename(from)} #{to}")
|
|
311
321
|
else
|
|
312
322
|
run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:#{to}"
|
|
313
323
|
end
|
|
@@ -323,7 +333,7 @@ module HybridPlatformsConductor
|
|
|
323
333
|
#{File.basename(from)} | \
|
|
324
334
|
#{ssh_exec} \
|
|
325
335
|
#{ssh_url} \
|
|
326
|
-
\"#{
|
|
336
|
+
\"#{need_sudo ? @actions_executor.sudo_prefix(@node) : ''}tar \
|
|
327
337
|
--extract \
|
|
328
338
|
--gunzip \
|
|
329
339
|
--file - \
|
|
@@ -374,16 +384,18 @@ module HybridPlatformsConductor
|
|
|
374
384
|
|
|
375
385
|
# Add each node
|
|
376
386
|
# Query for the metadata of all nodes at once
|
|
377
|
-
@nodes_handler.prefetch_metadata_of nodes, %i[private_ips hostname host_ip description]
|
|
387
|
+
@nodes_handler.prefetch_metadata_of nodes, %i[private_ips hostname host_ip description ssh_port]
|
|
378
388
|
nodes.sort.each do |node|
|
|
379
389
|
# Generate the conf for the node
|
|
380
390
|
connection, connection_user, gateway, gateway_user = connection_info_for(node, no_exception: true)
|
|
381
391
|
if connection.nil?
|
|
382
392
|
config_content << "# #{node} - Not connectable using SSH - #{@nodes_handler.get_description_of(node) || ''}\n"
|
|
383
393
|
else
|
|
394
|
+
ssh_port = @nodes_handler.get_ssh_port_of(node)
|
|
384
395
|
config_content << "# #{node} - #{connection} - #{@nodes_handler.get_description_of(node) || ''}\n"
|
|
385
396
|
config_content << "Host #{ssh_aliases_for(node).join(' ')}\n"
|
|
386
397
|
config_content << " Hostname #{connection}\n"
|
|
398
|
+
config_content << " Port #{ssh_port}\n" unless ssh_port.nil?
|
|
387
399
|
config_content << " User \"#{connection_user}\"\n" if connection_user != @ssh_user
|
|
388
400
|
config_content << " ProxyCommand #{ssh_exec} -q -W %h:%p #{gateway_user}@#{gateway}\n" unless gateway.nil?
|
|
389
401
|
if @passwords.key?(node)
|
|
@@ -648,7 +660,7 @@ module HybridPlatformsConductor
|
|
|
648
660
|
existing_users = File.exist?(control_master_users_file) ? File.read(control_master_users_file).split("\n") : []
|
|
649
661
|
ssh_url = "hpc.#{node}"
|
|
650
662
|
connection, connection_user, _gateway, _gateway_user = connection_info_for(node)
|
|
651
|
-
control_path_file = control_master_file(connection,
|
|
663
|
+
control_path_file = control_master_file(connection, @nodes_handler.get_ssh_port_of(node) || 22, connection_user)
|
|
652
664
|
if existing_users.empty?
|
|
653
665
|
# Make sure there is no stale one.
|
|
654
666
|
if File.exist?(control_path_file)
|
|
@@ -29,10 +29,9 @@ module HybridPlatformsConductor
|
|
|
29
29
|
# Result::
|
|
30
30
|
# * Array< Hash<Symbol,Object> >: List of actions to be done
|
|
31
31
|
def actions_to_save_logs(node, services, deployment_info, exit_status, stdout, stderr)
|
|
32
|
-
# Create a log file to be scp with all relevant info
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{ssh_user}"
|
|
32
|
+
# Create a log file to be scp-ed with all relevant info
|
|
33
|
+
sudo_prefix = @actions_executor.sudo_prefix(node)
|
|
34
|
+
log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{@actions_executor.connector(:ssh).ssh_user}"
|
|
36
35
|
[
|
|
37
36
|
{
|
|
38
37
|
ruby: proc do
|
|
@@ -56,7 +55,7 @@ module HybridPlatformsConductor
|
|
|
56
55
|
{
|
|
57
56
|
scp: {
|
|
58
57
|
log_file => '/var/log/deployments',
|
|
59
|
-
:sudo =>
|
|
58
|
+
:sudo => !@actions_executor.privileged_access?(node),
|
|
60
59
|
:owner => 'root',
|
|
61
60
|
:group => 'root'
|
|
62
61
|
}
|
|
@@ -85,7 +84,7 @@ module HybridPlatformsConductor
|
|
|
85
84
|
# Result::
|
|
86
85
|
# * Array< Hash<Symbol,Object> >: List of actions to be done
|
|
87
86
|
def actions_to_read_logs(node)
|
|
88
|
-
sudo_prefix = @actions_executor.
|
|
87
|
+
sudo_prefix = @actions_executor.sudo_prefix(node)
|
|
89
88
|
[
|
|
90
89
|
{ remote_bash: "#{sudo_prefix}cat /var/log/deployments/`#{sudo_prefix}ls -t /var/log/deployments/ | head -1`" }
|
|
91
90
|
]
|
|
@@ -241,18 +241,24 @@ module HybridPlatformsConductor
|
|
|
241
241
|
'--json-attributes', "nodes/#{node}.json"
|
|
242
242
|
]
|
|
243
243
|
client_options << '--why-run' if use_why_run
|
|
244
|
+
# Force setting of TERM variable and usage of unbuffer to get colored output from chef-client even if executed through a non-interactive SSH session.
|
|
245
|
+
client_env = {
|
|
246
|
+
'SSL_CERT_DIR' => '/etc/ssl/certs',
|
|
247
|
+
'TERM' => 'xterm-256color'
|
|
248
|
+
}
|
|
244
249
|
if @nodes_handler.get_use_local_chef_of(node)
|
|
245
250
|
# Just run the chef-client directly from the packaged repository
|
|
246
|
-
sudo_prefix = @cmd_runner.root? ? '' : 'sudo '
|
|
251
|
+
sudo_prefix = @cmd_runner.root? ? '' : 'sudo -E '
|
|
247
252
|
[
|
|
248
253
|
{
|
|
249
254
|
bash: [
|
|
250
255
|
'set -e',
|
|
251
256
|
"cd #{package_dir}"
|
|
252
257
|
] +
|
|
253
|
-
|
|
258
|
+
client_env.map { |var_name, value| "export #{var_name}=#{value}" } +
|
|
259
|
+
gems_to_install.map { |(gem_name, gem_version)| "#{sudo_prefix}/opt/chef-workstation/bin/chef gem install #{gem_name} --version \"#{gem_version}\"" } +
|
|
254
260
|
[
|
|
255
|
-
"#{sudo_prefix}
|
|
261
|
+
"#{sudo_prefix}/opt/chef-workstation/bin/chef-client #{client_options.join(' ')}"
|
|
256
262
|
]
|
|
257
263
|
}
|
|
258
264
|
]
|
|
@@ -263,14 +269,14 @@ module HybridPlatformsConductor
|
|
|
263
269
|
raise "Missing file #{chef_versions_file} specifying the Chef Infra Client version to be deployed" unless File.exist?(chef_versions_file)
|
|
264
270
|
|
|
265
271
|
required_chef_client_version = YAML.load_file(chef_versions_file)['client']
|
|
266
|
-
sudo =
|
|
272
|
+
sudo = @actions_executor.sudo_prefix(node, forward_env: true)
|
|
267
273
|
[
|
|
268
274
|
{
|
|
269
275
|
# Install dependencies
|
|
270
276
|
remote_bash: [
|
|
271
277
|
'set -e',
|
|
272
278
|
'set -o pipefail',
|
|
273
|
-
"if [ -n \"$(command -v apt)\" ]; then #{sudo}apt update && #{sudo}apt install -y curl build-essential ; else #{sudo}yum groupinstall 'Development Tools' && #{sudo}yum install -y curl ; fi",
|
|
279
|
+
"if [ -n \"$(command -v apt)\" ]; then #{sudo}apt update && #{sudo}apt install -y curl build-essential expect ; else #{sudo}yum groupinstall 'Development Tools' && #{sudo}yum install -y curl expect ; fi",
|
|
274
280
|
'mkdir -p ./hpc_deploy',
|
|
275
281
|
'rm -rf ./hpc_deploy/tmp',
|
|
276
282
|
'mkdir -p ./hpc_deploy/tmp',
|
|
@@ -281,16 +287,19 @@ module HybridPlatformsConductor
|
|
|
281
287
|
},
|
|
282
288
|
{
|
|
283
289
|
scp: { package_dir => './hpc_deploy' },
|
|
284
|
-
remote_bash:
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
gems_to_install.map { |(gem_name, gem_version)| "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/embedded/bin/gem install #{gem_name} --version \"#{gem_version}\"" } +
|
|
289
|
-
[
|
|
290
|
-
"#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/bin/chef-client #{client_options.join(' ')}",
|
|
291
|
-
'cd ..'
|
|
290
|
+
remote_bash: {
|
|
291
|
+
commands: [
|
|
292
|
+
'set -e',
|
|
293
|
+
"cd ./hpc_deploy/#{package_name}"
|
|
292
294
|
] +
|
|
293
|
-
|
|
295
|
+
gems_to_install.map { |(gem_name, gem_version)| "#{sudo}/opt/chef/embedded/bin/gem install #{gem_name} --version \"#{gem_version}\"" } +
|
|
296
|
+
[
|
|
297
|
+
"#{sudo}unbuffer /opt/chef/bin/chef-client #{client_options.join(' ')}",
|
|
298
|
+
'cd ..'
|
|
299
|
+
] +
|
|
300
|
+
(log_debug? ? [] : ["#{sudo}rm -rf ./hpc_deploy/#{package_name}"]),
|
|
301
|
+
env: client_env
|
|
302
|
+
}
|
|
294
303
|
}
|
|
295
304
|
]
|
|
296
305
|
end
|
|
@@ -21,7 +21,7 @@ module HybridPlatformsConductor
|
|
|
21
21
|
::Docker.validate_version!
|
|
22
22
|
docker_ok = true
|
|
23
23
|
rescue
|
|
24
|
-
log_error "
|
|
24
|
+
log_error "Docker is not installed correctly. Please install it. Error: #{$ERROR_INFO}"
|
|
25
25
|
end
|
|
26
26
|
docker_ok
|
|
27
27
|
end
|
|
@@ -2,6 +2,7 @@ require 'json'
|
|
|
2
2
|
require 'proxmox'
|
|
3
3
|
require 'digest'
|
|
4
4
|
require 'hybrid_platforms_conductor/actions_executor'
|
|
5
|
+
require 'hybrid_platforms_conductor/credentials'
|
|
5
6
|
require 'hybrid_platforms_conductor/provisioner'
|
|
6
7
|
|
|
7
8
|
module HybridPlatformsConductor
|
|
@@ -284,7 +285,7 @@ module HybridPlatformsConductor
|
|
|
284
285
|
# cf https://pve.proxmox.com/wiki/Renaming_a_PVE_node
|
|
285
286
|
URI.parse(url).host.downcase.split('.').first,
|
|
286
287
|
user,
|
|
287
|
-
password,
|
|
288
|
+
password&.to_unprotected,
|
|
288
289
|
ENV['hpc_realm_for_proxmox'] || 'pam',
|
|
289
290
|
{
|
|
290
291
|
verify_ssl: false,
|
|
@@ -436,7 +437,7 @@ module HybridPlatformsConductor
|
|
|
436
437
|
{
|
|
437
438
|
proxmox_test_info[:sync_node] => {
|
|
438
439
|
remote_bash: {
|
|
439
|
-
commands: "#{@actions_executor.
|
|
440
|
+
commands: "#{@actions_executor.sudo_prefix(proxmox_test_info[:sync_node], forward_env: true)}./proxmox/#{cmd}",
|
|
440
441
|
env: {
|
|
441
442
|
'hpc_user_for_proxmox' => user,
|
|
442
443
|
'hpc_password_for_proxmox' => password,
|
|
@@ -90,7 +90,7 @@ module HybridPlatformsConductor
|
|
|
90
90
|
key_file = ENV['hpc_key_file_for_keepass']
|
|
91
91
|
password_enc = ENV['hpc_password_enc_for_keepass']
|
|
92
92
|
keepass_credentials = {}
|
|
93
|
-
keepass_credentials[:password] = password if password
|
|
93
|
+
keepass_credentials[:password] = password.to_unprotected if password
|
|
94
94
|
keepass_credentials[:password_enc] = password_enc if password_enc
|
|
95
95
|
keepass_credentials[:key_file] = key_file if key_file
|
|
96
96
|
KeepassKpscript.
|
|
@@ -26,7 +26,13 @@ module HybridPlatformsConductor
|
|
|
26
26
|
# Check that we can connect with root
|
|
27
27
|
ssh_ok = false
|
|
28
28
|
begin
|
|
29
|
-
Net::SSH.start(
|
|
29
|
+
Net::SSH.start(
|
|
30
|
+
instance.ip,
|
|
31
|
+
'root',
|
|
32
|
+
password: 'root_pwd',
|
|
33
|
+
auth_methods: ['password'],
|
|
34
|
+
verify_host_key: :never
|
|
35
|
+
) do |ssh|
|
|
30
36
|
ssh_ok = ssh.exec!('echo Works').strip == 'Works'
|
|
31
37
|
end
|
|
32
38
|
rescue
|
|
@@ -53,14 +59,22 @@ module HybridPlatformsConductor
|
|
|
53
59
|
# System is booting up. See pam_nologin(8)
|
|
54
60
|
# Authentication failed.
|
|
55
61
|
instance.stop
|
|
56
|
-
|
|
62
|
+
ssh_port = @nodes_handler.get_ssh_port_of(@node) || 22
|
|
63
|
+
instance.with_running_instance(port: ssh_port) do
|
|
57
64
|
|
|
58
65
|
unless @nodes_handler.get_root_access_allowed_of(@node)
|
|
59
66
|
# ===== Deploy removes root access
|
|
60
67
|
# Check that we can't connect with root
|
|
61
68
|
ssh_ok = false
|
|
62
69
|
begin
|
|
63
|
-
Net::SSH.start(
|
|
70
|
+
Net::SSH.start(
|
|
71
|
+
instance.ip,
|
|
72
|
+
'root',
|
|
73
|
+
password: 'root_pwd',
|
|
74
|
+
auth_methods: ['password'],
|
|
75
|
+
verify_host_key: :never,
|
|
76
|
+
port: ssh_port
|
|
77
|
+
) do |ssh|
|
|
64
78
|
ssh_ok = ssh.exec!('echo Works').strip == 'Works'
|
|
65
79
|
end
|
|
66
80
|
rescue
|
|
@@ -18,7 +18,13 @@ module HybridPlatformsConductor
|
|
|
18
18
|
# Check that we can connect with root
|
|
19
19
|
ssh_ok = false
|
|
20
20
|
begin
|
|
21
|
-
Net::SSH.start(
|
|
21
|
+
Net::SSH.start(
|
|
22
|
+
instance.ip,
|
|
23
|
+
'root',
|
|
24
|
+
password: 'root_pwd',
|
|
25
|
+
auth_methods: ['password'],
|
|
26
|
+
verify_host_key: :never
|
|
27
|
+
) do |ssh|
|
|
22
28
|
ssh_ok = ssh.exec!('echo Works').strip == 'Works'
|
|
23
29
|
end
|
|
24
30
|
rescue
|
|
@@ -29,17 +35,31 @@ module HybridPlatformsConductor
|
|
|
29
35
|
deployer.nbr_retries_on_error = 3
|
|
30
36
|
deployer.deploy_on @node
|
|
31
37
|
# As sshd is certainly being restarted, start and stop the container to reload it.
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
# As it's possible sshd has to be restarted because of a change in its conf, restart the container.
|
|
39
|
+
# Otherwise you'll get the following error upon reconnection:
|
|
40
|
+
# System is booting up. See pam_nologin(8)
|
|
41
|
+
# Authentication failed.
|
|
42
|
+
instance.stop
|
|
43
|
+
ssh_port = @nodes_handler.get_ssh_port_of(@node) || 22
|
|
44
|
+
instance.with_running_instance(port: ssh_port) do
|
|
45
|
+
# Check that we can't connect with root
|
|
46
|
+
ssh_ok = false
|
|
47
|
+
begin
|
|
48
|
+
Net::SSH.start(
|
|
49
|
+
instance.ip,
|
|
50
|
+
'root',
|
|
51
|
+
password: 'root_pwd',
|
|
52
|
+
auth_methods: ['password'],
|
|
53
|
+
verify_host_key: :never,
|
|
54
|
+
port: ssh_port
|
|
55
|
+
) do |ssh|
|
|
56
|
+
ssh_ok = ssh.exec!('echo Works').strip == 'Works'
|
|
57
|
+
end
|
|
58
|
+
rescue
|
|
59
|
+
nil
|
|
38
60
|
end
|
|
39
|
-
|
|
40
|
-
nil
|
|
61
|
+
assert_equal ssh_ok, false, 'Root can still connect on the image after deployment'
|
|
41
62
|
end
|
|
42
|
-
assert_equal ssh_ok, false, 'Root can still connect on the image after deployment'
|
|
43
63
|
end
|
|
44
64
|
end
|
|
45
65
|
end
|