hybrid_platforms_conductor 32.12.0 → 32.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1103 -0
- data/LICENSE.md +31 -0
- data/README.md +395 -0
- data/bin/setup +1 -1
- data/docs/api.md +349 -0
- data/docs/config_dsl.md +315 -0
- data/docs/executables.md +226 -0
- data/docs/executables/check-node.md +155 -0
- data/docs/executables/deploy.md +198 -0
- data/docs/executables/dump_nodes_json.md +110 -0
- data/docs/executables/free_ips.md +93 -0
- data/docs/executables/free_veids.md +73 -0
- data/docs/executables/get_impacted_nodes.md +94 -0
- data/docs/executables/last_deploys.md +114 -0
- data/docs/executables/nodes_to_deploy.md +139 -0
- data/docs/executables/report.md +159 -0
- data/docs/executables/run.md +126 -0
- data/docs/executables/setup.md +92 -0
- data/docs/executables/ssh_config.md +151 -0
- data/docs/executables/test.md +213 -0
- data/docs/executables/topograph.md +139 -0
- data/docs/gen/mermaid/README.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/free_veids.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/setup.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
- data/docs/install.md +161 -0
- data/docs/plugins.md +215 -0
- data/docs/plugins/action/bash.md +37 -0
- data/docs/plugins/action/interactive.md +37 -0
- data/docs/plugins/action/remote_bash.md +67 -0
- data/docs/plugins/action/ruby.md +69 -0
- data/docs/plugins/action/scp.md +61 -0
- data/docs/plugins/cmdb/config.md +46 -0
- data/docs/plugins/cmdb/host_ip.md +33 -0
- data/docs/plugins/cmdb/host_keys.md +33 -0
- data/docs/plugins/cmdb/platform_handlers.md +33 -0
- data/docs/plugins/connector/local.md +28 -0
- data/docs/plugins/connector/ssh.md +95 -0
- data/docs/plugins/platform_handler/yaml_inventory.md +105 -0
- data/docs/plugins/provisioner/docker.md +27 -0
- data/docs/plugins/provisioner/podman.md +27 -0
- data/docs/plugins/provisioner/proxmox.md +115 -0
- data/docs/plugins/report/confluence.md +49 -0
- data/docs/plugins/report/mediawiki.md +28 -0
- data/docs/plugins/report/stdout.md +32 -0
- data/docs/plugins/test/bitbucket_conf.md +97 -0
- data/docs/plugins/test/can_be_checked.md +27 -0
- data/docs/plugins/test/check_deploy_and_idempotence.md +61 -0
- data/docs/plugins/test/check_from_scratch.md +28 -0
- data/docs/plugins/test/connection.md +27 -0
- data/docs/plugins/test/deploy_freshness.md +27 -0
- data/docs/plugins/test/deploy_from_scratch.md +28 -0
- data/docs/plugins/test/deploy_removes_root_access.md +29 -0
- data/docs/plugins/test/divergence.md +41 -0
- data/docs/plugins/test/executables.md +26 -0
- data/docs/plugins/test/file_system.md +49 -0
- data/docs/plugins/test/file_system_hdfs.md +65 -0
- data/docs/plugins/test/hostname.md +27 -0
- data/docs/plugins/test/idempotence.md +56 -0
- data/docs/plugins/test/ip.md +28 -0
- data/docs/plugins/test/jenkins_ci_conf.md +54 -0
- data/docs/plugins/test/jenkins_ci_masters_ok.md +54 -0
- data/docs/plugins/test/linear_strategy.md +26 -0
- data/docs/plugins/test/local_users.md +48 -0
- data/docs/plugins/test/mounts.md +55 -0
- data/docs/plugins/test/orphan_files.md +38 -0
- data/docs/plugins/test/ports.md +50 -0
- data/docs/plugins/test/private_ips.md +27 -0
- data/docs/plugins/test/public_ips.md +27 -0
- data/docs/plugins/test/spectre.md +26 -0
- data/docs/plugins/test/veids.md +27 -0
- data/docs/plugins/test/vulnerabilities.md +65 -0
- data/docs/plugins/test_report/confluence.md +43 -0
- data/docs/plugins/test_report/stdout.md +26 -0
- data/docs/plugins_create.md +135 -0
- data/docs/tutorial.md +57 -0
- data/docs/tutorial/01_installation.md +129 -0
- data/docs/tutorial/02_first_node.md +466 -0
- data/docs/tutorial/03_scale.md +876 -0
- data/docs/tutorial/04_test.md +965 -0
- data/docs/tutorial/05_extend_with_plugins.md +1132 -0
- data/examples/bare/Gemfile +4 -0
- data/examples/bare/hpc_config.rb +2 -0
- data/examples/localhost/Gemfile +4 -0
- data/examples/localhost/hpc_config.rb +2 -0
- data/examples/localhost/inventory.yaml +4 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +1 -0
- data/lib/hybrid_platforms_conductor/deployer.rb +3 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +29 -13
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +98 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +7 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +5 -5
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/yaml_inventory.rb +140 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +5 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +19 -17
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +3 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +4 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +8 -7
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +1 -1
- data/lib/hybrid_platforms_conductor/json_dumper.rb +1 -1
- data/lib/hybrid_platforms_conductor/platform_handler.rb +1 -1
- data/lib/hybrid_platforms_conductor/services_handler.rb +18 -16
- data/lib/hybrid_platforms_conductor/tests_runner.rb +0 -1
- data/lib/hybrid_platforms_conductor/topographer.rb +0 -1
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +16 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/connectable_nodes_spec.rb +30 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +113 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +6 -2
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +38 -1
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +8 -8
- data/spec/hybrid_platforms_conductor_test/docs_spec.rb +10 -0
- data/tools/check_md +89 -0
- data/tools/generate_mermaid +75 -0
- metadata +207 -12
@@ -5,6 +5,7 @@ require 'securerandom'
|
|
5
5
|
require 'tmpdir'
|
6
6
|
require 'hybrid_platforms_conductor/action'
|
7
7
|
require 'hybrid_platforms_conductor/cmd_runner'
|
8
|
+
require 'hybrid_platforms_conductor/config'
|
8
9
|
require 'hybrid_platforms_conductor/connector'
|
9
10
|
require 'hybrid_platforms_conductor/io_router'
|
10
11
|
require 'hybrid_platforms_conductor/logger_helpers'
|
@@ -41,7 +41,7 @@ module HybridPlatformsConductor
|
|
41
41
|
|
42
42
|
include LoggerHelpers
|
43
43
|
|
44
|
-
Config.extend_config_dsl_with ConfigDSLExtension, :
|
44
|
+
Config.extend_config_dsl_with ConfigDSLExtension, :init_deployer_config
|
45
45
|
|
46
46
|
# Do we use why-run mode while deploying? [default = false]
|
47
47
|
# Boolean
|
@@ -336,7 +336,8 @@ module HybridPlatformsConductor
|
|
336
336
|
actions_executor.connector(:ssh).passwords[node] = 'root_pwd'
|
337
337
|
deployer.local_environment = true
|
338
338
|
# Ignore secrets that might have been given: in Docker containers we always use dummy secrets
|
339
|
-
|
339
|
+
dummy_secrets_file = "#{@config.hybrid_platforms_dir}/dummy_secrets.json"
|
340
|
+
deployer.secrets = File.exist?(dummy_secrets_file) ? [JSON.parse(File.read(dummy_secrets_file))] : []
|
340
341
|
yield deployer, instance
|
341
342
|
end
|
342
343
|
rescue
|
@@ -14,16 +14,33 @@ module HybridPlatformsConductor
|
|
14
14
|
# [API] - @actions_executor is accessible
|
15
15
|
#
|
16
16
|
# Parameters::
|
17
|
-
# * *remote_bash* (Array
|
18
|
-
# *
|
19
|
-
# *
|
20
|
-
#
|
17
|
+
# * *remote_bash* (Array or Object): List of commands (or single command) to be executed. Each command can be the following:
|
18
|
+
# * String: Simple bash command.
|
19
|
+
# * Hash<Symbol, Object>: Information about the commands to execute. Can have the following properties:
|
20
|
+
# * *commands* (Array<String> or String): List of bash commands to execute (can be a single one) [default: ''].
|
21
|
+
# * *file* (String): Name of file from which commands should be taken [optional].
|
22
|
+
# * *env* (Hash<String, String>): Environment variables to be set before executing those commands [default: {}].
|
21
23
|
def setup(remote_bash)
|
22
|
-
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
@remote_bash
|
24
|
+
# Normalize the parameters.
|
25
|
+
# Array< Hash<Symbol,Object> >: Simple array of info:
|
26
|
+
# * *commands* (Array<String>): List of bash commands to execute.
|
27
|
+
# * *env* (Hash<String, String>): Environment variables to be set before executing those commands.
|
28
|
+
@remote_bash = (remote_bash.is_a?(Array) ? remote_bash : [remote_bash]).map do |cmd_info|
|
29
|
+
if cmd_info.is_a?(String)
|
30
|
+
{
|
31
|
+
commands: [cmd_info],
|
32
|
+
env: {}
|
33
|
+
}
|
34
|
+
else
|
35
|
+
commands = []
|
36
|
+
commands.concat(cmd_info[:commands].is_a?(String) ? [cmd_info[:commands]] : cmd_info[:commands]) if cmd_info[:commands]
|
37
|
+
commands << File.read(cmd_info[:file]) if cmd_info[:file]
|
38
|
+
{
|
39
|
+
commands: commands,
|
40
|
+
env: cmd_info[:env] || {}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
end
|
27
44
|
end
|
28
45
|
|
29
46
|
# Do we need a connector to execute this action on a node?
|
@@ -46,10 +63,9 @@ module HybridPlatformsConductor
|
|
46
63
|
# [API] - @stderr_io can be used to log stderr messages
|
47
64
|
# [API] - run_cmd(String) method can be used to execute a command. See CmdRunner#run_cmd to know about the result's signature.
|
48
65
|
def execute
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
bash_str = bash_commands.join("\n")
|
66
|
+
bash_str = @remote_bash.map do |cmd_info|
|
67
|
+
(cmd_info[:env].map { |var_name, var_value| "export #{var_name}='#{var_value}'" } + cmd_info[:commands]).join("\n")
|
68
|
+
end.join("\n")
|
53
69
|
log_debug "[#{@node}] - Execute remote Bash commands \"#{bash_str}\"..."
|
54
70
|
@connector.remote_bash bash_str
|
55
71
|
end
|
@@ -16,7 +16,7 @@ module HybridPlatformsConductor
|
|
16
16
|
# Parameters::
|
17
17
|
# * *mappings* (Hash<String or Symbol, Object>): Set of couples source => destination_dir to copy files or directories from the local file system to the remote file system.
|
18
18
|
# The following properties can also be used:
|
19
|
-
# * *sudo* (Boolean): Do we use sudo to make the copy? [default: false]
|
19
|
+
# * *sudo* (Boolean): Do we use sudo on the remote to make the copy? [default: false]
|
20
20
|
# * *owner* (String or nil): Owner to use for files, or nil to use current one [default: nil]
|
21
21
|
# * *group* (String or nil): Group to use for files, or nil to use current one [default: nil]
|
22
22
|
def setup(mappings)
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module HybridPlatformsConductor
|
5
|
+
|
6
|
+
module HpcPlugins
|
7
|
+
|
8
|
+
module Connector
|
9
|
+
|
10
|
+
# Connector executing remote commands on the local environment in dedicated workspaces (/tmp/hpc_local_workspaces)
|
11
|
+
class Local < HybridPlatformsConductor::Connector
|
12
|
+
|
13
|
+
# Select nodes where this connector can connect.
|
14
|
+
# [API] - This method is mandatory
|
15
|
+
# [API] - @cmd_runner can be used
|
16
|
+
# [API] - @nodes_handler can be used
|
17
|
+
#
|
18
|
+
# Parameters::
|
19
|
+
# * *nodes* (Array<String>): List of candidate nodes
|
20
|
+
# Result::
|
21
|
+
# * Array<String>: List of nodes we can connect to from the candidates
|
22
|
+
def connectable_nodes_from(nodes)
|
23
|
+
@nodes_handler.prefetch_metadata_of nodes, :local_node
|
24
|
+
nodes.select { |node| @nodes_handler.get_local_node_of(node) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Run bash commands on a given node.
|
28
|
+
# [API] - This method is mandatory
|
29
|
+
# [API] - If defined, then with_connection_to has been called before this method.
|
30
|
+
# [API] - @cmd_runner can be used
|
31
|
+
# [API] - @nodes_handler can be used
|
32
|
+
# [API] - @node can be used to access the node on which we execute the remote bash
|
33
|
+
# [API] - @timeout can be used to know when the action should fail
|
34
|
+
# [API] - @stdout_io can be used to send stdout output
|
35
|
+
# [API] - @stderr_io can be used to send stderr output
|
36
|
+
#
|
37
|
+
# Parameters::
|
38
|
+
# * *bash_cmds* (String): Bash commands to execute
|
39
|
+
def remote_bash(bash_cmds)
|
40
|
+
run_cmd "cd #{workspace_for(@node)} ; #{bash_cmds}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Execute an interactive shell on the remote node
|
44
|
+
# [API] - This method is mandatory
|
45
|
+
# [API] - If defined, then with_connection_to has been called before this method.
|
46
|
+
# [API] - @cmd_runner can be used
|
47
|
+
# [API] - @nodes_handler can be used
|
48
|
+
# [API] - @node can be used to access the node on which we execute the remote bash
|
49
|
+
# [API] - @timeout can be used to know when the action should fail
|
50
|
+
# [API] - @stdout_io can be used to send stdout output
|
51
|
+
# [API] - @stderr_io can be used to send stderr output
|
52
|
+
def remote_interactive
|
53
|
+
system "cd #{workspace_for(@node)} ; /bin/bash"
|
54
|
+
end
|
55
|
+
|
56
|
+
# Copy a file to the remote node in a directory
|
57
|
+
# [API] - This method is mandatory
|
58
|
+
# [API] - If defined, then with_connection_to has been called before this method.
|
59
|
+
# [API] - @cmd_runner can be used
|
60
|
+
# [API] - @nodes_handler can be used
|
61
|
+
# [API] - @node can be used to access the node on which we execute the remote bash
|
62
|
+
# [API] - @timeout can be used to know when the action should fail
|
63
|
+
# [API] - @stdout_io can be used to send stdout output
|
64
|
+
# [API] - @stderr_io can be used to send stderr output
|
65
|
+
#
|
66
|
+
# Parameters::
|
67
|
+
# * *from* (String): Local file to copy
|
68
|
+
# * *to* (String): Remote directory to copy to
|
69
|
+
# * *sudo* (Boolean): Do we use sudo to copy? [default: false]
|
70
|
+
# * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
|
71
|
+
# * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
|
72
|
+
def remote_copy(from, to, sudo: false, owner: nil, group: nil)
|
73
|
+
# If the destination is a relative path, prepend the workspace dir to it.
|
74
|
+
to = "#{workspace_for(@node)}/#{to}" unless to.start_with?('/')
|
75
|
+
FileUtils.cp_r from, to
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Create or reuse a dedicated workspace for a node
|
81
|
+
#
|
82
|
+
# Parameters::
|
83
|
+
# * *node* (String): Node for which we want a dedicated workspace
|
84
|
+
# Result::
|
85
|
+
# * String: Dedicated workspace path
|
86
|
+
def workspace_for(node)
|
87
|
+
workspace = "#{Dir.tmpdir}/hpc_local_workspaces/#{node}"
|
88
|
+
FileUtils.mkdir_p workspace
|
89
|
+
workspace
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -73,7 +73,7 @@ module HybridPlatformsConductor
|
|
73
73
|
# Result::
|
74
74
|
# * Array<String>: List of nodes we can connect to from the candidates
|
75
75
|
def connectable_nodes_from(nodes)
|
76
|
-
nodes.select { |node| @nodes_handler.
|
76
|
+
nodes.select { |node| @nodes_handler.get_host_ip_of(node) =~ /^192\.168\..+$/ }
|
77
77
|
end
|
78
78
|
|
79
79
|
# Prepare connections to a given set of nodes.
|
@@ -135,7 +135,7 @@ module HybridPlatformsConductor
|
|
135
135
|
# Parameters::
|
136
136
|
# * *from* (String): Local file to copy
|
137
137
|
# * *to* (String): Remote directory to copy to
|
138
|
-
# * *sudo* (Boolean): Do we use sudo to copy? [default: false]
|
138
|
+
# * *sudo* (Boolean): Do we use sudo on the remote to copy? [default: false]
|
139
139
|
# * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
|
140
140
|
# * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
|
141
141
|
def remote_copy(from, to, sudo: false, owner: nil, group: nil)
|
@@ -131,6 +131,10 @@ module HybridPlatformsConductor
|
|
131
131
|
# Default values
|
132
132
|
@ssh_user = ENV['hpc_ssh_user']
|
133
133
|
@ssh_user = ENV['USER'] if @ssh_user.nil? || @ssh_user.empty?
|
134
|
+
if @ssh_user.nil? || @ssh_user.empty?
|
135
|
+
_exit_status, stdout = @cmd_runner.run_cmd 'whoami', log_to_stdout: log_debug?
|
136
|
+
@ssh_user = stdout.strip
|
137
|
+
end
|
134
138
|
@ssh_use_control_master = true
|
135
139
|
@ssh_strict_host_key_checking = true
|
136
140
|
@passwords = {}
|
@@ -236,9 +240,9 @@ module HybridPlatformsConductor
|
|
236
240
|
ssh_cmd =
|
237
241
|
if @nodes_handler.get_ssh_session_exec_of(@node) == 'false'
|
238
242
|
# When ExecSession is disabled we need to use stdin directly
|
239
|
-
"{ cat | #{ssh_exec} #{ssh_url} -T; } <<'
|
243
|
+
"{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
|
240
244
|
else
|
241
|
-
"#{ssh_exec} #{ssh_url} /bin/bash <<'
|
245
|
+
"#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
|
242
246
|
end
|
243
247
|
# Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
|
244
248
|
# 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.
|
@@ -292,7 +296,7 @@ module HybridPlatformsConductor
|
|
292
296
|
# Parameters::
|
293
297
|
# * *from* (String): Local file to copy
|
294
298
|
# * *to* (String): Remote directory to copy to
|
295
|
-
# * *sudo* (Boolean): Do we use sudo to copy? [default: false]
|
299
|
+
# * *sudo* (Boolean): Do we use sudo on the remote to copy? [default: false]
|
296
300
|
# * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
|
297
301
|
# * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
|
298
302
|
def remote_copy(from, to, sudo: false, owner: nil, group: nil)
|
data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample
CHANGED
@@ -69,7 +69,7 @@ module HybridPlatformsConductor
|
|
69
69
|
end
|
70
70
|
|
71
71
|
# Setup the platform, install dependencies...
|
72
|
-
# [API] - This method is
|
72
|
+
# [API] - This method is optional.
|
73
73
|
# [API] - @cmd_runner is accessible.
|
74
74
|
def setup
|
75
75
|
# This method is called by the setup executable.
|
@@ -163,7 +163,7 @@ module HybridPlatformsConductor
|
|
163
163
|
end
|
164
164
|
|
165
165
|
# Package the repository, ready to be deployed on artefacts or directly to a node.
|
166
|
-
# [API] - This method is
|
166
|
+
# [API] - This method is optional.
|
167
167
|
# [API] - @cmd_runner is accessible.
|
168
168
|
# [API] - @actions_executor is accessible.
|
169
169
|
#
|
@@ -212,7 +212,7 @@ module HybridPlatformsConductor
|
|
212
212
|
# This method returns all the actions to execute to deploy on a node.
|
213
213
|
# The use_why_run switch is on if the deployment should just be simulated.
|
214
214
|
# Those actions (bash commands, scp of files, ruby code...) should be thread safe as they can be executed in parallel with other deployment actions for other nodes in case of a concurrent deployment on several nodes.
|
215
|
-
# The complete description of an action can be found in
|
215
|
+
# The complete description of an action can be found in the action plugins' documentation.
|
216
216
|
[
|
217
217
|
{
|
218
218
|
scp: {
|
@@ -229,7 +229,7 @@ module HybridPlatformsConductor
|
|
229
229
|
end
|
230
230
|
|
231
231
|
# Prepare a why-run deployment so that a JSON file describing the nodes will be output in the run_logs.
|
232
|
-
# [API] - This method is
|
232
|
+
# [API] - This method is optional.
|
233
233
|
# [API] - @cmd_runner is accessible.
|
234
234
|
# [API] - @actions_executor is accessible.
|
235
235
|
# [API] - @deployer is accessible.
|
@@ -247,7 +247,7 @@ module HybridPlatformsConductor
|
|
247
247
|
# Result::
|
248
248
|
# * Array< Hash<Symbol,Object> >: List of task properties. The following properties should be returned, among free ones:
|
249
249
|
# * *name* (String): Task name
|
250
|
-
# * *status* (Symbol): Task status. Should be
|
250
|
+
# * *status* (Symbol): Task status. Should be one of:
|
251
251
|
# * *:changed*: The task has been changed
|
252
252
|
# * *:identical*: The task has not been changed
|
253
253
|
# * *diffs* (String): Differences, if any
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'hybrid_platforms_conductor/platform_handler'
|
3
|
+
|
4
|
+
module HybridPlatformsConductor
|
5
|
+
|
6
|
+
module HpcPlugins
|
7
|
+
|
8
|
+
module PlatformHandler
|
9
|
+
|
10
|
+
# Basic platform handler, reading inventory and metadata from simple Yaml files.
|
11
|
+
class YamlInventory < HybridPlatformsConductor::PlatformHandler
|
12
|
+
|
13
|
+
# Initialize a new instance of this platform handler.
|
14
|
+
# [API] - This method is optional.
|
15
|
+
# [API] - @cmd_runner is accessible.
|
16
|
+
def init
|
17
|
+
# This method is called when initializing a new instance of this platform handler, for a given repository.
|
18
|
+
inv_file = "#{@repository_path}/inventory.yaml"
|
19
|
+
@inventory = File.exist?(inv_file) ? YAML.load(File.read(inv_file)) : {}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get the list of known nodes.
|
23
|
+
# [API] - This method is mandatory.
|
24
|
+
#
|
25
|
+
# Result::
|
26
|
+
# * Array<String>: List of node names
|
27
|
+
def known_nodes
|
28
|
+
@inventory.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
# Get the metadata of a given node.
|
32
|
+
# [API] - This method is mandatory.
|
33
|
+
#
|
34
|
+
# Parameters::
|
35
|
+
# * *node* (String): Node to read metadata from
|
36
|
+
# Result::
|
37
|
+
# * Hash<Symbol,Object>: The corresponding metadata
|
38
|
+
def metadata_for(node)
|
39
|
+
(@inventory[node]['metadata'] || {}).transform_keys(&:to_sym)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return the services for a given node
|
43
|
+
# [API] - This method is mandatory.
|
44
|
+
#
|
45
|
+
# Parameters::
|
46
|
+
# * *node* (String): node to read configuration from
|
47
|
+
# Result::
|
48
|
+
# * Array<String>: The corresponding services
|
49
|
+
def services_for(node)
|
50
|
+
@inventory[node]['services'] || []
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get the list of services we can deploy
|
54
|
+
# [API] - This method is mandatory.
|
55
|
+
#
|
56
|
+
# Result::
|
57
|
+
# * Array<String>: The corresponding services
|
58
|
+
def deployable_services
|
59
|
+
Dir.glob("#{@repository_path}/service_*.rb").map { |file| File.basename(file).match(/^service_(.*)\.rb$/)[1] }
|
60
|
+
end
|
61
|
+
|
62
|
+
# Get the list of actions to perform to deploy on a given node.
|
63
|
+
# Those actions can be executed in parallel with other deployments on other nodes. They must be thread safe.
|
64
|
+
# [API] - This method is mandatory.
|
65
|
+
# [API] - @cmd_runner is accessible.
|
66
|
+
# [API] - @actions_executor is accessible.
|
67
|
+
#
|
68
|
+
# Parameters::
|
69
|
+
# * *node* (String): Node to deploy on
|
70
|
+
# * *service* (String): Service to be deployed
|
71
|
+
# * *use_why_run* (Boolean): Do we use a why-run mode? [default = true]
|
72
|
+
# Result::
|
73
|
+
# * Array< Hash<Symbol,Object> >: List of actions to be done
|
74
|
+
def actions_to_deploy_on(node, service, use_why_run: true)
|
75
|
+
# Load the check and deploy methods in a temporary class for encapsulation
|
76
|
+
service_file = "#{@repository_path}/service_#{service}.rb"
|
77
|
+
Class.new do
|
78
|
+
|
79
|
+
include LoggerHelpers
|
80
|
+
|
81
|
+
# Constructor
|
82
|
+
#
|
83
|
+
# Parameters::
|
84
|
+
# * *platform_handler* (PlatformHandler): PlatformHandler needing this service to be deployed
|
85
|
+
# * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
|
86
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
87
|
+
# * *config* (Config): Config to be used. [default: Config.new]
|
88
|
+
# * *nodes_handler* (NodesHandler): NodesHandler to be used [default: NodesHandler.new]
|
89
|
+
# * *cmd_runner* (CmdRunner): CmdRunner to be used [default: CmdRunner.new]
|
90
|
+
def initialize(
|
91
|
+
platform_handler,
|
92
|
+
logger: Logger.new(STDOUT),
|
93
|
+
logger_stderr: Logger.new(STDERR),
|
94
|
+
config: Config.new,
|
95
|
+
nodes_handler: NodesHandler.new,
|
96
|
+
cmd_runner: CmdRunner.new
|
97
|
+
)
|
98
|
+
init_loggers(logger, logger_stderr)
|
99
|
+
@platform_handler = platform_handler
|
100
|
+
@config = config
|
101
|
+
@nodes_handler = nodes_handler
|
102
|
+
@cmd_runner = cmd_runner
|
103
|
+
end
|
104
|
+
|
105
|
+
class_eval(File.read(service_file))
|
106
|
+
|
107
|
+
end.new(
|
108
|
+
self,
|
109
|
+
logger: @logger,
|
110
|
+
logger_stderr: @logger_stderr,
|
111
|
+
config: @config,
|
112
|
+
nodes_handler: @nodes_handler,
|
113
|
+
cmd_runner: @cmd_runner
|
114
|
+
).send(use_why_run ? :check : :deploy, node)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Parse stdout and stderr of a given deploy run and get the list of tasks with their status
|
118
|
+
# [API] - This method is mandatory.
|
119
|
+
#
|
120
|
+
# Parameters::
|
121
|
+
# * *stdout* (String): stdout to be parsed
|
122
|
+
# * *stderr* (String): stderr to be parsed
|
123
|
+
# Result::
|
124
|
+
# * Array< Hash<Symbol,Object> >: List of task properties. The following properties should be returned, among free ones:
|
125
|
+
# * *name* (String): Task name
|
126
|
+
# * *status* (Symbol): Task status. Should be one of:
|
127
|
+
# * *:changed*: The task has been changed
|
128
|
+
# * *:identical*: The task has not been changed
|
129
|
+
# * *diffs* (String): Differences, if any
|
130
|
+
def parse_deploy_output(stdout, stderr)
|
131
|
+
[]
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|