hybrid_platforms_conductor 32.11.0 → 32.13.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 +1109 -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 +61 -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 +975 -0
- data/docs/tutorial/05_extend_with_plugins.md +1130 -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/examples/tutorial/01_installation/my-platforms/Gemfile +3 -0
- data/examples/tutorial/01_installation/my-platforms/hpc_config.rb +0 -0
- data/examples/tutorial/02_first_node/my-platforms/Gemfile +3 -0
- data/examples/tutorial/02_first_node/my-platforms/hpc_config.rb +1 -0
- data/examples/tutorial/02_first_node/my-service-conf-repo/inventory.yaml +13 -0
- data/examples/tutorial/02_first_node/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/02_first_node/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/02_first_node/node/my-service.conf +4 -0
- data/examples/tutorial/03_scale/my-platforms/Gemfile +3 -0
- data/examples/tutorial/03_scale/my-platforms/hpc_config.rb +1 -0
- data/examples/tutorial/03_scale/my-platforms/my_commands.bash +2 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/inventory.yaml +90 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/03_scale/my-service-conf-repo/service_web-hello.rb +43 -0
- data/examples/tutorial/03_scale/node/my-service.conf +4 -0
- data/examples/tutorial/03_scale/web_docker_image/Dockerfile +33 -0
- data/examples/tutorial/03_scale/web_docker_image/hello_world.txt +1 -0
- data/examples/tutorial/03_scale/web_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/03_scale/web_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/03_scale/web_docker_image/main.go +43 -0
- data/examples/tutorial/03_scale/web_docker_image/start.sh +7 -0
- data/examples/tutorial/03_scale/web_docker_image/test.bash +6 -0
- data/examples/tutorial/04_test/my-platforms/Gemfile +3 -0
- data/examples/tutorial/04_test/my-platforms/hpc_config.rb +12 -0
- data/examples/tutorial/04_test/my-platforms/images/debian_10/Dockerfile +13 -0
- data/examples/tutorial/04_test/my-platforms/my_commands.bash +2 -0
- data/examples/tutorial/04_test/my-service-conf-repo/inventory.yaml +100 -0
- data/examples/tutorial/04_test/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/04_test/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/04_test/my-service-conf-repo/service_web-hello.rb +43 -0
- data/examples/tutorial/04_test/node/my-service.conf +4 -0
- data/examples/tutorial/04_test/web_docker_image/Dockerfile +33 -0
- data/examples/tutorial/04_test/web_docker_image/hello_world.txt +1 -0
- data/examples/tutorial/04_test/web_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/04_test/web_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/04_test/web_docker_image/main.go +43 -0
- data/examples/tutorial/04_test/web_docker_image/start.sh +7 -0
- data/examples/tutorial/04_test/web_docker_image/test.bash +6 -0
- data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/hosts.json +12 -0
- data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-gcc.bash +14 -0
- data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-python.bash +14 -0
- data/examples/tutorial/05_extend_with_plugins/dev_docker_image/Dockerfile +20 -0
- data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/Gemfile +4 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/hpc_config.rb +13 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/images/debian_10/Dockerfile +13 -0
- data/examples/tutorial/05_extend_with_plugins/my-platforms/my_commands.bash +2 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/inventory.yaml +100 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/my-service.conf.erb +3 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_my-service.rb +58 -0
- data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_web-hello.rb +43 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/platform_handler/json_bash.rb +115 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/report/web_report.rb +52 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/test/root_space.rb +44 -0
- data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/my_hpc_plugins.gemspec +15 -0
- data/examples/tutorial/05_extend_with_plugins/node/my-service.conf +4 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/Dockerfile +33 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/hello_world.txt +1 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key +27 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key.pub +1 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/main.go +43 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/start.sh +7 -0
- data/examples/tutorial/05_extend_with_plugins/web_docker_image/test.bash +6 -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 +15 -4
- 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 +6 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/templates/confluence_inventory.html.erb +1 -1
- 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/executables.rb +27 -13
- 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/hpc_plugins/test_report/templates/confluence.html.erb +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 +37 -4
- data/spec/hybrid_platforms_conductor_test/docs_spec.rb +10 -0
- data/tools/check_md +89 -0
- data/tools/generate_mermaid +75 -0
- metadata +337 -12
@@ -0,0 +1,1130 @@
|
|
1
|
+
|
2
|
+
---
|
3
|
+
**<p style="text-align: center;">Tutorial navigation</p>**
|
4
|
+
|
5
|
+
| <sub>[Introduction](/docs/tutorial.md)</sub> | <sub>[1. Installation and first-time setup](/docs/tutorial/01_installation.md)</sub> | <sub>[2. Deploy and check a first node](/docs/tutorial/02_first_node.md)</sub> | <sub>[3. Scale your processes](/docs/tutorial/03_scale.md)</sub> | <sub>[4. Testing your processes and platforms](/docs/tutorial/04_test.md)</sub> | <nobr><sub><sub>👇You are here👇</sub></sub></nobr><br><sub>[5. Extend Hybrid Platforms Conductor with your own requirements](/docs/tutorial/05_extend_with_plugins.md)</sub> |
|
6
|
+
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
7
|
+
| <sub><sub>**[Use-case](/docs/tutorial.md#use-case)**</sub></sub> | <sub><sub>**[Dependencies installation](/docs/tutorial/01_installation.md#hpc-dependencies)**</sub></sub> | <sub><sub>**[Add your first node and its platform repository](/docs/tutorial/02_first_node.md#add-first-node)**</sub></sub> | <sub><sub>**[Provision our web services platform](/docs/tutorial/03_scale.md#provision)**</sub></sub> | <sub><sub>**[Hello test framework](/docs/tutorial/04_test.md#framework)**</sub></sub> | <sub><sub>**[Create your plugins' repository](/docs/tutorial/05_extend_with_plugins.md#plugins-repo)**</sub></sub> |
|
8
|
+
| <sub><sub>**[Prerequisites](/docs/tutorial.md#prerequisites)**</sub></sub> | <sub><sub>**[Our platforms' main repository](/docs/tutorial/01_installation.md#main-repo)**</sub></sub> | <sub><sub>**[Check and deploy services on this node](/docs/tutorial/02_first_node.md#check-deploy)**</sub></sub> | <sub><sub>**[Run commands on our new web services](/docs/tutorial/03_scale.md#run)**</sub></sub> | <sub><sub>**[Testing your nodes](/docs/tutorial/04_test.md#nodes-tests)**</sub></sub> | <sub><sub>**[Your own platform handler](/docs/tutorial/05_extend_with_plugins.md#platform-handler)**</sub></sub> |
|
9
|
+
| <sub><sub>**[Tutorial setup](/docs/tutorial.md#tutorial-setup)**</sub></sub> | | <sub><sub>**[Updating the configuration](/docs/tutorial/02_first_node.md#update)**</sub></sub> | <sub><sub>**[Check and deploy our web services on several nodes at once](/docs/tutorial/03_scale.md#check-deploy)**</sub></sub> | <sub><sub>**[Testing your platforms' configuration](/docs/tutorial/04_test.md#platforms-tests)**</sub></sub> | <sub><sub>**[Write your own tests](/docs/tutorial/05_extend_with_plugins.md#test)**</sub></sub> |
|
10
|
+
| | | | | <sub><sub>**[Other kinds of tests](/docs/tutorial/04_test.md#other-tests)**</sub></sub> | <sub><sub>**[Enough of stdout, we want to report to other tools](/docs/tutorial/05_extend_with_plugins.md#report)**</sub></sub> |
|
11
|
+
| | | | | | <sub><sub>**[What next?](/docs/tutorial/05_extend_with_plugins.md#what-next)**</sub></sub> |
|
12
|
+
|
13
|
+
# 5. Extend Hybrid Platforms Conductor with your own requirements
|
14
|
+
|
15
|
+
The plugins provided by default with Hybrid Platforms Conductor can help a lot in starting out, but every organization, every project has its own conventions, frameworks, tools.
|
16
|
+
|
17
|
+
**You should not change your current conventions and tools to adapt to Hybrid Platforms Conductor.
|
18
|
+
Hybrid Platforms Conductor has to adapt to your conventions, tools, platforms...**
|
19
|
+
|
20
|
+
It is with this mindset that all Hybrid Platform Conductor's processes have been designed.
|
21
|
+
To achieve this, [plugins](/docs/plugins.md) are used extensively in every part of the processes.
|
22
|
+
During this tutorial we already used a lot of them, but now we are going to see how to add new ones to match **your** requirements.
|
23
|
+
|
24
|
+
<a name="plugins-repo"></a>
|
25
|
+
## Create your plugins' repository
|
26
|
+
|
27
|
+
Plugins can be defined in any [Rubygem](https://guides.rubygems.org/what-is-a-gem/) that will have files named `lib/<gem_name>/hpc_plugins/<plugin_type>/<plugin_name>.rb`.
|
28
|
+
Then you just need to add your plugins' Rubygem your project and Hybrid Platforms Conductor will automatically discover all your plugins from there.
|
29
|
+
|
30
|
+
You can of course organize your plugins among several Rubygems the way you want, depending on the reusability of those plugins across your organization or even publish them as open source on [Rubygems.org](https://rubygems.org).
|
31
|
+
|
32
|
+
Let's start by creating your repository for plugins, structured as a Rubygem, and reference it in our main configuration project.
|
33
|
+
We'll call it `my_hpc_plugins`.
|
34
|
+
|
35
|
+
```bash
|
36
|
+
# Create an empty Rubygem repository named my_hpc_plugins
|
37
|
+
mkdir -p ~/hpc_tutorial/my_hpc_plugins
|
38
|
+
cat <<EOF >~/hpc_tutorial/my_hpc_plugins/my_hpc_plugins.gemspec
|
39
|
+
Gem::Specification.new do |s|
|
40
|
+
s.name = 'my_hpc_plugins'
|
41
|
+
s.version = '0.0.1'
|
42
|
+
s.date = '2021-04-29'
|
43
|
+
s.authors = ['Me myself!']
|
44
|
+
s.email = ['me-myself@my-domain.com']
|
45
|
+
s.summary = 'My awesome plugins for Hybrid Platforms Conductor'
|
46
|
+
s.files = Dir['{bin,lib,spec}/**/*']
|
47
|
+
Dir['bin/**/*'].each do |exec_name|
|
48
|
+
s.executables << File.basename(exec_name)
|
49
|
+
end
|
50
|
+
# Dependencies
|
51
|
+
# Make sure we use a compatible version of hybrid_platforms_conductor
|
52
|
+
s.add_dependency 'hybrid_platforms_conductor', '~> 32.12'
|
53
|
+
end
|
54
|
+
EOF
|
55
|
+
|
56
|
+
# Reference it in our configuration repository, in the Gemfile
|
57
|
+
cat <<EOF >>Gemfile
|
58
|
+
gem 'my_hpc_plugins', path: "#{Dir.home}/hpc_tutorial/my_hpc_plugins"
|
59
|
+
EOF
|
60
|
+
|
61
|
+
# Install dependencies now that we have added a new gem into our project
|
62
|
+
bundle install
|
63
|
+
# =>
|
64
|
+
# [...]
|
65
|
+
# Using pastel 0.8.0
|
66
|
+
# Using tty-command 0.10.1
|
67
|
+
# Using hybrid_platforms_conductor 32.12.0
|
68
|
+
# Using my_hpc_plugins 0.0.1 from source at `/root/hpc_tutorial/my_hpc_plugins`
|
69
|
+
# Bundle complete! 2 Gemfile dependencies, 46 gems now installed.
|
70
|
+
# Bundled gems are installed into `./vendor/bundle`
|
71
|
+
```
|
72
|
+
|
73
|
+
Now we can add the plugins we want in it.
|
74
|
+
|
75
|
+
<a name="platform-handler"></a>
|
76
|
+
## Your own platform handler
|
77
|
+
|
78
|
+
The most common use case is that you already have configuration repositories using Chef, Ansible, Puppet or even simple bash scripts.
|
79
|
+
Now you want to integrate those in Hybrid Platforms Conductor to benefit from all the simple interfaces and integration within well-defined DevOps processes.
|
80
|
+
|
81
|
+
So let's start with a new platform repository storing some configuration for hosts you are already handling.
|
82
|
+
|
83
|
+
We'll create a platform repository that you already use without Hybrid Platforms Conductor and works this way:
|
84
|
+
* It has a list of JSON files in a `nodes/` directory defining hostnames to configure and pointing to bash scripts installing services.
|
85
|
+
* It has a list of bash scripts that are installing services on a give host in a `services/` directory.
|
86
|
+
* Each service bash script takes 2 parameters: the hostname to configure and an optional `check` parameter that checks if the service is installed. You use those scripts directly from you command-line to check and install services on your nodes.
|
87
|
+
|
88
|
+
Let's say you use those scripts to configure development servers that need some tooling installed for your team (like gcc, cmake...) and that your team connects to them using ssh.
|
89
|
+
|
90
|
+
### Provision your dev servers that are configured by your platform repository
|
91
|
+
|
92
|
+
First, let's provision those development servers using some Docker containers from bare Debian images, and a `root` ssh key to connect to them.
|
93
|
+
The corresponding hostnames will be `devN.hpc_tutorial.org`:
|
94
|
+
```bash
|
95
|
+
mkdir -p ~/hpc_tutorial/dev_docker_image
|
96
|
+
|
97
|
+
# Generate root admin RSA keys
|
98
|
+
yes y | ssh-keygen -t rsa -b 2048 -C "admin@example.com" -f ~/hpc_tutorial/dev_docker_image/hpc_root.key -N ""
|
99
|
+
|
100
|
+
# The Dockerfile
|
101
|
+
cat <<EOF >~/hpc_tutorial/dev_docker_image/Dockerfile
|
102
|
+
# syntax=docker/dockerfile:1
|
103
|
+
# Pull the image containing Go
|
104
|
+
FROM debian:buster
|
105
|
+
|
106
|
+
# Install sshd
|
107
|
+
RUN apt-get update && apt-get install -y openssh-server
|
108
|
+
RUN mkdir /var/run/sshd
|
109
|
+
# Activate root login
|
110
|
+
RUN sed -i 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config
|
111
|
+
# Speed-up considerably ssh performance and avoid huge lags and timeouts without DNS
|
112
|
+
RUN sed -i 's/#UseDNS yes/UseDNS no/' /etc/ssh/sshd_config
|
113
|
+
EXPOSE 22
|
114
|
+
|
115
|
+
# Upload our root key for key authentication of root
|
116
|
+
COPY hpc_root.key.pub /root/.ssh/authorized_keys
|
117
|
+
RUN chmod 700 /root/.ssh
|
118
|
+
RUN chmod 400 /root/.ssh/authorized_keys
|
119
|
+
|
120
|
+
# Startup command
|
121
|
+
CMD ["/usr/sbin/sshd", "-D"]
|
122
|
+
EOF
|
123
|
+
|
124
|
+
# Build the Docker image named hpc_tutorial_dev
|
125
|
+
DOCKER_BUILDKIT=1 docker build -t hpc_tutorial_dev ~/hpc_tutorial/dev_docker_image
|
126
|
+
|
127
|
+
# Provision 10 dev servers named devN and add their hostnames to /etc/hosts
|
128
|
+
for ((i=1;i<=10;i++));
|
129
|
+
do
|
130
|
+
docker run --hostname "dev$i.hpc_tutorial.org" --name "dev$i" -P -d hpc_tutorial_dev
|
131
|
+
echo "$(docker container inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' dev$i) dev$i.hpc_tutorial.org" >>/etc/hosts
|
132
|
+
done
|
133
|
+
|
134
|
+
# Add the root SSH key to our agent
|
135
|
+
ssh-add ~/hpc_tutorial/dev_docker_image/hpc_root.key
|
136
|
+
```
|
137
|
+
|
138
|
+
We can check that our platform is provisioned with a simple test script:
|
139
|
+
```bash
|
140
|
+
for ((i=1;i<=10;i++));
|
141
|
+
do
|
142
|
+
ssh -o StrictHostKeyChecking=no root@dev$i.hpc_tutorial.org 'echo Hello $(hostname)!' 2>/dev/null
|
143
|
+
done
|
144
|
+
# =>
|
145
|
+
# Hello dev1.hpc_tutorial.org!
|
146
|
+
# Hello dev2.hpc_tutorial.org!
|
147
|
+
# Hello dev3.hpc_tutorial.org!
|
148
|
+
# Hello dev4.hpc_tutorial.org!
|
149
|
+
# Hello dev5.hpc_tutorial.org!
|
150
|
+
# Hello dev6.hpc_tutorial.org!
|
151
|
+
# Hello dev7.hpc_tutorial.org!
|
152
|
+
# Hello dev8.hpc_tutorial.org!
|
153
|
+
# Hello dev9.hpc_tutorial.org!
|
154
|
+
# Hello dev10.hpc_tutorial.org!
|
155
|
+
```
|
156
|
+
|
157
|
+
Please note that if we exit your Docker tutorial container and restart it, you will need to restart your dev containers and regenerate their hostname/ip in `/etc/hosts`.
|
158
|
+
This will be done this way (to be done each time you will restart your tutorial or dev containers):
|
159
|
+
```bash
|
160
|
+
for ((i=1;i<=10;i++));
|
161
|
+
do
|
162
|
+
docker container start dev$i
|
163
|
+
echo "$(docker container inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' dev$i) dev$i.hpc_tutorial.org" >>/etc/hosts
|
164
|
+
done
|
165
|
+
```
|
166
|
+
|
167
|
+
For info, here are what your docker containers and `/etc/hosts` should look like currently:
|
168
|
+
```bash
|
169
|
+
docker container list --all
|
170
|
+
# =>
|
171
|
+
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
172
|
+
# 9fd42bf48092 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49194->22/tcp dev10
|
173
|
+
# f88aa890875d hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49193->22/tcp dev9
|
174
|
+
# a1c4967c9e75 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49192->22/tcp dev8
|
175
|
+
# d1d361e43913 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49191->22/tcp dev7
|
176
|
+
# 83ee06f500a8 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49190->22/tcp dev6
|
177
|
+
# cc27dda93985 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49189->22/tcp dev5
|
178
|
+
# d5bc37e91408 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49188->22/tcp dev4
|
179
|
+
# 538d5b3503d5 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49187->22/tcp dev3
|
180
|
+
# 039cbb03734e hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49186->22/tcp dev2
|
181
|
+
# 8dbc7f911454 hpc_tutorial_dev "/usr/sbin/sshd -D" 2 minutes ago Up 2 minutes 0.0.0.0:49185->22/tcp dev1
|
182
|
+
# 87e6a31c21ea hpc_image_debian_10 "/usr/sbin/sshd -D" 25 hours ago Exited (0) 25 hours ago hpc_docker_container_web1_root_check_from_scratch
|
183
|
+
# fd6fe2331b86 hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49172->22/tcp, 0.0.0.0:49171->80/tcp web10
|
184
|
+
# af538c1db9ba hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49170->22/tcp, 0.0.0.0:49169->80/tcp web9
|
185
|
+
# 0fc004f8fafb hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49168->22/tcp, 0.0.0.0:49167->80/tcp web8
|
186
|
+
# cda9dfa98062 hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49166->22/tcp, 0.0.0.0:49165->80/tcp web7
|
187
|
+
# bea9d491774b hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49164->22/tcp, 0.0.0.0:49163->80/tcp web6
|
188
|
+
# 3869a1262c5a hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49162->22/tcp, 0.0.0.0:49161->80/tcp web5
|
189
|
+
# e886cc392725 hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49160->22/tcp, 0.0.0.0:49159->80/tcp web4
|
190
|
+
# aff2c221b724 hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49158->22/tcp, 0.0.0.0:49157->80/tcp web3
|
191
|
+
# 192d4f8e01af hpc_tutorial_web "/start.sh" 47 hours ago Up 42 minutes 0.0.0.0:49156->22/tcp, 0.0.0.0:49155->80/tcp web2
|
192
|
+
# b283d646c3fa hpc_tutorial_web "/start.sh" 47 hours ago Up 3 minutes 0.0.0.0:49184->22/tcp, 0.0.0.0:49183->80/tcp web1
|
193
|
+
# e8dddeb2ba25 debian:buster "/bin/bash" 3 days ago Up 45 minutes hpc_tutorial
|
194
|
+
|
195
|
+
cat /etc/hosts
|
196
|
+
# =>
|
197
|
+
# 127.0.0.1 localhost
|
198
|
+
# ::1 localhost ip6-localhost ip6-loopback
|
199
|
+
# fe00::0 ip6-localnet
|
200
|
+
# ff00::0 ip6-mcastprefix
|
201
|
+
# ff02::1 ip6-allnodes
|
202
|
+
# ff02::2 ip6-allrouters
|
203
|
+
# 172.17.0.2 e8dddeb2ba25
|
204
|
+
# 172.17.0.3 web1.hpc_tutorial.org
|
205
|
+
# 172.17.0.4 web2.hpc_tutorial.org
|
206
|
+
# 172.17.0.5 web3.hpc_tutorial.org
|
207
|
+
# 172.17.0.6 web4.hpc_tutorial.org
|
208
|
+
# 172.17.0.7 web5.hpc_tutorial.org
|
209
|
+
# 172.17.0.8 web6.hpc_tutorial.org
|
210
|
+
# 172.17.0.9 web7.hpc_tutorial.org
|
211
|
+
# 172.17.0.10 web8.hpc_tutorial.org
|
212
|
+
# 172.17.0.11 web9.hpc_tutorial.org
|
213
|
+
# 172.17.0.12 web10.hpc_tutorial.org
|
214
|
+
# 172.17.0.13 dev1.hpc_tutorial.org
|
215
|
+
# 172.17.0.14 dev2.hpc_tutorial.org
|
216
|
+
# 172.17.0.15 dev3.hpc_tutorial.org
|
217
|
+
# 172.17.0.16 dev4.hpc_tutorial.org
|
218
|
+
# 172.17.0.17 dev5.hpc_tutorial.org
|
219
|
+
# 172.17.0.18 dev6.hpc_tutorial.org
|
220
|
+
# 172.17.0.19 dev7.hpc_tutorial.org
|
221
|
+
# 172.17.0.20 dev8.hpc_tutorial.org
|
222
|
+
# 172.17.0.21 dev9.hpc_tutorial.org
|
223
|
+
# 172.17.0.22 dev10.hpc_tutorial.org
|
224
|
+
```
|
225
|
+
|
226
|
+
Now that we have provisioned a dev platform, let's create our platform repository, that should work without Hybrid Platforms Conductor's processes for now.
|
227
|
+
|
228
|
+
### Create your existing platform repository with your own processes
|
229
|
+
|
230
|
+
Let's say we have 2 kind of dev servers in our platform:
|
231
|
+
* `dev1` to `dev5` used for Python development.
|
232
|
+
* `dev6` to `dev10` used for C++ development.
|
233
|
+
|
234
|
+
We are using bash scripts that check and install requirements for those both environments:
|
235
|
+
```bash
|
236
|
+
mkdir -p ~/hpc_tutorial/dev-servers-conf-repo
|
237
|
+
|
238
|
+
# Bash script checking and installing Python on a hostname via ssh
|
239
|
+
cat <<EOF >~/hpc_tutorial/dev-servers-conf-repo/install-python.bash
|
240
|
+
hostname=\${1}
|
241
|
+
check_flag=\${2:-deploy}
|
242
|
+
if [ "\${check_flag}" = "check" ]; then
|
243
|
+
# Check if python3 is installed
|
244
|
+
if ssh -o StrictHostKeyChecking=no root@\${hostname} 'python3 --version' 2>/dev/null; then
|
245
|
+
echo 'OK'
|
246
|
+
else
|
247
|
+
echo 'Missing'
|
248
|
+
fi
|
249
|
+
else
|
250
|
+
# Install python3
|
251
|
+
ssh -o StrictHostKeyChecking=no root@\${hostname} 'apt install -y python3-pip' 2>/dev/null
|
252
|
+
echo 'Installed'
|
253
|
+
fi
|
254
|
+
EOF
|
255
|
+
chmod a+x ~/hpc_tutorial/dev-servers-conf-repo/install-python.bash
|
256
|
+
|
257
|
+
# Bash script checking and installing Python on a hostname via ssh
|
258
|
+
cat <<EOF >~/hpc_tutorial/dev-servers-conf-repo/install-gcc.bash
|
259
|
+
hostname=\${1}
|
260
|
+
check_flag=\${2:-deploy}
|
261
|
+
if [ "\${check_flag}" = "check" ]; then
|
262
|
+
# Check if gcc is installed
|
263
|
+
if ssh -o StrictHostKeyChecking=no root@\${hostname} 'gcc --version' 2>/dev/null; then
|
264
|
+
echo 'OK'
|
265
|
+
else
|
266
|
+
echo 'Missing'
|
267
|
+
fi
|
268
|
+
else
|
269
|
+
# Install gcc
|
270
|
+
ssh -o StrictHostKeyChecking=no root@\${hostname} 'apt install -y gcc' 2>/dev/null
|
271
|
+
echo 'Installed'
|
272
|
+
fi
|
273
|
+
EOF
|
274
|
+
chmod a+x ~/hpc_tutorial/dev-servers-conf-repo/install-gcc.bash
|
275
|
+
```
|
276
|
+
|
277
|
+
We can already check that our bash scripts work as expected by using them manually:
|
278
|
+
```bash
|
279
|
+
# Check that Python is not installed by default
|
280
|
+
~/hpc_tutorial/dev-servers-conf-repo/install-python.bash dev1.hpc_tutorial.org check
|
281
|
+
# => Missing
|
282
|
+
|
283
|
+
# Install Python
|
284
|
+
~/hpc_tutorial/dev-servers-conf-repo/install-python.bash dev1.hpc_tutorial.org
|
285
|
+
# =>
|
286
|
+
# [...]
|
287
|
+
# Setting up python3-dev (3.7.3-1) ...
|
288
|
+
# Setting up python3-keyring (17.1.1-1) ...
|
289
|
+
# Processing triggers for libc-bin (2.28-10) ...
|
290
|
+
# Processing triggers for ca-certificates (20200601~deb10u2) ...
|
291
|
+
# Updating certificates in /etc/ssl/certs...
|
292
|
+
# 0 added, 0 removed; done.
|
293
|
+
# Running hooks in /etc/ca-certificates/update.d...
|
294
|
+
# done.
|
295
|
+
# Installed
|
296
|
+
|
297
|
+
# Check that Python is reported as installed
|
298
|
+
~/hpc_tutorial/dev-servers-conf-repo/install-python.bash dev1.hpc_tutorial.org check
|
299
|
+
# =>
|
300
|
+
# Python 3.7.3
|
301
|
+
# OK
|
302
|
+
|
303
|
+
# Check that gcc is not installed by default
|
304
|
+
~/hpc_tutorial/dev-servers-conf-repo/install-gcc.bash dev6.hpc_tutorial.org check
|
305
|
+
# => Missing
|
306
|
+
|
307
|
+
# Install gcc
|
308
|
+
~/hpc_tutorial/dev-servers-conf-repo/install-gcc.bash dev6.hpc_tutorial.org
|
309
|
+
# =>
|
310
|
+
# [...]
|
311
|
+
# Setting up libgcc-8-dev:amd64 (8.3.0-6) ...
|
312
|
+
# Setting up cpp (4:8.3.0-1) ...
|
313
|
+
# Setting up libc6-dev:amd64 (2.28-10) ...
|
314
|
+
# Setting up gcc-8 (8.3.0-6) ...
|
315
|
+
# Setting up gcc (4:8.3.0-1) ...
|
316
|
+
# Processing triggers for libc-bin (2.28-10) ...
|
317
|
+
# Installed
|
318
|
+
|
319
|
+
# Check that gcc is reported as installed
|
320
|
+
~/hpc_tutorial/dev-servers-conf-repo/install-gcc.bash dev6.hpc_tutorial.org check
|
321
|
+
# =>
|
322
|
+
# gcc (Debian 8.3.0-6) 8.3.0
|
323
|
+
# Copyright (C) 2018 Free Software Foundation, Inc.
|
324
|
+
# This is free software; see the source for copying conditions. There is NO
|
325
|
+
# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
326
|
+
#
|
327
|
+
# OK
|
328
|
+
```
|
329
|
+
|
330
|
+
Now let's create our small inventory JSON file that tells which hostname has which service:
|
331
|
+
```bash
|
332
|
+
cat <<EOF >~/hpc_tutorial/dev-servers-conf-repo/hosts.json
|
333
|
+
{
|
334
|
+
"dev1.hpc_tutorial.org": "python",
|
335
|
+
"dev2.hpc_tutorial.org": "python",
|
336
|
+
"dev3.hpc_tutorial.org": "python",
|
337
|
+
"dev4.hpc_tutorial.org": "python",
|
338
|
+
"dev5.hpc_tutorial.org": "python",
|
339
|
+
"dev6.hpc_tutorial.org": "gcc",
|
340
|
+
"dev7.hpc_tutorial.org": "gcc",
|
341
|
+
"dev8.hpc_tutorial.org": "gcc",
|
342
|
+
"dev9.hpc_tutorial.org": "gcc",
|
343
|
+
"dev10.hpc_tutorial.org": "gcc"
|
344
|
+
}
|
345
|
+
EOF
|
346
|
+
```
|
347
|
+
|
348
|
+
So here we are: a full platform repository containing some inventory and bash scripts that we can use to check and deploy services on this platform, following some existing tooling and conventions in your team.
|
349
|
+
|
350
|
+
Let's see what does it take to integrate this new platform repository into Hybrid Platforms Conductor by writing your own [`platform_handler` plugin](/docs/plugins.md#platform_handler).
|
351
|
+
|
352
|
+
### Write a simple platform handler that can handle your existing repository
|
353
|
+
|
354
|
+
A [`platform_handler` plugin](/docs/plugins.md#platform_handler) handles a given kind of platform repository, and has basically 2 roles:
|
355
|
+
* Provide **inventory** information (nodes defined, their metadata, the services they are hosting...).
|
356
|
+
* Provide **services** information (how to check/deploy services on a node).
|
357
|
+
|
358
|
+
So let's write a new plugin handling your repository.
|
359
|
+
Like any plugin, we create a file named `lib/<gem_name>/hpc_plugins/<plugin_type>/<plugin_name>.rb` that define a simple class inherting from a plugin's class.
|
360
|
+
Here is the code of our plugin:
|
361
|
+
```ruby
|
362
|
+
require 'json'
|
363
|
+
require 'hybrid_platforms_conductor/platform_handler'
|
364
|
+
|
365
|
+
module MyHpcPlugins
|
366
|
+
|
367
|
+
module HpcPlugins
|
368
|
+
|
369
|
+
module PlatformHandler
|
370
|
+
|
371
|
+
# A nice platform handler to handle platforms of our team, using json inventory and bash scripts.
|
372
|
+
class JsonBash < HybridPlatformsConductor::PlatformHandler
|
373
|
+
|
374
|
+
# Get the list of known nodes.
|
375
|
+
# [API] - This method is mandatory.
|
376
|
+
#
|
377
|
+
# Result::
|
378
|
+
# * Array<String>: List of node names
|
379
|
+
def known_nodes
|
380
|
+
# This method is used to get the list of nodes that are handled by the platform
|
381
|
+
# In our case we read our json file to get this information, and use just the first part of the hostname as the node's name.
|
382
|
+
JSON.parse(File.read("#{repository_path}/hosts.json")).keys.map { |hostname| hostname.split('.').first }
|
383
|
+
end
|
384
|
+
|
385
|
+
# Get the metadata of a given node.
|
386
|
+
# [API] - This method is mandatory.
|
387
|
+
#
|
388
|
+
# Parameters::
|
389
|
+
# * *node* (String): Node to read metadata from
|
390
|
+
# Result::
|
391
|
+
# * Hash<Symbol,Object>: The corresponding metadata
|
392
|
+
def metadata_for(node)
|
393
|
+
# All nodes handled by this platform are running a debian buster image and we derive their name from their hostname.
|
394
|
+
{
|
395
|
+
hostname: "#{node}.hpc_tutorial.org",
|
396
|
+
image: 'debian_10'
|
397
|
+
}
|
398
|
+
end
|
399
|
+
|
400
|
+
# Return the services for a given node
|
401
|
+
# [API] - This method is mandatory.
|
402
|
+
#
|
403
|
+
# Parameters::
|
404
|
+
# * *node* (String): node to read configuration from
|
405
|
+
# Result::
|
406
|
+
# * Array<String>: The corresponding services
|
407
|
+
def services_for(node)
|
408
|
+
# This info is taken from our JSON inventory file
|
409
|
+
[JSON.parse(File.read("#{repository_path}/hosts.json"))["#{node}.hpc_tutorial.org"]]
|
410
|
+
end
|
411
|
+
|
412
|
+
# Get the list of services we can deploy
|
413
|
+
# [API] - This method is mandatory.
|
414
|
+
#
|
415
|
+
# Result::
|
416
|
+
# * Array<String>: The corresponding services
|
417
|
+
def deployable_services
|
418
|
+
# This info is taken by listing existing bash scripts
|
419
|
+
Dir.glob("#{repository_path}/install-*.bash").map { |file| File.basename(file).match(/install-(.*)\.bash/)[1] }
|
420
|
+
end
|
421
|
+
|
422
|
+
# Get the list of actions to perform to deploy on a given node.
|
423
|
+
# Those actions can be executed in parallel with other deployments on other nodes. They must be thread safe.
|
424
|
+
# [API] - This method is mandatory.
|
425
|
+
# [API] - @cmd_runner is accessible.
|
426
|
+
# [API] - @actions_executor is accessible.
|
427
|
+
#
|
428
|
+
# Parameters::
|
429
|
+
# * *node* (String): Node to deploy on
|
430
|
+
# * *service* (String): Service to be deployed
|
431
|
+
# * *use_why_run* (Boolean): Do we use a why-run mode? [default = true]
|
432
|
+
# Result::
|
433
|
+
# * Array< Hash<Symbol,Object> >: List of actions to be done
|
434
|
+
def actions_to_deploy_on(node, service, use_why_run: true)
|
435
|
+
# This method returns all the actions to execute to deploy on a node.
|
436
|
+
# The use_why_run switch is on if the deployment should just be simulated.
|
437
|
+
# 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.
|
438
|
+
# In our case it's very simple: we just call our bash script on the node's hostname.
|
439
|
+
[{ bash: "#{repository_path}/install-#{service}.bash #{@nodes_handler.get_hostname_of(node)} #{use_why_run ? 'check' : ''}" }]
|
440
|
+
end
|
441
|
+
|
442
|
+
# Parse stdout and stderr of a given deploy run and get the list of tasks with their status
|
443
|
+
# [API] - This method is mandatory.
|
444
|
+
#
|
445
|
+
# Parameters::
|
446
|
+
# * *stdout* (String): stdout to be parsed
|
447
|
+
# * *stderr* (String): stderr to be parsed
|
448
|
+
# Result::
|
449
|
+
# * Array< Hash<Symbol,Object> >: List of task properties. The following properties should be returned, among free ones:
|
450
|
+
# * *name* (String): Task name
|
451
|
+
# * *status* (Symbol): Task status. Should be one of:
|
452
|
+
# * *:changed*: The task has been changed
|
453
|
+
# * *:identical*: The task has not been changed
|
454
|
+
# * *diffs* (String): Differences, if any
|
455
|
+
def parse_deploy_output(stdout, stderr)
|
456
|
+
# In our case our bash scripts return the last line as a status, so use it.
|
457
|
+
[{
|
458
|
+
name: 'Install tool',
|
459
|
+
status:
|
460
|
+
case stdout.split("\n").last
|
461
|
+
when 'OK'
|
462
|
+
:identical
|
463
|
+
else
|
464
|
+
:changed
|
465
|
+
end,
|
466
|
+
diffs: stdout
|
467
|
+
}]
|
468
|
+
end
|
469
|
+
|
470
|
+
end
|
471
|
+
|
472
|
+
end
|
473
|
+
|
474
|
+
end
|
475
|
+
|
476
|
+
end
|
477
|
+
```
|
478
|
+
|
479
|
+
Let's write it in our Rubygem:
|
480
|
+
```bash
|
481
|
+
mkdir -p ~/hpc_tutorial/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/platform_handler
|
482
|
+
cat <<EOF >~/hpc_tutorial/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/platform_handler/json_bash.rb
|
483
|
+
# --- Copy-paste the previous Ruby code here ---
|
484
|
+
EOF
|
485
|
+
```
|
486
|
+
|
487
|
+
And now we can reference our platform repository `~/hpc_tutorial/dev-servers-conf-repo` as a platform of type `json_bash`.
|
488
|
+
Let's do it in the main configuration `hpc_config.rb`:
|
489
|
+
```bash
|
490
|
+
cat <<EOF >>hpc_config.rb
|
491
|
+
json_bash_platform path: "#{Dir.home}/hpc_tutorial/dev-servers-conf-repo"
|
492
|
+
EOF
|
493
|
+
```
|
494
|
+
|
495
|
+
And that's it!
|
496
|
+
Nothing else is needed to have all the Hybrid Platforms Conductor processes use your new platform.
|
497
|
+
|
498
|
+
Let's check this with the processes we already know, applied to all our platforms (local, web services and now dev servers):
|
499
|
+
```bash
|
500
|
+
# Check the whole inventory
|
501
|
+
./bin/report
|
502
|
+
# =>
|
503
|
+
# +-------+-----------------------+------------------------+-------------+-----------+-----------+-----------------------+-----------------------+
|
504
|
+
# | Node | Platform | Host name | IP | Physical? | OS | Description | Services |
|
505
|
+
# +-------+-----------------------+------------------------+-------------+-----------+-----------+-----------------------+-----------------------+
|
506
|
+
# | dev1 | dev-servers-conf-repo | dev1.hpc_tutorial.org | 172.17.0.13 | No | debian_10 | | python |
|
507
|
+
# | dev10 | dev-servers-conf-repo | dev10.hpc_tutorial.org | 172.17.0.22 | No | debian_10 | | gcc |
|
508
|
+
# | dev2 | dev-servers-conf-repo | dev2.hpc_tutorial.org | 172.17.0.14 | No | debian_10 | | python |
|
509
|
+
# | dev3 | dev-servers-conf-repo | dev3.hpc_tutorial.org | 172.17.0.15 | No | debian_10 | | python |
|
510
|
+
# | dev4 | dev-servers-conf-repo | dev4.hpc_tutorial.org | 172.17.0.16 | No | debian_10 | | python |
|
511
|
+
# | dev5 | dev-servers-conf-repo | dev5.hpc_tutorial.org | 172.17.0.17 | No | debian_10 | | python |
|
512
|
+
# | dev6 | dev-servers-conf-repo | dev6.hpc_tutorial.org | 172.17.0.18 | No | debian_10 | | gcc |
|
513
|
+
# | dev7 | dev-servers-conf-repo | dev7.hpc_tutorial.org | 172.17.0.19 | No | debian_10 | | gcc |
|
514
|
+
# | dev8 | dev-servers-conf-repo | dev8.hpc_tutorial.org | 172.17.0.20 | No | debian_10 | | gcc |
|
515
|
+
# | dev9 | dev-servers-conf-repo | dev9.hpc_tutorial.org | 172.17.0.21 | No | debian_10 | | gcc |
|
516
|
+
# | local | my-service-conf-repo | | | No | | The local environment | my-service |
|
517
|
+
# | web1 | my-service-conf-repo | web1.hpc_tutorial.org | 172.17.0.3 | No | debian_10 | Web service nbr 1 | my-service, web-hello |
|
518
|
+
# | web10 | my-service-conf-repo | web10.hpc_tutorial.org | 172.17.0.12 | No | debian_10 | Web service nbr 10 | web-hello |
|
519
|
+
# | web2 | my-service-conf-repo | web2.hpc_tutorial.org | 172.17.0.4 | No | debian_10 | Web service nbr 2 | my-service, web-hello |
|
520
|
+
# | web3 | my-service-conf-repo | web3.hpc_tutorial.org | 172.17.0.5 | No | debian_10 | Web service nbr 3 | my-service, web-hello |
|
521
|
+
# | web4 | my-service-conf-repo | web4.hpc_tutorial.org | 172.17.0.6 | No | debian_10 | Web service nbr 4 | my-service, web-hello |
|
522
|
+
# | web5 | my-service-conf-repo | web5.hpc_tutorial.org | 172.17.0.7 | No | debian_10 | Web service nbr 5 | my-service, web-hello |
|
523
|
+
# | web6 | my-service-conf-repo | web6.hpc_tutorial.org | 172.17.0.8 | No | debian_10 | Web service nbr 6 | web-hello |
|
524
|
+
# | web7 | my-service-conf-repo | web7.hpc_tutorial.org | 172.17.0.9 | No | debian_10 | Web service nbr 7 | web-hello |
|
525
|
+
# | web8 | my-service-conf-repo | web8.hpc_tutorial.org | 172.17.0.10 | No | debian_10 | Web service nbr 8 | web-hello |
|
526
|
+
# | web9 | my-service-conf-repo | web9.hpc_tutorial.org | 172.17.0.11 | No | debian_10 | Web service nbr 9 | web-hello |
|
527
|
+
# +-------+-----------------------+------------------------+-------------+-----------+-----------+-----------------------+-----------------------+
|
528
|
+
|
529
|
+
# Can we connect and run commands everywhere?
|
530
|
+
./bin/run --all --command 'echo Hello from $(hostname)'
|
531
|
+
# =>
|
532
|
+
# Hello from dev1.hpc_tutorial.org
|
533
|
+
# Hello from dev10.hpc_tutorial.org
|
534
|
+
# Hello from dev2.hpc_tutorial.org
|
535
|
+
# Hello from dev3.hpc_tutorial.org
|
536
|
+
# Hello from dev4.hpc_tutorial.org
|
537
|
+
# Hello from dev5.hpc_tutorial.org
|
538
|
+
# Hello from dev6.hpc_tutorial.org
|
539
|
+
# Hello from dev7.hpc_tutorial.org
|
540
|
+
# Hello from dev8.hpc_tutorial.org
|
541
|
+
# Hello from dev9.hpc_tutorial.org
|
542
|
+
# Hello from e8dddeb2ba25
|
543
|
+
# Hello from web1.hpc_tutorial.org
|
544
|
+
# Hello from web10.hpc_tutorial.org
|
545
|
+
# Hello from web2.hpc_tutorial.org
|
546
|
+
# Hello from web3.hpc_tutorial.org
|
547
|
+
# Hello from web4.hpc_tutorial.org
|
548
|
+
# Hello from web5.hpc_tutorial.org
|
549
|
+
# Hello from web6.hpc_tutorial.org
|
550
|
+
# Hello from web7.hpc_tutorial.org
|
551
|
+
# Hello from web8.hpc_tutorial.org
|
552
|
+
# Hello from web9.hpc_tutorial.org
|
553
|
+
|
554
|
+
# Can we check a dev server?
|
555
|
+
./bin/check-node --node dev1
|
556
|
+
# =>
|
557
|
+
# ===== Packaging deployment ==== Begin...
|
558
|
+
# ===== Packaging deployment ==== ...End
|
559
|
+
#
|
560
|
+
# ===== Checking on 1 nodes ==== Begin...
|
561
|
+
# ===== [ dev1 / python ] - HPC Service Check ===== Begin
|
562
|
+
# ===== [ dev1 / python ] - HPC Service Check ===== Begin
|
563
|
+
# Python 3.7.3
|
564
|
+
# OK
|
565
|
+
# ===== [ dev1 / python ] - HPC Service Check ===== End
|
566
|
+
# ===== [ dev1 / python ] - HPC Service Check ===== End
|
567
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 1 - Total: 1 ]
|
568
|
+
# ===== Checking on 1 nodes ==== ...End
|
569
|
+
|
570
|
+
# Can we test our dev servers for spectre vulnerabilities?
|
571
|
+
./bin/test --node /dev/ --test spectre
|
572
|
+
# =>
|
573
|
+
# ===== Run 10 connected tests ==== Begin...
|
574
|
+
# ===== Run test commands on 10 connected nodes (timeout to 50 secs) ==== Begin...
|
575
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 10 - Total: 10 ]
|
576
|
+
# ===== Run test commands on 10 connected nodes (timeout to 50 secs) ==== ...End
|
577
|
+
#
|
578
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev1 ] - [ spectre ] - Start test...
|
579
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev1 ] - [ spectre ] - Test finished in 0.001014909 seconds.
|
580
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev10 ] - [ spectre ] - Start test...
|
581
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev10 ] - [ spectre ] - Test finished in 0.000775197 seconds.
|
582
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev2 ] - [ spectre ] - Start test...
|
583
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev2 ] - [ spectre ] - Test finished in 0.000576852 seconds.
|
584
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev3 ] - [ spectre ] - Start test...
|
585
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev3 ] - [ spectre ] - Test finished in 0.00043014 seconds.
|
586
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev4 ] - [ spectre ] - Start test...
|
587
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev4 ] - [ spectre ] - Test finished in 0.000708113 seconds.
|
588
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev5 ] - [ spectre ] - Start test...
|
589
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev5 ] - [ spectre ] - Test finished in 0.000220576 seconds.
|
590
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev6 ] - [ spectre ] - Start test...
|
591
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev6 ] - [ spectre ] - Test finished in 0.000458778 seconds.
|
592
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev7 ] - [ spectre ] - Start test...
|
593
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev7 ] - [ spectre ] - Test finished in 0.000219419 seconds.
|
594
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev8 ] - [ spectre ] - Start test...
|
595
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev8 ] - [ spectre ] - Test finished in 0.000209414 seconds.
|
596
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev9 ] - [ spectre ] - Start test...
|
597
|
+
# [ 2021-04-30 13:32:23 ] - [ Node dev9 ] - [ spectre ] - Test finished in 0.000406352 seconds.
|
598
|
+
# ===== Run 10 connected tests ==== ...End
|
599
|
+
#
|
600
|
+
#
|
601
|
+
# ========== Error report of 10 tests run on 10 nodes
|
602
|
+
#
|
603
|
+
# ======= 0 unexpected failing global tests:
|
604
|
+
#
|
605
|
+
#
|
606
|
+
# ======= 0 unexpected failing platform tests:
|
607
|
+
#
|
608
|
+
#
|
609
|
+
# ======= 0 unexpected failing node tests:
|
610
|
+
#
|
611
|
+
#
|
612
|
+
# ======= 0 unexpected failing platforms:
|
613
|
+
#
|
614
|
+
#
|
615
|
+
# ======= 0 unexpected failing nodes:
|
616
|
+
#
|
617
|
+
#
|
618
|
+
# ========== Stats by nodes list:
|
619
|
+
#
|
620
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
621
|
+
# | List name | # nodes | % tested | % expected success | % success | [Expected] [Error] [Success] [Non tested] |
|
622
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
623
|
+
# | No list | 21 | 47 % | 100 % | 100 % | ========================================= |
|
624
|
+
# | All | 21 | 47 % | 100 % | 100 % | ========================================= |
|
625
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
626
|
+
#
|
627
|
+
# ===== No unexpected errors =====
|
628
|
+
|
629
|
+
# Can we deploy some dev servers?
|
630
|
+
./bin/deploy --node /dev\[4-7\]/
|
631
|
+
# =>
|
632
|
+
# ===== Packaging deployment ==== Begin...
|
633
|
+
# ===== Packaging deployment ==== ...End
|
634
|
+
#
|
635
|
+
# ===== Deploying on 4 nodes ==== Begin...
|
636
|
+
# ===== [ dev4 / python ] - HPC Service Deploy ===== Begin
|
637
|
+
# ===== [ dev4 / python ] - HPC Service Deploy ===== Begin
|
638
|
+
# [...]
|
639
|
+
# ===== [ dev7 / gcc ] - HPC Service Deploy ===== End
|
640
|
+
# ===== [ dev7 / gcc ] - HPC Service Deploy ===== End
|
641
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 4 - Total: 4 ]
|
642
|
+
# ===== Saving deployment logs for 4 nodes ==== Begin...
|
643
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 4 - Total: 4 ]
|
644
|
+
# ===== Saving deployment logs for 4 nodes ==== ...End
|
645
|
+
#
|
646
|
+
# ===== Deploying on 4 nodes ==== ...End
|
647
|
+
|
648
|
+
# Can we check last deployments everywhere?
|
649
|
+
./bin/last_deploys
|
650
|
+
# =>
|
651
|
+
# +-------+---------------------+-------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
652
|
+
# | Node | Date | Admin | Services | Error |
|
653
|
+
# +-------+---------------------+-------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
654
|
+
# | dev1 | | | | Error: failed_command |
|
655
|
+
# | | | | | /bin/bash: line 1: cd: /var/log/deployments: No such file or directory |
|
656
|
+
# | | | | | Command '/tmp/hpc_ssh/platforms_ssh_5222020210430-2889-lctc2/ssh hpc.dev1 /bin/bash <<'HPC_EOF'' returned error code 1 (expected 0). |
|
657
|
+
# | dev10 | | | | Error: failed_command |
|
658
|
+
# | | | | | /bin/bash: line 1: cd: /var/log/deployments: No such file or directory |
|
659
|
+
# | | | | | Command '/tmp/hpc_ssh/platforms_ssh_5222020210430-2889-lctc2/ssh hpc.dev10 /bin/bash <<'HPC_EOF'' returned error code 1 (expected 0). |
|
660
|
+
# | dev2 | | | | Error: failed_command |
|
661
|
+
# | | | | | /bin/bash: line 1: cd: /var/log/deployments: No such file or directory |
|
662
|
+
# | | | | | Command '/tmp/hpc_ssh/platforms_ssh_5222020210430-2889-lctc2/ssh hpc.dev2 /bin/bash <<'HPC_EOF'' returned error code 1 (expected 0). |
|
663
|
+
# | dev3 | | | | Error: failed_command |
|
664
|
+
# | | | | | /bin/bash: line 1: cd: /var/log/deployments: No such file or directory |
|
665
|
+
# | | | | | Command '/tmp/hpc_ssh/platforms_ssh_5222020210430-2889-lctc2/ssh hpc.dev3 /bin/bash <<'HPC_EOF'' returned error code 1 (expected 0). |
|
666
|
+
# | dev8 | | | | Error: failed_command |
|
667
|
+
# | | | | | /bin/bash: line 1: cd: /var/log/deployments: No such file or directory |
|
668
|
+
# | | | | | Command '/tmp/hpc_ssh/platforms_ssh_5222020210430-2889-lctc2/ssh hpc.dev8 /bin/bash <<'HPC_EOF'' returned error code 1 (expected 0). |
|
669
|
+
# | dev9 | | | | Error: failed_command |
|
670
|
+
# | | | | | /bin/bash: line 1: cd: /var/log/deployments: No such file or directory |
|
671
|
+
# | | | | | Command '/tmp/hpc_ssh/platforms_ssh_5222020210430-2889-lctc2/ssh hpc.dev9 /bin/bash <<'HPC_EOF'' returned error code 1 (expected 0). |
|
672
|
+
# | dev4 | 2021-04-30 13:36:21 | root | python | |
|
673
|
+
# | dev5 | 2021-04-30 13:36:21 | root | python | |
|
674
|
+
# | dev6 | 2021-04-30 13:36:21 | root | gcc | |
|
675
|
+
# | dev7 | 2021-04-30 13:36:21 | root | gcc | |
|
676
|
+
# | local | 2021-04-28 17:34:17 | root | my-service | |
|
677
|
+
# | web1 | 2021-04-28 17:34:17 | root | web-hello, my-service | |
|
678
|
+
# | web10 | 2021-04-28 17:34:17 | root | web-hello | |
|
679
|
+
# | web2 | 2021-04-28 17:34:17 | root | web-hello, my-service | |
|
680
|
+
# | web3 | 2021-04-28 17:34:17 | root | web-hello, my-service | |
|
681
|
+
# | web4 | 2021-04-28 17:34:17 | root | web-hello, my-service | |
|
682
|
+
# | web5 | 2021-04-28 17:34:17 | root | web-hello, my-service | |
|
683
|
+
# | web6 | 2021-04-28 17:34:17 | root | web-hello | |
|
684
|
+
# | web7 | 2021-04-28 17:34:17 | root | web-hello | |
|
685
|
+
# | web8 | 2021-04-28 17:34:17 | root | web-hello | |
|
686
|
+
# | web9 | 2021-04-28 17:34:17 | root | web-hello | |
|
687
|
+
# +-------+---------------------+-------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------+
|
688
|
+
```
|
689
|
+
|
690
|
+
That's a lot of processes that are now made available to every node handled by our platform repository, with just 1 single plugin and without having to modify anything on your team's repository!
|
691
|
+
|
692
|
+
As a bonus, your platform handler plugin also reported ways to parse the check or deploy logs to analyze them in terms of tasks (see the `parse_deploy_output` last method from the plugin we just wrote).
|
693
|
+
This opens up a new process in Hybrid Platforms Conductor: the checks for divergence or idempotence.
|
694
|
+
By knowing tasks' statuses from a deployment or a check, we can report if the nodes need changes or not.
|
695
|
+
The [`divergence` test plugin](/docs/plugins/test/divergence.md) is using this information to report nodes that are not aligned.
|
696
|
+
|
697
|
+
See it in action:
|
698
|
+
```bash
|
699
|
+
./bin/test --test divergence --node /dev/
|
700
|
+
# ===== Run 10 check-node tests ==== Begin...
|
701
|
+
# ===== Packaging deployment ==== Begin...
|
702
|
+
# ===== Packaging deployment ==== ...End
|
703
|
+
#
|
704
|
+
# ===== Checking on 10 nodes ==== Begin...
|
705
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 10 - Total: 10 ]
|
706
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 10 - Total: 10 ]
|
707
|
+
# ===== Checking on 10 nodes ==== ...End
|
708
|
+
#
|
709
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev1 ] - [ divergence ] - Start test...
|
710
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev1 ] - [ divergence ] - Test finished in 0.000292363 seconds.
|
711
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev10 ] - [ divergence ] - Start test...
|
712
|
+
# [2021-04-30 13:43:32 (PID 3316 / TID 62000)] ERROR - [ Divergence ] - [ #< Test divergence - Node dev10 > ] - Task Install tool has diverged
|
713
|
+
# ----- Changes:
|
714
|
+
# Missing
|
715
|
+
# -----
|
716
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev10 ] - [ divergence ] - Test finished in 0.000465428 seconds.
|
717
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev2 ] - [ divergence ] - Start test...
|
718
|
+
# [2021-04-30 13:43:32 (PID 3316 / TID 62000)] ERROR - [ Divergence ] - [ #< Test divergence - Node dev2 > ] - Task Install tool has diverged
|
719
|
+
# ----- Changes:
|
720
|
+
# Missing
|
721
|
+
# -----
|
722
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev2 ] - [ divergence ] - Test finished in 0.000382199 seconds.
|
723
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev3 ] - [ divergence ] - Start test...
|
724
|
+
# [2021-04-30 13:43:32 (PID 3316 / TID 62000)] ERROR - [ Divergence ] - [ #< Test divergence - Node dev3 > ] - Task Install tool has diverged
|
725
|
+
# ----- Changes:
|
726
|
+
# Missing
|
727
|
+
# -----
|
728
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev3 ] - [ divergence ] - Test finished in 0.000380728 seconds.
|
729
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev4 ] - [ divergence ] - Start test...
|
730
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev4 ] - [ divergence ] - Test finished in 0.000169298 seconds.
|
731
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev5 ] - [ divergence ] - Start test...
|
732
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev5 ] - [ divergence ] - Test finished in 0.00020049 seconds.
|
733
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev6 ] - [ divergence ] - Start test...
|
734
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev6 ] - [ divergence ] - Test finished in 0.000195422 seconds.
|
735
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev7 ] - [ divergence ] - Start test...
|
736
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev7 ] - [ divergence ] - Test finished in 0.000218584 seconds.
|
737
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev8 ] - [ divergence ] - Start test...
|
738
|
+
# [2021-04-30 13:43:32 (PID 3316 / TID 62000)] ERROR - [ Divergence ] - [ #< Test divergence - Node dev8 > ] - Task Install tool has diverged
|
739
|
+
# ----- Changes:
|
740
|
+
# Missing
|
741
|
+
# -----
|
742
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev8 ] - [ divergence ] - Test finished in 0.000323749 seconds.
|
743
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev9 ] - [ divergence ] - Start test...
|
744
|
+
# [2021-04-30 13:43:32 (PID 3316 / TID 62000)] ERROR - [ Divergence ] - [ #< Test divergence - Node dev9 > ] - Task Install tool has diverged
|
745
|
+
# ----- Changes:
|
746
|
+
# Missing
|
747
|
+
# -----
|
748
|
+
# [ 2021-04-30 13:43:32 ] - [ Node dev9 ] - [ divergence ] - Test finished in 0.000242289 seconds.
|
749
|
+
# ===== Run 10 check-node tests ==== ...End
|
750
|
+
#
|
751
|
+
#
|
752
|
+
# ========== Error report of 10 tests run on 10 nodes
|
753
|
+
#
|
754
|
+
# ======= 0 unexpected failing global tests:
|
755
|
+
#
|
756
|
+
#
|
757
|
+
# ======= 0 unexpected failing platform tests:
|
758
|
+
#
|
759
|
+
#
|
760
|
+
# ======= 1 unexpected failing node tests:
|
761
|
+
#
|
762
|
+
# ===== divergence found 5 nodes having errors:
|
763
|
+
# * [ dev10 ] - 1 errors:
|
764
|
+
# - Task Install tool has diverged
|
765
|
+
# * [ dev2 ] - 1 errors:
|
766
|
+
# - Task Install tool has diverged
|
767
|
+
# * [ dev3 ] - 1 errors:
|
768
|
+
# - Task Install tool has diverged
|
769
|
+
# * [ dev8 ] - 1 errors:
|
770
|
+
# - Task Install tool has diverged
|
771
|
+
# * [ dev9 ] - 1 errors:
|
772
|
+
# - Task Install tool has diverged
|
773
|
+
#
|
774
|
+
#
|
775
|
+
# ======= 0 unexpected failing platforms:
|
776
|
+
#
|
777
|
+
#
|
778
|
+
# ======= 5 unexpected failing nodes:
|
779
|
+
#
|
780
|
+
# ===== dev10 has 1 failing tests:
|
781
|
+
# * [ divergence ] - 1 errors:
|
782
|
+
# - Task Install tool has diverged
|
783
|
+
#
|
784
|
+
# ===== dev2 has 1 failing tests:
|
785
|
+
# * [ divergence ] - 1 errors:
|
786
|
+
# - Task Install tool has diverged
|
787
|
+
#
|
788
|
+
# ===== dev3 has 1 failing tests:
|
789
|
+
# * [ divergence ] - 1 errors:
|
790
|
+
# - Task Install tool has diverged
|
791
|
+
#
|
792
|
+
# ===== dev8 has 1 failing tests:
|
793
|
+
# * [ divergence ] - 1 errors:
|
794
|
+
# - Task Install tool has diverged
|
795
|
+
#
|
796
|
+
# ===== dev9 has 1 failing tests:
|
797
|
+
# * [ divergence ] - 1 errors:
|
798
|
+
# - Task Install tool has diverged
|
799
|
+
#
|
800
|
+
#
|
801
|
+
# ========== Stats by nodes list:
|
802
|
+
#
|
803
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
804
|
+
# | List name | # nodes | % tested | % expected success | % success | [Expected] [Error] [Success] [Non tested] |
|
805
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
806
|
+
# | No list | 21 | 47 % | 100 % | 50 % | ========================================= |
|
807
|
+
# | All | 21 | 47 % | 100 % | 50 % | ========================================= |
|
808
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
809
|
+
#
|
810
|
+
# ===== Some errors were found. Check output. =====
|
811
|
+
```
|
812
|
+
|
813
|
+
Here we see that nodes `dev2`, `dev3`, `dev8`, `dev9` and `dev10` all have a diverging task named `Install tool`.
|
814
|
+
Logs above show us more details about the divergence, and we see that the reason is the `Missing` reported message, which is expected as we didn't deploy those nodes yet.
|
815
|
+
|
816
|
+
So now you are ready to write as many platform handlers as you have kinds of platform repositories.
|
817
|
+
|
818
|
+
Let's see other kinds of plugins.
|
819
|
+
|
820
|
+
<a name="test"></a>
|
821
|
+
## Write your own tests
|
822
|
+
|
823
|
+
Another common plugin type you'll want to write are [tests](/docs/plugins.md#test).
|
824
|
+
Nothing is easier: a test plugin basically defines 1 test method and uses assertion methods in there to check and report errors.
|
825
|
+
Depending on the scope of your test (on your nodes, your platforms or global), the method name will be different (`test_on_node`, `test_on_platform` or `test`).
|
826
|
+
|
827
|
+
Let's add a test on our nodes that checks for the size used in the `/root` folder of our nodes.
|
828
|
+
We don't want this folder to store too many data, so we'll report errors if it uses more than 1MB of files.
|
829
|
+
We'll use the command [`du`](https://man7.org/linux/man-pages/man1/du.1.html) for that and parse easily its output.
|
830
|
+
|
831
|
+
Here is the code of our test plugin:
|
832
|
+
```ruby
|
833
|
+
module MyHpcPlugins
|
834
|
+
|
835
|
+
module HpcPlugins
|
836
|
+
|
837
|
+
module Test
|
838
|
+
|
839
|
+
# Check root space
|
840
|
+
class RootSpace < HybridPlatformsConductor::Test
|
841
|
+
|
842
|
+
# Run test using SSH commands on the node.
|
843
|
+
# Instead of executing the SSH commands directly on each node for each test, this method returns the list of commands to run and the test framework then groups them in 1 SSH connection.
|
844
|
+
# [API] - @node can be used to adapt the command with the node.
|
845
|
+
#
|
846
|
+
# Result::
|
847
|
+
# * Hash<String,Object>: For each command to execute, information regarding the assertion.
|
848
|
+
# * Values can be:
|
849
|
+
# * Proc: The code block making the test given the stdout of the command. Here is the Proc description:
|
850
|
+
# * Parameters::
|
851
|
+
# * *stdout* (Array<String>): List of lines of the stdout of the command.
|
852
|
+
# * *stderr* (Array<String>): List of lines of the stderr of the command.
|
853
|
+
# * *return_code* (Integer): The return code of the command.
|
854
|
+
# * Hash<Symbol,Object>: More complete information, that can contain the following keys:
|
855
|
+
# * *validator* (Proc): The proc containing the assertions to perform (as described above). This key is mandatory.
|
856
|
+
# * *timeout* (Integer): Timeout to wait for this command to execute.
|
857
|
+
def test_on_node
|
858
|
+
# If this method is defined, it will be used to execute SSH commands on each node that is being tested.
|
859
|
+
# For each SSH command, a validator code block will be called with the stdout of the command run remotely on the node.
|
860
|
+
# In place of a simple validator code block, a more complex structure can be used to give more info (for example timeout).
|
861
|
+
{
|
862
|
+
'du -sk /root' => proc do |stdout|
|
863
|
+
# stdout contains the output of our du command
|
864
|
+
used_kb = stdout.first.split.first.to_i
|
865
|
+
error "Root space used is #{used_kb}KB - too much!" if used_kb > 1024
|
866
|
+
end
|
867
|
+
}
|
868
|
+
end
|
869
|
+
|
870
|
+
end
|
871
|
+
|
872
|
+
end
|
873
|
+
|
874
|
+
end
|
875
|
+
|
876
|
+
end
|
877
|
+
```
|
878
|
+
|
879
|
+
Let's write it in our Rubygem:
|
880
|
+
```bash
|
881
|
+
mkdir -p ~/hpc_tutorial/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/test
|
882
|
+
cat <<EOF >~/hpc_tutorial/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/test/root_space.rb
|
883
|
+
# --- Copy-paste the previous Ruby code here ---
|
884
|
+
EOF
|
885
|
+
```
|
886
|
+
|
887
|
+
And now let's put some big files in some of our `devN` nodes' `root` account to simulate space filling up:
|
888
|
+
```bash
|
889
|
+
./bin/run --node /dev\[5-7\]/ --command 'dd if=/dev/zero of=/root/big_file bs=1024 count=2048'
|
890
|
+
# =>
|
891
|
+
# 2048+0 records in
|
892
|
+
# 2048+0 records out
|
893
|
+
# 2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.0138115 s, 152 MB/s
|
894
|
+
# 2048+0 records in
|
895
|
+
# 2048+0 records out
|
896
|
+
# 2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.00515761 s, 407 MB/s
|
897
|
+
# 2048+0 records in
|
898
|
+
# 2048+0 records out
|
899
|
+
# 2097152 bytes (2.1 MB, 2.0 MiB) copied, 0.0044817 s, 468 MB/s
|
900
|
+
```
|
901
|
+
|
902
|
+
Time to check that our test plugin works out-of-the-box :D
|
903
|
+
```bash
|
904
|
+
./bin/test --node /dev/ --test root_space
|
905
|
+
# =>
|
906
|
+
# ===== Run 10 connected tests ==== Begin...
|
907
|
+
# ===== Run test commands on 10 connected nodes (timeout to 25 secs) ==== Begin...
|
908
|
+
# Executing actions [100%] - | C| - [ Queue: 0 - Processing: 0 - Done: 10 - Total: 10 ]
|
909
|
+
# ===== Run test commands on 10 connected nodes (timeout to 25 secs) ==== ...End
|
910
|
+
#
|
911
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev1 ] - [ root_space ] - Start test...
|
912
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev1 ] - [ root_space ] - Test finished in 0.000240216 seconds.
|
913
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev10 ] - [ root_space ] - Start test...
|
914
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev10 ] - [ root_space ] - Test finished in 0.000139912 seconds.
|
915
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev2 ] - [ root_space ] - Start test...
|
916
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev2 ] - [ root_space ] - Test finished in 0.00011111 seconds.
|
917
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev3 ] - [ root_space ] - Start test...
|
918
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev3 ] - [ root_space ] - Test finished in 4.0237e-05 seconds.
|
919
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev4 ] - [ root_space ] - Start test...
|
920
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev4 ] - [ root_space ] - Test finished in 4.4058e-05 seconds.
|
921
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev5 ] - [ root_space ] - Start test...
|
922
|
+
# [2021-04-30 14:15:51 (PID 4077 / TID 56180)] ERROR - [ RootSpace ] - [ #< Test root_space - Node dev5 > ] - Root space used is 2076KB - too much!
|
923
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev5 ] - [ root_space ] - Test finished in 0.002698342 seconds.
|
924
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev6 ] - [ root_space ] - Start test...
|
925
|
+
# [2021-04-30 14:15:51 (PID 4077 / TID 56180)] ERROR - [ RootSpace ] - [ #< Test root_space - Node dev6 > ] - Root space used is 2076KB - too much!
|
926
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev6 ] - [ root_space ] - Test finished in 0.000527592 seconds.
|
927
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev7 ] - [ root_space ] - Start test...
|
928
|
+
# [2021-04-30 14:15:51 (PID 4077 / TID 56180)] ERROR - [ RootSpace ] - [ #< Test root_space - Node dev7 > ] - Root space used is 2076KB - too much!
|
929
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev7 ] - [ root_space ] - Test finished in 0.000327025 seconds.
|
930
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev8 ] - [ root_space ] - Start test...
|
931
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev8 ] - [ root_space ] - Test finished in 3.0503e-05 seconds.
|
932
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev9 ] - [ root_space ] - Start test...
|
933
|
+
# [ 2021-04-30 14:15:51 ] - [ Node dev9 ] - [ root_space ] - Test finished in 0.000231408 seconds.
|
934
|
+
# ===== Run 10 connected tests ==== ...End
|
935
|
+
#
|
936
|
+
#
|
937
|
+
# ========== Error report of 10 tests run on 10 nodes
|
938
|
+
#
|
939
|
+
# ======= 0 unexpected failing global tests:
|
940
|
+
#
|
941
|
+
#
|
942
|
+
# ======= 0 unexpected failing platform tests:
|
943
|
+
#
|
944
|
+
#
|
945
|
+
# ======= 1 unexpected failing node tests:
|
946
|
+
#
|
947
|
+
# ===== root_space found 3 nodes having errors:
|
948
|
+
# * [ dev5 ] - 1 errors:
|
949
|
+
# - Root space used is 2076KB - too much!
|
950
|
+
# * [ dev6 ] - 1 errors:
|
951
|
+
# - Root space used is 2076KB - too much!
|
952
|
+
# * [ dev7 ] - 1 errors:
|
953
|
+
# - Root space used is 2076KB - too much!
|
954
|
+
#
|
955
|
+
#
|
956
|
+
# ======= 0 unexpected failing platforms:
|
957
|
+
#
|
958
|
+
#
|
959
|
+
# ======= 3 unexpected failing nodes:
|
960
|
+
#
|
961
|
+
# ===== dev5 has 1 failing tests:
|
962
|
+
# * [ root_space ] - 1 errors:
|
963
|
+
# - Root space used is 2076KB - too much!
|
964
|
+
#
|
965
|
+
# ===== dev6 has 1 failing tests:
|
966
|
+
# * [ root_space ] - 1 errors:
|
967
|
+
# - Root space used is 2076KB - too much!
|
968
|
+
#
|
969
|
+
# ===== dev7 has 1 failing tests:
|
970
|
+
# * [ root_space ] - 1 errors:
|
971
|
+
# - Root space used is 2076KB - too much!
|
972
|
+
#
|
973
|
+
#
|
974
|
+
# ========== Stats by nodes list:
|
975
|
+
#
|
976
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
977
|
+
# | List name | # nodes | % tested | % expected success | % success | [Expected] [Error] [Success] [Non tested] |
|
978
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
979
|
+
# | No list | 21 | 47 % | 100 % | 70 % | ========================================= |
|
980
|
+
# | All | 21 | 47 % | 100 % | 70 % | ========================================= |
|
981
|
+
# +-----------+---------+----------+--------------------+-----------+-------------------------------------------+
|
982
|
+
#
|
983
|
+
# ===== Some errors were found. Check output. =====
|
984
|
+
```
|
985
|
+
Indeed we see that `dev5`, `dev6` and `dev7` are failing the test.
|
986
|
+
|
987
|
+
<a name="report"></a>
|
988
|
+
## Enough of stdout, we want to report to other tools
|
989
|
+
|
990
|
+
Being able to have all your processes at your terminal's fingertips is great, but what if you want to integrate to other reporting, monitoring or auditing tools?
|
991
|
+
|
992
|
+
A simple way to do is to write your own [`report` plugin](/docs/plugins.md#report) for inventory reporting, or [`test_report` plugin](/docs/plugins.md#test_report) for tests results reporting.
|
993
|
+
From such plugins you could push your reports to external APIs, and therefore populate data from other tools, CMDBs, monitoring, without duplicating the source of your inventory.
|
994
|
+
|
995
|
+
So let's say one of our web services (`web10`) is in fact a disguised reporting tool that should display our inventory ;-)
|
996
|
+
Remember how those web services were just displaying the content of the file `/root/hello_world.txt`?
|
997
|
+
Now we want `web10` to be a reporting tool that has to display our inventory.
|
998
|
+
For that we'll create a report plugin that will publish to our `web10` instance.
|
999
|
+
|
1000
|
+
Here is the code of our report plugin:
|
1001
|
+
```ruby
|
1002
|
+
require 'hybrid_platforms_conductor/report'
|
1003
|
+
|
1004
|
+
module MyHpcPlugins
|
1005
|
+
|
1006
|
+
module HpcPlugins
|
1007
|
+
|
1008
|
+
module Report
|
1009
|
+
|
1010
|
+
# Publish reports to our web reporting tool
|
1011
|
+
class WebReport < HybridPlatformsConductor::Report
|
1012
|
+
|
1013
|
+
# Give the list of supported locales by this report generator
|
1014
|
+
# [API] - This method is mandatory.
|
1015
|
+
#
|
1016
|
+
# Result::
|
1017
|
+
# * Array<Symbol>: List of supported locales
|
1018
|
+
def self.supported_locales
|
1019
|
+
# This method has to publish the list of translations it accepts.
|
1020
|
+
[:en]
|
1021
|
+
end
|
1022
|
+
|
1023
|
+
# Create a report for a list of nodes, in a given locale
|
1024
|
+
# [API] - This method is mandatory.
|
1025
|
+
#
|
1026
|
+
# Parameters::
|
1027
|
+
# * *nodes* (Array<String>): List of nodes
|
1028
|
+
# * *locale_code* (Symbol): The locale code
|
1029
|
+
def report_for(nodes, locale_code)
|
1030
|
+
# This method simply provides a report for a given list of nodes in the desired locale.
|
1031
|
+
# The locale will be one of the supported ones.
|
1032
|
+
# Generate the report in a file to be uploaded on web10.
|
1033
|
+
File.write(
|
1034
|
+
'/tmp/web_report.txt',
|
1035
|
+
@platforms_handler.known_platforms.map do |platform|
|
1036
|
+
"= Inventory for platform #{platform.repository_path} of type #{platform.platform_type}:\n" +
|
1037
|
+
platform.known_nodes.map do |node|
|
1038
|
+
"* Node #{node} (IP: #{@nodes_handler.get_host_ip_of(node)}, Hostname: #{@nodes_handler.get_hostname_of(node)})."
|
1039
|
+
end.join("\n")
|
1040
|
+
end.join("\n")
|
1041
|
+
)
|
1042
|
+
# Upload the file on our web10 instance
|
1043
|
+
system 'scp -o StrictHostKeyChecking=no /tmp/web_report.txt root@web10.hpc_tutorial.org:/root/hello_world.txt'
|
1044
|
+
out 'Upload successful'
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
end
|
1050
|
+
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
end
|
1054
|
+
```
|
1055
|
+
|
1056
|
+
Let's write it in our Rubygem:
|
1057
|
+
```bash
|
1058
|
+
mkdir -p ~/hpc_tutorial/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/report
|
1059
|
+
cat <<EOF >~/hpc_tutorial/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/report/web_report.rb
|
1060
|
+
# --- Copy-paste the previous Ruby code here ---
|
1061
|
+
EOF
|
1062
|
+
```
|
1063
|
+
|
1064
|
+
And now we can use our new report plugin to publish to our web reporting tool:
|
1065
|
+
```bash
|
1066
|
+
./bin/report --format web_report
|
1067
|
+
# =>
|
1068
|
+
# web_report.txt 100% 1483 3.1MB/s 00:00
|
1069
|
+
# Upload successful
|
1070
|
+
```
|
1071
|
+
|
1072
|
+
And we can check our new web reporting tool :D
|
1073
|
+
```bash
|
1074
|
+
curl http://web10.hpc_tutorial.org
|
1075
|
+
# =>
|
1076
|
+
# = Inventory for platform /root/hpc_tutorial/my-service-conf-repo of type yaml_inventory:
|
1077
|
+
# * Node local (IP: , Hostname: ).
|
1078
|
+
# * Node web1 (IP: 172.17.0.3, Hostname: web1.hpc_tutorial.org).
|
1079
|
+
# * Node web2 (IP: 172.17.0.4, Hostname: web2.hpc_tutorial.org).
|
1080
|
+
# * Node web3 (IP: 172.17.0.5, Hostname: web3.hpc_tutorial.org).
|
1081
|
+
# * Node web4 (IP: 172.17.0.6, Hostname: web4.hpc_tutorial.org).
|
1082
|
+
# * Node web5 (IP: 172.17.0.7, Hostname: web5.hpc_tutorial.org).
|
1083
|
+
# * Node web6 (IP: 172.17.0.8, Hostname: web6.hpc_tutorial.org).
|
1084
|
+
# * Node web7 (IP: 172.17.0.9, Hostname: web7.hpc_tutorial.org).
|
1085
|
+
# * Node web8 (IP: 172.17.0.10, Hostname: web8.hpc_tutorial.org).
|
1086
|
+
# * Node web9 (IP: 172.17.0.11, Hostname: web9.hpc_tutorial.org).
|
1087
|
+
# * Node web10 (IP: 172.17.0.12, Hostname: web10.hpc_tutorial.org).
|
1088
|
+
# = Inventory for platform /root/hpc_tutorial/dev-servers-conf-repo of type json_bash:
|
1089
|
+
# * Node dev1 (IP: 172.17.0.13, Hostname: dev1.hpc_tutorial.org).
|
1090
|
+
# * Node dev2 (IP: 172.17.0.14, Hostname: dev2.hpc_tutorial.org).
|
1091
|
+
# * Node dev3 (IP: 172.17.0.15, Hostname: dev3.hpc_tutorial.org).
|
1092
|
+
# * Node dev4 (IP: 172.17.0.16, Hostname: dev4.hpc_tutorial.org).
|
1093
|
+
# * Node dev5 (IP: 172.17.0.17, Hostname: dev5.hpc_tutorial.org).
|
1094
|
+
# * Node dev6 (IP: 172.17.0.18, Hostname: dev6.hpc_tutorial.org).
|
1095
|
+
# * Node dev7 (IP: 172.17.0.19, Hostname: dev7.hpc_tutorial.org).
|
1096
|
+
# * Node dev8 (IP: 172.17.0.20, Hostname: dev8.hpc_tutorial.org).
|
1097
|
+
# * Node dev9 (IP: 172.17.0.21, Hostname: dev9.hpc_tutorial.org).
|
1098
|
+
# * Node dev10 (IP: 172.17.0.22, Hostname: dev10.hpc_tutorial.org).
|
1099
|
+
```
|
1100
|
+
|
1101
|
+
It works like a charm!
|
1102
|
+
|
1103
|
+
**Now you have plenty of ways to integrate your processes with Hybrid Platforms Conductor, and integrate Hybrid Platforms Conductor with other processes as well.**
|
1104
|
+
|
1105
|
+
The goal is for you to be agile and handle your inventory and platforms without duplicating information and efforts, and still keeping your heterogenous environments.
|
1106
|
+
Then you can apply simple and normalized DevOps processes that can encompass all your platforms so that you operate and test them uniformely.
|
1107
|
+
|
1108
|
+
<a name="what-next"></a>
|
1109
|
+
## What next?
|
1110
|
+
|
1111
|
+
This concludes this simple tutorial.
|
1112
|
+
We hope it gave you a good glimpse of the power of Hybrid Platforms Conductor and how it helps you easily integrate heterogenous technologies into simple, agile and robust DevOps processes.
|
1113
|
+
|
1114
|
+
From now one, you are ready to dive deeper into the details:
|
1115
|
+
* The various [executables](/docs/executables.md) available will cover much more than what we've seen in this tutorial. Their processes is documented there, as well their dependencies.
|
1116
|
+
* The various [plugins](/docs/plugins.md) available can already fill some of your needs, and otherwise they can serve as examples for you to write your own, so looking into them is really insightful.
|
1117
|
+
* The [API](/docs/api.md) itself can be used from inside your plugins (in fact you already did it in the plugins you wrote in this tutorial), and also from any Ruby project. Having a good understanding of the API's organization will help you a lot.
|
1118
|
+
|
1119
|
+
We would love to reference your plugins as well here if you make them publicly available. Please don't refrain: if it's useful to you it will certainly be useful to others.
|
1120
|
+
|
1121
|
+
---
|
1122
|
+
**<p style="text-align: center;">Tutorial navigation</p>**
|
1123
|
+
|
1124
|
+
| <sub>[Introduction](/docs/tutorial.md)</sub> | <sub>[1. Installation and first-time setup](/docs/tutorial/01_installation.md)</sub> | <sub>[2. Deploy and check a first node](/docs/tutorial/02_first_node.md)</sub> | <sub>[3. Scale your processes](/docs/tutorial/03_scale.md)</sub> | <sub>[4. Testing your processes and platforms](/docs/tutorial/04_test.md)</sub> | <nobr><sub><sub>👇You are here👇</sub></sub></nobr><br><sub>[5. Extend Hybrid Platforms Conductor with your own requirements](/docs/tutorial/05_extend_with_plugins.md)</sub> |
|
1125
|
+
| ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
1126
|
+
| <sub><sub>**[Use-case](/docs/tutorial.md#use-case)**</sub></sub> | <sub><sub>**[Dependencies installation](/docs/tutorial/01_installation.md#hpc-dependencies)**</sub></sub> | <sub><sub>**[Add your first node and its platform repository](/docs/tutorial/02_first_node.md#add-first-node)**</sub></sub> | <sub><sub>**[Provision our web services platform](/docs/tutorial/03_scale.md#provision)**</sub></sub> | <sub><sub>**[Hello test framework](/docs/tutorial/04_test.md#framework)**</sub></sub> | <sub><sub>**[Create your plugins' repository](/docs/tutorial/05_extend_with_plugins.md#plugins-repo)**</sub></sub> |
|
1127
|
+
| <sub><sub>**[Prerequisites](/docs/tutorial.md#prerequisites)**</sub></sub> | <sub><sub>**[Our platforms' main repository](/docs/tutorial/01_installation.md#main-repo)**</sub></sub> | <sub><sub>**[Check and deploy services on this node](/docs/tutorial/02_first_node.md#check-deploy)**</sub></sub> | <sub><sub>**[Run commands on our new web services](/docs/tutorial/03_scale.md#run)**</sub></sub> | <sub><sub>**[Testing your nodes](/docs/tutorial/04_test.md#nodes-tests)**</sub></sub> | <sub><sub>**[Your own platform handler](/docs/tutorial/05_extend_with_plugins.md#platform-handler)**</sub></sub> |
|
1128
|
+
| <sub><sub>**[Tutorial setup](/docs/tutorial.md#tutorial-setup)**</sub></sub> | | <sub><sub>**[Updating the configuration](/docs/tutorial/02_first_node.md#update)**</sub></sub> | <sub><sub>**[Check and deploy our web services on several nodes at once](/docs/tutorial/03_scale.md#check-deploy)**</sub></sub> | <sub><sub>**[Testing your platforms' configuration](/docs/tutorial/04_test.md#platforms-tests)**</sub></sub> | <sub><sub>**[Write your own tests](/docs/tutorial/05_extend_with_plugins.md#test)**</sub></sub> |
|
1129
|
+
| | | | | <sub><sub>**[Other kinds of tests](/docs/tutorial/04_test.md#other-tests)**</sub></sub> | <sub><sub>**[Enough of stdout, we want to report to other tools](/docs/tutorial/05_extend_with_plugins.md#report)**</sub></sub> |
|
1130
|
+
| | | | | | <sub><sub>**[What next?](/docs/tutorial/05_extend_with_plugins.md#what-next)**</sub></sub> |
|