hybrid_platforms_conductor 32.17.0 → 33.0.2
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 +36 -0
- data/README.md +6 -3
- data/bin/check-node +0 -1
- data/bin/deploy +0 -1
- data/bin/get_impacted_nodes +0 -1
- data/bin/last_deploys +12 -8
- data/bin/nodes_to_deploy +6 -6
- data/bin/setup +6 -6
- data/bin/topograph +1 -1
- data/docs/config_dsl.md +45 -1
- data/docs/executables.md +6 -7
- data/docs/executables/check-node.md +3 -3
- data/docs/executables/deploy.md +3 -3
- data/docs/executables/dump_nodes_json.md +3 -3
- data/docs/executables/test.md +3 -3
- data/docs/executables/topograph.md +3 -3
- 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/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/ssh_config.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
- data/docs/plugins.md +46 -0
- data/docs/plugins/connector/ssh.md +1 -1
- data/docs/plugins/log/remote_fs.md +26 -0
- data/docs/plugins/secrets_reader/cli.md +31 -0
- data/docs/plugins/secrets_reader/thycotic.md +46 -0
- data/docs/plugins/test/check_deploy_and_idempotence.md +1 -1
- data/docs/plugins/test/connection.md +1 -0
- data/docs/plugins/test/deploy_removes_root_access.md +1 -1
- data/docs/plugins/test/file_system.md +1 -0
- data/docs/plugins/test/hostname.md +1 -0
- data/docs/plugins/test/ip.md +1 -0
- data/docs/plugins/test/local_users.md +1 -0
- data/docs/plugins/test/mounts.md +1 -0
- data/docs/plugins/test/orphan_files.md +1 -0
- data/docs/plugins/test/ports.md +1 -0
- data/docs/plugins/test/spectre.md +1 -0
- data/docs/plugins/test/vulnerabilities.md +1 -0
- data/lib/hybrid_platforms_conductor/action.rb +4 -4
- data/lib/hybrid_platforms_conductor/actions_executor.rb +45 -43
- data/lib/hybrid_platforms_conductor/bitbucket.rb +5 -4
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +13 -12
- data/lib/hybrid_platforms_conductor/cmdb.rb +2 -2
- data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +2 -1
- data/lib/hybrid_platforms_conductor/common_config_dsl/confluence.rb +2 -1
- data/lib/hybrid_platforms_conductor/common_config_dsl/file_system_tests.rb +5 -4
- data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +4 -3
- data/lib/hybrid_platforms_conductor/common_config_dsl/idempotence_tests.rb +2 -2
- data/lib/hybrid_platforms_conductor/config.rb +8 -4
- data/lib/hybrid_platforms_conductor/confluence.rb +1 -1
- data/lib/hybrid_platforms_conductor/connector.rb +5 -2
- data/lib/hybrid_platforms_conductor/core_extensions/cleanroom/fix_kwargs.rb +116 -0
- data/lib/hybrid_platforms_conductor/core_extensions/symbol/zero.rb +24 -0
- data/lib/hybrid_platforms_conductor/credentials.rb +39 -36
- data/lib/hybrid_platforms_conductor/current_dir_monitor.rb +4 -1
- data/lib/hybrid_platforms_conductor/deployer.rb +275 -224
- data/lib/hybrid_platforms_conductor/executable.rb +20 -15
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/config.rb +10 -7
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_ip.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/platform_handlers.rb +4 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +2 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +45 -49
- data/lib/hybrid_platforms_conductor/hpc_plugins/log/my_log_plugin.rb.sample +100 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +180 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +68 -66
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +13 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +39 -38
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/yaml_inventory.rb +5 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +43 -45
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +18 -20
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +118 -117
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/proxmox_waiter.rb +39 -43
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +9 -13
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/mediawiki.rb +28 -21
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/stdout.rb +26 -22
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/cli.rb +77 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/my_secrets_reader_plugin.rb.sample +46 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +90 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +3 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +4 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +7 -21
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +21 -19
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/executables.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +21 -22
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system_hdfs.rb +19 -21
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +2 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +4 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +21 -22
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +10 -12
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/linear_strategy.rb +9 -9
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +5 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +5 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +13 -10
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +5 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/private_ips.rb +5 -5
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/public_ips.rb +5 -5
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +7 -7
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/veids.rb +3 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +27 -25
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +2 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/stdout.rb +8 -6
- data/lib/hybrid_platforms_conductor/io_router.rb +14 -13
- data/lib/hybrid_platforms_conductor/json_dumper.rb +2 -2
- data/lib/hybrid_platforms_conductor/log.rb +31 -0
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +19 -16
- data/lib/hybrid_platforms_conductor/nodes_handler.rb +89 -71
- data/lib/hybrid_platforms_conductor/parallel_threads.rb +7 -11
- data/lib/hybrid_platforms_conductor/platform_handler.rb +7 -7
- data/lib/hybrid_platforms_conductor/platforms_handler.rb +5 -3
- data/lib/hybrid_platforms_conductor/plugin.rb +2 -2
- data/lib/hybrid_platforms_conductor/plugins.rb +14 -8
- data/lib/hybrid_platforms_conductor/provisioner.rb +4 -4
- data/lib/hybrid_platforms_conductor/report.rb +2 -2
- data/lib/hybrid_platforms_conductor/reports_handler.rb +3 -2
- data/lib/hybrid_platforms_conductor/secrets_reader.rb +31 -0
- data/lib/hybrid_platforms_conductor/services_handler.rb +32 -29
- data/lib/hybrid_platforms_conductor/test_only_remote_node.rb +18 -0
- data/lib/hybrid_platforms_conductor/test_report.rb +15 -18
- data/lib/hybrid_platforms_conductor/tests_runner.rb +116 -118
- data/lib/hybrid_platforms_conductor/thycotic.rb +28 -19
- data/lib/hybrid_platforms_conductor/topographer.rb +200 -190
- data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +8 -8
- data/lib/hybrid_platforms_conductor/topographer/plugins/json.rb +4 -4
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test.rb +33 -12
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +18 -11
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/interactive_spec.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -21
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/ruby_spec.rb +75 -49
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/scp_spec.rb +27 -15
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions_spec.rb +90 -59
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connection_spec.rb +46 -44
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/connectable_nodes_spec.rb +12 -8
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +4 -7
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +21 -22
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +23 -24
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connectable_nodes_spec.rb +10 -6
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +106 -75
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +145 -126
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +29 -25
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb +167 -142
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb +272 -244
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb +16 -16
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +36 -36
- data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +24 -22
- data/spec/hybrid_platforms_conductor_test/api/deployer/check_spec.rb +4 -2
- data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +43 -5
- data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +199 -216
- data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +223 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/parse_deploy_output_spec.rb +55 -59
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +36 -62
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/podman_spec.rb +17 -17
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/config_dsl_spec.rb +4 -4
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/create_spec.rb +44 -51
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/destroy_spec.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/ip_spec.rb +12 -16
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/destroy_vm_spec.rb +31 -19
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/expired_containers_spec.rb +324 -266
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/ips_assignment_spec.rb +89 -61
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/other_lxc_containers_resources_spec.rb +117 -93
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/pve_node_resources_spec.rb +71 -54
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/retries_spec.rb +10 -8
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/vm_ids_assignment_spec.rb +80 -60
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/start_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/state_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/stop_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/cli_spec.rb +64 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +268 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/config_spec.rb +8 -10
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_ip_spec.rb +33 -24
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +64 -51
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +50 -51
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +91 -81
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/config_dsl_spec.rb +14 -16
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +51 -75
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +35 -26
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb +24 -16
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/several_platforms_spec.rb +29 -19
- data/spec/hybrid_platforms_conductor_test/api/platform_handler_spec.rb +4 -4
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/deploy_output_parsing_spec.rb +6 -6
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +57 -99
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/inventory_spec.rb +4 -4
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/packaging_spec.rb +32 -35
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +10 -10
- data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +38 -27
- data/spec/hybrid_platforms_conductor_test/api/plugins_spec.rb +46 -52
- data/spec/hybrid_platforms_conductor_test/api/reports_handler_spec.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/api/services_handler/actions_to_deploy_spec.rb +90 -58
- data/spec/hybrid_platforms_conductor_test/api/services_handler/deploy_allowed_spec.rb +38 -34
- data/spec/hybrid_platforms_conductor_test/api/services_handler/log_info_spec.rb +11 -9
- data/spec/hybrid_platforms_conductor_test/api/services_handler/package_spec.rb +193 -171
- data/spec/hybrid_platforms_conductor_test/api/services_handler/parse_deploy_output_spec.rb +66 -54
- data/spec/hybrid_platforms_conductor_test/api/services_handler/prepare_for_deploy_spec.rb +147 -133
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/common_spec.rb +69 -49
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +5 -4
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_check_spec.rb +8 -5
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_spec.rb +8 -5
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_ssh_spec.rb +30 -27
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/platform_spec.rb +12 -9
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/reports_spec.rb +48 -47
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +5 -5
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +5 -5
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_reports_plugins/confluence_spec.rb +5 -5
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb.rb +9 -9
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/{test_cmdb2.rb → test_cmdb_2.rb} +6 -6
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/{test_cmdb_others2.rb → test_cmdb_others_2.rb} +2 -2
- data/spec/hybrid_platforms_conductor_test/docs_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/executables/{check-node_spec.rb → check_node_spec.rb} +4 -6
- data/spec/hybrid_platforms_conductor_test/executables/deploy_spec.rb +4 -6
- data/spec/hybrid_platforms_conductor_test/executables/get_impacted_nodes_spec.rb +76 -77
- data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +159 -113
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +299 -160
- data/spec/hybrid_platforms_conductor_test/executables/options/actions_executor_spec.rb +4 -6
- data/spec/hybrid_platforms_conductor_test/executables/options/cmd_runner_spec.rb +3 -5
- data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +8 -8
- data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +12 -196
- data/spec/hybrid_platforms_conductor_test/executables/options/nodes_handler_spec.rb +9 -10
- data/spec/hybrid_platforms_conductor_test/executables/options/nodes_selectors_spec.rb +9 -10
- data/spec/hybrid_platforms_conductor_test/executables/options/reports_handler_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/executables/options/tests_runner_spec.rb +22 -22
- data/spec/hybrid_platforms_conductor_test/executables/report_spec.rb +22 -16
- data/spec/hybrid_platforms_conductor_test/executables/run_spec.rb +32 -32
- data/spec/hybrid_platforms_conductor_test/executables/ssh_config_spec.rb +7 -9
- data/spec/hybrid_platforms_conductor_test/executables/test_spec.rb +3 -5
- data/spec/hybrid_platforms_conductor_test/helpers/actions_executor_helpers.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +4 -3
- data/spec/hybrid_platforms_conductor_test/helpers/cmdb_helpers.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/helpers/config_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +12 -13
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +245 -56
- data/spec/hybrid_platforms_conductor_test/helpers/executables_helpers.rb +11 -11
- data/spec/hybrid_platforms_conductor_test/helpers/nodes_handler_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +39 -28
- data/spec/hybrid_platforms_conductor_test/helpers/plugins_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +86 -111
- data/spec/hybrid_platforms_conductor_test/helpers/reports_handler_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/serverless_chef_helpers.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/helpers/services_handler_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/tests_runner_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/{test_plugin_id1.rb → test_plugin_id_1.rb} +0 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/{test_plugin_id2.rb → test_plugin_id_2.rb} +0 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type/{test_plugin_id3.rb → test_plugin_id_3.rb} +0 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/{test_plugin_type2/test_plugin_id4.rb → test_plugin_type_2/test_plugin_id_4.rb} +0 -0
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/{test2.rb → test_2.rb} +0 -0
- data/spec/hybrid_platforms_conductor_test/rubocop_spec.rb +31 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json +3 -3
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/nodes/node.json +3 -3
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/libraries/default.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/libraries/default.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +952 -0
- data/spec/hybrid_platforms_conductor_test/test_connector.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/test_log_no_read_plugin.rb +84 -0
- data/spec/hybrid_platforms_conductor_test/test_log_plugin.rb +105 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/global.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node_check.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/platform.rb +1 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/several_checks.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/test_secrets_reader_plugin.rb +45 -0
- data/spec/hybrid_platforms_conductor_test/tests_report_plugin.rb +5 -6
- data/spec/spec_helper.rb +17 -18
- data/tools/check_md +16 -20
- data/tools/generate_mermaid +1 -1
- metadata +195 -144
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +0 -916
|
@@ -42,7 +42,7 @@ module HybridPlatformsConductor
|
|
|
42
42
|
# * *url* (String or nil): The URL for which we want the credentials, or nil if not associated to a URL [default: nil]
|
|
43
43
|
# * *logger* (Logger): Logger to be used [default = Logger.new(STDOUT)]
|
|
44
44
|
# * *logger_stderr* (Logger): Logger to be used for stderr [default = Logger.new(STDERR)]
|
|
45
|
-
def initialize(id, url: nil, logger: Logger.new(
|
|
45
|
+
def initialize(id, url: nil, logger: Logger.new($stdout), logger_stderr: Logger.new($stderr))
|
|
46
46
|
init_loggers(logger, logger_stderr)
|
|
47
47
|
@id = id
|
|
48
48
|
@url = url
|
|
@@ -54,7 +54,7 @@ module HybridPlatformsConductor
|
|
|
54
54
|
# Provide a helper to clear password from memory for security.
|
|
55
55
|
# To be used when the client knows it won't use the password anymore.
|
|
56
56
|
def clear_password
|
|
57
|
-
@password
|
|
57
|
+
@password&.replace('gotyou!' * 100)
|
|
58
58
|
GC.start
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -82,46 +82,49 @@ module HybridPlatformsConductor
|
|
|
82
82
|
# Do it only once.
|
|
83
83
|
# Make sure the retrieved credentials are not linked to other objects in memory, so that we can remove any other trace of secrets.
|
|
84
84
|
def retrieve_credentials
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
85
|
+
return if @retrieved
|
|
86
|
+
|
|
87
|
+
# Check environment variables
|
|
88
|
+
@user = ENV["hpc_user_for_#{@id}"].dup
|
|
89
|
+
@password = ENV["hpc_password_for_#{@id}"].dup
|
|
90
|
+
if @user.nil? || @user.empty? || @password.nil? || @password.empty?
|
|
91
|
+
log_debug "[ Credentials for #{@id} ] - Credentials not found from environment variables."
|
|
92
|
+
if @url.nil?
|
|
93
|
+
log_debug "[ Credentials for #{@id} ] - No URL associated to this credentials, so .netrc can't be used."
|
|
94
|
+
else
|
|
95
|
+
# Check Netrc
|
|
96
|
+
netrc = ::Netrc.read
|
|
97
|
+
begin
|
|
98
|
+
netrc_user, netrc_password = netrc[URI.parse(@url).host.downcase]
|
|
99
|
+
if netrc_user.nil?
|
|
100
|
+
log_debug "[ Credentials for #{@id} ] - No credentials retrieved from .netrc."
|
|
101
|
+
# TODO: Add more credentials source if needed here
|
|
102
|
+
log_warn "[ Credentials for #{@id} ] - Unable to get credentials for #{@id} (URL: #{@url})."
|
|
103
|
+
else
|
|
104
|
+
@user = netrc_user.dup
|
|
105
|
+
@password = netrc_password.dup
|
|
106
|
+
log_debug "[ Credentials for #{@id} ] - Credentials retrieved from .netrc using #{@url}."
|
|
107
|
+
end
|
|
108
|
+
ensure
|
|
109
|
+
# Make sure the password does not stay in Netrc memory
|
|
110
|
+
# Wipe out any memory trace that might contain passwords in clear
|
|
111
|
+
netrc.instance_variable_get(:@data).each do |data_line|
|
|
112
|
+
data_line.each do |data_string|
|
|
113
|
+
data_string.replace('GotYou!!!' * 100)
|
|
114
114
|
end
|
|
115
|
-
netrc = nil
|
|
116
115
|
end
|
|
116
|
+
# We don this assignment on purpose so that GC can remove sensitive data later
|
|
117
|
+
# rubocop:disable Lint/UselessAssignment
|
|
118
|
+
netrc = nil
|
|
119
|
+
# rubocop:enable Lint/UselessAssignment
|
|
117
120
|
end
|
|
118
|
-
else
|
|
119
|
-
log_debug "[ Credentials for #{@id} ] - Credentials retrieved from environment variables."
|
|
120
121
|
end
|
|
121
|
-
|
|
122
|
+
else
|
|
123
|
+
log_debug "[ Credentials for #{@id} ] - Credentials retrieved from environment variables."
|
|
122
124
|
end
|
|
125
|
+
GC.start
|
|
123
126
|
end
|
|
124
127
|
|
|
125
128
|
end
|
|
126
129
|
|
|
127
|
-
end
|
|
130
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require 'monitor'
|
|
2
2
|
|
|
3
|
+
# Decorate methods changing the process' current directory with a mutex to ensure they have an exclusive access
|
|
3
4
|
module HybridPlatformsConductor
|
|
4
5
|
|
|
5
6
|
# Implement a global monitor to protect accesses to the current directory.
|
|
@@ -7,7 +8,9 @@ module HybridPlatformsConductor
|
|
|
7
8
|
module CurrentDirMonitor
|
|
8
9
|
|
|
9
10
|
class << self
|
|
11
|
+
|
|
10
12
|
attr_reader :monitor
|
|
13
|
+
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
@monitor = Monitor.new
|
|
@@ -24,7 +27,7 @@ module HybridPlatformsConductor
|
|
|
24
27
|
result = nil
|
|
25
28
|
CurrentDirMonitor.monitor.synchronize do
|
|
26
29
|
# puts "TID #{Thread.current.object_id} from #{caller[2]} - Current dir monitor taken from #{Dir.pwd}"
|
|
27
|
-
result =
|
|
30
|
+
result = send(original_method_name, *args, &block)
|
|
28
31
|
# puts "TID #{Thread.current.object_id} from #{caller[2]} - Current dir monitor released back to #{Dir.pwd}"
|
|
29
32
|
end
|
|
30
33
|
result
|
|
@@ -3,7 +3,6 @@ require 'futex'
|
|
|
3
3
|
require 'json'
|
|
4
4
|
require 'securerandom'
|
|
5
5
|
require 'time'
|
|
6
|
-
require 'thread'
|
|
7
6
|
require 'hybrid_platforms_conductor/actions_executor'
|
|
8
7
|
require 'hybrid_platforms_conductor/cmd_runner'
|
|
9
8
|
require 'hybrid_platforms_conductor/executable'
|
|
@@ -11,7 +10,6 @@ require 'hybrid_platforms_conductor/logger_helpers'
|
|
|
11
10
|
require 'hybrid_platforms_conductor/nodes_handler'
|
|
12
11
|
require 'hybrid_platforms_conductor/services_handler'
|
|
13
12
|
require 'hybrid_platforms_conductor/plugins'
|
|
14
|
-
require 'hybrid_platforms_conductor/thycotic'
|
|
15
13
|
|
|
16
14
|
module HybridPlatformsConductor
|
|
17
15
|
|
|
@@ -21,12 +19,26 @@ module HybridPlatformsConductor
|
|
|
21
19
|
# Extend the Config DSL
|
|
22
20
|
module ConfigDSLExtension
|
|
23
21
|
|
|
22
|
+
# List of log plugins. Each info has the following properties:
|
|
23
|
+
# * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
|
|
24
|
+
# * *log_plugins* (Array<Symbol>): List of log plugins to be used to store deployment logs.
|
|
25
|
+
# Array< Hash<Symbol, Object> >
|
|
26
|
+
attr_reader :deployment_logs
|
|
27
|
+
|
|
28
|
+
# List of secrets reader plugins. Each info has the following properties:
|
|
29
|
+
# * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
|
|
30
|
+
# * *secrets_readers* (Array<Symbol>): List of log plugins to be used to store deployment logs.
|
|
31
|
+
# Array< Hash<Symbol, Object> >
|
|
32
|
+
attr_reader :secrets_readers
|
|
33
|
+
|
|
24
34
|
# Integer: Timeout (in seconds) for packaging repositories
|
|
25
35
|
attr_reader :packaging_timeout_secs
|
|
26
36
|
|
|
27
37
|
# Mixin initializer
|
|
28
38
|
def init_deployer_config
|
|
29
39
|
@packaging_timeout_secs = 60
|
|
40
|
+
@deployment_logs = []
|
|
41
|
+
@secrets_readers = []
|
|
30
42
|
end
|
|
31
43
|
|
|
32
44
|
# Set the packaging timeout
|
|
@@ -37,6 +49,28 @@ module HybridPlatformsConductor
|
|
|
37
49
|
@packaging_timeout_secs = packaging_timeout_secs
|
|
38
50
|
end
|
|
39
51
|
|
|
52
|
+
# Set the deployment log plugins to be used
|
|
53
|
+
#
|
|
54
|
+
# Parameters::
|
|
55
|
+
# * *log_plugins* (Symbol or Array<Symbol>): The list of (or single) log plugins to be used
|
|
56
|
+
def send_logs_to(*log_plugins)
|
|
57
|
+
@deployment_logs << {
|
|
58
|
+
nodes_selectors_stack: current_nodes_selectors_stack,
|
|
59
|
+
log_plugins: log_plugins.flatten
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Set the secrets readers
|
|
64
|
+
#
|
|
65
|
+
# Parameters::
|
|
66
|
+
# * *secrets_readers* (Symbol or Array<Symbol>): The list of (or single) secrets readers plugins to be used
|
|
67
|
+
def read_secrets_from(*secrets_readers)
|
|
68
|
+
@secrets_readers << {
|
|
69
|
+
nodes_selectors_stack: current_nodes_selectors_stack,
|
|
70
|
+
secrets_readers: secrets_readers.flatten
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
40
74
|
end
|
|
41
75
|
|
|
42
76
|
include LoggerHelpers
|
|
@@ -55,10 +89,6 @@ module HybridPlatformsConductor
|
|
|
55
89
|
# Boolean
|
|
56
90
|
attr_accessor :concurrent_execution
|
|
57
91
|
|
|
58
|
-
# The list of JSON secrets
|
|
59
|
-
# Array<Hash>
|
|
60
|
-
attr_accessor :secrets
|
|
61
|
-
|
|
62
92
|
# Are we deploying in a local environment?
|
|
63
93
|
# Boolean
|
|
64
94
|
attr_accessor :local_environment
|
|
@@ -78,8 +108,8 @@ module HybridPlatformsConductor
|
|
|
78
108
|
# * *actions_executor* (ActionsExecutor): Actions Executor to be used. [default: ActionsExecutor.new]
|
|
79
109
|
# * *services_handler* (ServicesHandler): Services Handler to be used. [default: ServicesHandler.new]
|
|
80
110
|
def initialize(
|
|
81
|
-
logger: Logger.new(
|
|
82
|
-
logger_stderr: Logger.new(
|
|
111
|
+
logger: Logger.new($stdout),
|
|
112
|
+
logger_stderr: Logger.new($stderr),
|
|
83
113
|
config: Config.new,
|
|
84
114
|
cmd_runner: CmdRunner.new,
|
|
85
115
|
nodes_handler: NodesHandler.new,
|
|
@@ -92,8 +122,36 @@ module HybridPlatformsConductor
|
|
|
92
122
|
@nodes_handler = nodes_handler
|
|
93
123
|
@actions_executor = actions_executor
|
|
94
124
|
@services_handler = services_handler
|
|
95
|
-
@
|
|
125
|
+
@override_secrets = nil
|
|
126
|
+
@secrets_readers = Plugins.new(
|
|
127
|
+
:secrets_reader,
|
|
128
|
+
logger: @logger,
|
|
129
|
+
logger_stderr: @logger_stderr,
|
|
130
|
+
init_plugin: proc do |plugin_class|
|
|
131
|
+
plugin_class.new(
|
|
132
|
+
logger: @logger,
|
|
133
|
+
logger_stderr: @logger_stderr,
|
|
134
|
+
config: @config,
|
|
135
|
+
cmd_runner: @cmd_runner,
|
|
136
|
+
nodes_handler: @nodes_handler
|
|
137
|
+
)
|
|
138
|
+
end
|
|
139
|
+
)
|
|
96
140
|
@provisioners = Plugins.new(:provisioner, logger: @logger, logger_stderr: @logger_stderr)
|
|
141
|
+
@log_plugins = Plugins.new(
|
|
142
|
+
:log,
|
|
143
|
+
logger: @logger,
|
|
144
|
+
logger_stderr: @logger_stderr,
|
|
145
|
+
init_plugin: proc do |plugin_class|
|
|
146
|
+
plugin_class.new(
|
|
147
|
+
logger: @logger,
|
|
148
|
+
logger_stderr: @logger_stderr,
|
|
149
|
+
config: @config,
|
|
150
|
+
nodes_handler: @nodes_handler,
|
|
151
|
+
actions_executor: @actions_executor
|
|
152
|
+
)
|
|
153
|
+
end
|
|
154
|
+
)
|
|
97
155
|
# Default values
|
|
98
156
|
@use_why_run = false
|
|
99
157
|
@timeout = nil
|
|
@@ -112,42 +170,32 @@ module HybridPlatformsConductor
|
|
|
112
170
|
def options_parse(options_parser, parallel_switch: true, why_run_switch: false, timeout_options: true)
|
|
113
171
|
options_parser.separator ''
|
|
114
172
|
options_parser.separator 'Deployer options:'
|
|
115
|
-
|
|
116
|
-
'-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
secret = thycotic.download_file_attachment_by_item_id(secret_id, secret_file_item_id)
|
|
130
|
-
raise "Unable to fetch secret file attachment from #{secrets_location}" if secret.nil?
|
|
131
|
-
end
|
|
132
|
-
secret
|
|
133
|
-
else
|
|
134
|
-
raise "Missing secret file: #{secrets_location}" unless File.exist?(secrets_location)
|
|
135
|
-
File.read(secrets_location)
|
|
136
|
-
end
|
|
137
|
-
)
|
|
173
|
+
if parallel_switch
|
|
174
|
+
options_parser.on('-p', '--parallel', 'Execute the commands in parallel (put the standard output in files <hybrid-platforms-dir>/run_logs/*.stdout)') do
|
|
175
|
+
@concurrent_execution = true
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
if timeout_options
|
|
179
|
+
options_parser.on('-t', '--timeout SECS', "Timeout in seconds to wait for each chef run. Only used in why-run mode. (defaults to #{@timeout.nil? ? 'no timeout' : @timeout})") do |nbr_secs|
|
|
180
|
+
@timeout = nbr_secs.to_i
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
if why_run_switch
|
|
184
|
+
options_parser.on('-W', '--why-run', 'Use the why-run mode to see what would be the result of the deploy instead of deploying it for real.') do
|
|
185
|
+
@use_why_run = true
|
|
186
|
+
end
|
|
138
187
|
end
|
|
139
|
-
options_parser.on('-p', '--parallel', 'Execute the commands in parallel (put the standard output in files <hybrid-platforms-dir>/run_logs/*.stdout)') do
|
|
140
|
-
@concurrent_execution = true
|
|
141
|
-
end if parallel_switch
|
|
142
|
-
options_parser.on('-t', '--timeout SECS', "Timeout in seconds to wait for each chef run. Only used in why-run mode. (defaults to #{@timeout.nil? ? 'no timeout' : @timeout})") do |nbr_secs|
|
|
143
|
-
@timeout = nbr_secs.to_i
|
|
144
|
-
end if timeout_options
|
|
145
|
-
options_parser.on('-W', '--why-run', 'Use the why-run mode to see what would be the result of the deploy instead of deploying it for real.') do
|
|
146
|
-
@use_why_run = true
|
|
147
|
-
end if why_run_switch
|
|
148
188
|
options_parser.on('--retries-on-error NBR', "Number of retries in case of non-deterministic errors (defaults to #{@nbr_retries_on_error})") do |nbr_retries|
|
|
149
189
|
@nbr_retries_on_error = nbr_retries.to_i
|
|
150
190
|
end
|
|
191
|
+
# Display options secrets readers might have
|
|
192
|
+
@secrets_readers.each do |secret_reader_name, secret_reader|
|
|
193
|
+
next unless secret_reader.respond_to?(:options_parse)
|
|
194
|
+
|
|
195
|
+
options_parser.separator ''
|
|
196
|
+
options_parser.separator "Secrets reader #{secret_reader_name} options:"
|
|
197
|
+
secret_reader.options_parse(options_parser)
|
|
198
|
+
end
|
|
151
199
|
end
|
|
152
200
|
|
|
153
201
|
# Validate that parsed parameters are valid
|
|
@@ -158,6 +206,16 @@ module HybridPlatformsConductor
|
|
|
158
206
|
# String: File used as a Futex for packaging
|
|
159
207
|
PACKAGING_FUTEX_FILE = "#{Dir.tmpdir}/hpc_packaging"
|
|
160
208
|
|
|
209
|
+
# Override the secrets with a given JSON.
|
|
210
|
+
# When using this method with a secrets Hash, further deployments will not query secrets readers, but will use those secrets directly.
|
|
211
|
+
# Useful to override secrets in test conditions when using dummy secrets for example.
|
|
212
|
+
#
|
|
213
|
+
# Parameters::
|
|
214
|
+
# * *secrets* (Hash or nil): Secrets to take into account in place of secrets readers, or nil to cancel a previous overriding and use secrets readers instead.
|
|
215
|
+
def override_secrets(secrets)
|
|
216
|
+
@override_secrets = secrets
|
|
217
|
+
end
|
|
218
|
+
|
|
161
219
|
# Deploy on a given list of nodes selectors.
|
|
162
220
|
# The workflow is the following:
|
|
163
221
|
# 1. Package the services to be deployed, considering the nodes, services and context (options, secrets, environment...)
|
|
@@ -171,16 +229,26 @@ module HybridPlatformsConductor
|
|
|
171
229
|
def deploy_on(*nodes_selectors)
|
|
172
230
|
# Get the sorted list of services to be deployed, per node
|
|
173
231
|
# Hash<String, Array<String> >
|
|
174
|
-
services_to_deploy =
|
|
232
|
+
services_to_deploy = @nodes_handler.select_nodes(nodes_selectors.flatten).map do |node|
|
|
175
233
|
[node, @nodes_handler.get_services_of(node)]
|
|
176
|
-
end
|
|
234
|
+
end.to_h
|
|
177
235
|
|
|
178
236
|
# Get the secrets to be deployed
|
|
179
237
|
secrets = {}
|
|
180
|
-
@
|
|
181
|
-
secrets
|
|
182
|
-
|
|
183
|
-
|
|
238
|
+
if @override_secrets
|
|
239
|
+
secrets = @override_secrets
|
|
240
|
+
else
|
|
241
|
+
services_to_deploy.each do |node, services|
|
|
242
|
+
# If there is no config for secrets, just use cli
|
|
243
|
+
(@config.secrets_readers.empty? ? [{ secrets_readers: %i[cli] }] : @nodes_handler.select_confs_for_node(node, @config.secrets_readers)).inject([]) do |secrets_readers, secrets_readers_info|
|
|
244
|
+
secrets_readers + secrets_readers_info[:secrets_readers]
|
|
245
|
+
end.sort.uniq.each do |secrets_reader|
|
|
246
|
+
services.each do |service|
|
|
247
|
+
node_secrets = @secrets_readers[secrets_reader].secrets_for(node, service)
|
|
248
|
+
conflicting_path = safe_merge(secrets, node_secrets)
|
|
249
|
+
raise "Secret set at path #{conflicting_path.join('->')} by #{secrets_reader} for service #{service} on node #{node} has conflicting values (#{log_debug? ? "#{node_secrets.dig(*conflicting_path)} != #{secrets.dig(*conflicting_path)}" : 'set debug for value details'})." unless conflicting_path.nil?
|
|
250
|
+
end
|
|
251
|
+
end
|
|
184
252
|
end
|
|
185
253
|
end
|
|
186
254
|
|
|
@@ -188,7 +256,6 @@ module HybridPlatformsConductor
|
|
|
188
256
|
unless @use_why_run
|
|
189
257
|
reason_for_interdiction = @services_handler.deploy_allowed?(
|
|
190
258
|
services: services_to_deploy,
|
|
191
|
-
secrets: secrets,
|
|
192
259
|
local_environment: @local_environment
|
|
193
260
|
)
|
|
194
261
|
raise "Deployment not allowed: #{reason_for_interdiction}" unless reason_for_interdiction.nil?
|
|
@@ -226,51 +293,50 @@ module HybridPlatformsConductor
|
|
|
226
293
|
remaining_nodes_to_deploy = services_to_deploy.keys
|
|
227
294
|
while nbr_retries >= 0 && !remaining_nodes_to_deploy.empty?
|
|
228
295
|
last_deploy_results = deploy(services_to_deploy.slice(*remaining_nodes_to_deploy))
|
|
229
|
-
if nbr_retries
|
|
296
|
+
if nbr_retries.positive?
|
|
230
297
|
# Check if we need to retry deployment on some nodes
|
|
231
298
|
# Only parse the last deployment attempt logs
|
|
232
|
-
retriable_nodes =
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
299
|
+
retriable_nodes = remaining_nodes_to_deploy.
|
|
300
|
+
map do |node|
|
|
301
|
+
exit_status, stdout, stderr = last_deploy_results[node]
|
|
302
|
+
if exit_status.zero?
|
|
303
|
+
nil
|
|
304
|
+
else
|
|
305
|
+
retriable_errors = retriable_errors_from(node, exit_status, stdout, stderr)
|
|
306
|
+
if retriable_errors.empty?
|
|
237
307
|
nil
|
|
238
308
|
else
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
else
|
|
243
|
-
# Log the issue in the stderr of the deployment
|
|
244
|
-
stderr << "!!! #{retriable_errors.size} retriable errors detected in this deployment:\n#{retriable_errors.map { |error| "* #{error}" }.join("\n")}\n"
|
|
245
|
-
[node, retriable_errors]
|
|
246
|
-
end
|
|
309
|
+
# Log the issue in the stderr of the deployment
|
|
310
|
+
stderr << "!!! #{retriable_errors.size} retriable errors detected in this deployment:\n#{retriable_errors.map { |error| "* #{error}" }.join("\n")}\n"
|
|
311
|
+
[node, retriable_errors]
|
|
247
312
|
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
|
|
313
|
+
end
|
|
314
|
+
end.
|
|
315
|
+
compact.
|
|
316
|
+
to_h
|
|
251
317
|
unless retriable_nodes.empty?
|
|
252
|
-
log_warn <<~
|
|
318
|
+
log_warn <<~EO_LOG.strip
|
|
253
319
|
Retry deployment for #{retriable_nodes.size} nodes as they got non-deterministic errors (#{nbr_retries} retries remaining):
|
|
254
320
|
#{retriable_nodes.map { |node, retriable_errors| " * #{node}:\n#{retriable_errors.map { |error| " - #{error}" }.join("\n")}" }.join("\n")}
|
|
255
|
-
|
|
321
|
+
EO_LOG
|
|
256
322
|
end
|
|
257
323
|
remaining_nodes_to_deploy = retriable_nodes.keys
|
|
258
324
|
end
|
|
259
325
|
# Merge deployment results
|
|
260
|
-
results.merge!(last_deploy_results) do |
|
|
326
|
+
results.merge!(last_deploy_results) do |_node, (exit_status_1, stdout_1, stderr_1), (exit_status_2, stdout_2, stderr_2)|
|
|
261
327
|
[
|
|
262
328
|
exit_status_2,
|
|
263
|
-
<<~
|
|
329
|
+
<<~EO_STDOUT,
|
|
264
330
|
#{stdout_1}
|
|
265
331
|
Deployment exit status code: #{exit_status_1}
|
|
266
332
|
!!! Retry deployment due to non-deterministic error (#{nbr_retries} remaining attempts)...
|
|
267
333
|
#{stdout_2}
|
|
268
|
-
|
|
269
|
-
<<~
|
|
334
|
+
EO_STDOUT
|
|
335
|
+
<<~EO_STDERR
|
|
270
336
|
#{stderr_1}
|
|
271
337
|
!!! Retry deployment due to non-deterministic error (#{nbr_retries} remaining attempts)...
|
|
272
338
|
#{stderr_2}
|
|
273
|
-
|
|
339
|
+
EO_STDERR
|
|
274
340
|
]
|
|
275
341
|
end
|
|
276
342
|
nbr_retries -= 1
|
|
@@ -325,7 +391,7 @@ module HybridPlatformsConductor
|
|
|
325
391
|
sub_executable.config.sudo_procs.replace(sub_executable.config.sudo_procs.map do |sudo_proc_info|
|
|
326
392
|
{
|
|
327
393
|
nodes_selectors_stack: sudo_proc_info[:nodes_selectors_stack].map do |nodes_selector|
|
|
328
|
-
@nodes_handler.select_nodes(nodes_selector).
|
|
394
|
+
@nodes_handler.select_nodes(nodes_selector).reject { |selected_node| selected_node == node }
|
|
329
395
|
end,
|
|
330
396
|
sudo_proc: sudo_proc_info[:sudo_proc]
|
|
331
397
|
}
|
|
@@ -338,13 +404,13 @@ module HybridPlatformsConductor
|
|
|
338
404
|
deployer.local_environment = true
|
|
339
405
|
# Ignore secrets that might have been given: in Docker containers we always use dummy secrets
|
|
340
406
|
dummy_secrets_file = "#{@config.hybrid_platforms_dir}/dummy_secrets.json"
|
|
341
|
-
deployer.
|
|
407
|
+
deployer.override_secrets(File.exist?(dummy_secrets_file) ? JSON.parse(File.read(dummy_secrets_file)) : {})
|
|
342
408
|
yield deployer, instance
|
|
343
409
|
end
|
|
344
410
|
rescue
|
|
345
411
|
# Make sure Docker logs are being output to better investigate errors if we were not already outputing them in debug mode
|
|
346
412
|
stdouts = sub_executable.stdouts_to_s
|
|
347
|
-
log_error "[ #{node}/#{environment} ] - Encountered unhandled exception #{
|
|
413
|
+
log_error "[ #{node}/#{environment} ] - Encountered unhandled exception #{$ERROR_INFO}\n#{$ERROR_INFO.backtrace.join("\n")}\n-----\n#{stdouts}" unless stdouts.nil?
|
|
348
414
|
raise
|
|
349
415
|
end
|
|
350
416
|
end
|
|
@@ -355,72 +421,31 @@ module HybridPlatformsConductor
|
|
|
355
421
|
# * *nodes* (Array<String>): Nodes to get info from
|
|
356
422
|
# Result::
|
|
357
423
|
# * Hash<String, Hash<Symbol,Object>: The deployed info, per node name.
|
|
358
|
-
#
|
|
359
|
-
# * *
|
|
424
|
+
# * *error* (String): Error string in case deployment logs could not be retrieved. If set then further properties will be ignored. [optional]
|
|
425
|
+
# * *services* (Array<String>): List of services deployed on the node
|
|
426
|
+
# * *deployment_info* (Hash<Symbol,Object>): Deployment metadata
|
|
427
|
+
# * *exit_status* (Integer or Symbol): Deployment exit status
|
|
428
|
+
# * *stdout* (String): Deployment stdout
|
|
429
|
+
# * *stderr* (String): Deployment stderr
|
|
360
430
|
def deployment_info_from(*nodes)
|
|
431
|
+
nodes = nodes.flatten
|
|
361
432
|
@actions_executor.max_threads = 64
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
# ...
|
|
379
|
-
# PropertyN: ValueN
|
|
380
|
-
# ===== STDOUT =====
|
|
381
|
-
# ...
|
|
382
|
-
deploy_info = {}
|
|
383
|
-
if exit_status.is_a?(Symbol)
|
|
384
|
-
deploy_info[:error] = "Error: #{exit_status}\n#{stderr}"
|
|
385
|
-
else
|
|
386
|
-
stdout_lines = stdout.split("\n")
|
|
387
|
-
if stdout_lines.first =~ /No such file or directory/
|
|
388
|
-
deploy_info[:error] = '/var/log/deployments missing'
|
|
389
|
-
else
|
|
390
|
-
stdout_lines.each do |line|
|
|
391
|
-
if line =~ /^([^:]+): (.+)$/
|
|
392
|
-
key_str, value = $1, $2
|
|
393
|
-
key = key_str.to_sym
|
|
394
|
-
# Type-cast some values
|
|
395
|
-
case key_str
|
|
396
|
-
when 'date'
|
|
397
|
-
# Date and time values
|
|
398
|
-
# Thu Nov 23 18:43:01 UTC 2017
|
|
399
|
-
deploy_info[key] = Time.parse(value)
|
|
400
|
-
when 'debug'
|
|
401
|
-
# Boolean values
|
|
402
|
-
# Yes
|
|
403
|
-
deploy_info[key] = (value == 'Yes')
|
|
404
|
-
when /^diff_files_.+$/, 'services'
|
|
405
|
-
# Array of strings
|
|
406
|
-
# my_file.txt, other_file.txt
|
|
407
|
-
deploy_info[key] = value.split(', ')
|
|
408
|
-
else
|
|
409
|
-
deploy_info[key] = value
|
|
410
|
-
end
|
|
411
|
-
else
|
|
412
|
-
deploy_info[:unknown_lines] = [] unless deploy_info.key?(:unknown_lines)
|
|
413
|
-
deploy_info[:unknown_lines] << line
|
|
414
|
-
end
|
|
415
|
-
end
|
|
416
|
-
end
|
|
417
|
-
end
|
|
418
|
-
[
|
|
419
|
-
node,
|
|
420
|
-
deploy_info
|
|
421
|
-
]
|
|
422
|
-
end
|
|
423
|
-
]
|
|
433
|
+
read_actions_results = @actions_executor.execute_actions(
|
|
434
|
+
nodes.map do |node|
|
|
435
|
+
master_log_plugin = @log_plugins[log_plugins_for(node).first]
|
|
436
|
+
master_log_plugin.respond_to?(:actions_to_read_logs) ? [node, master_log_plugin.actions_to_read_logs(node)] : nil
|
|
437
|
+
end.compact.to_h,
|
|
438
|
+
log_to_stdout: false,
|
|
439
|
+
concurrent: true,
|
|
440
|
+
timeout: 10,
|
|
441
|
+
progress_name: 'Read deployment logs'
|
|
442
|
+
)
|
|
443
|
+
nodes.map do |node|
|
|
444
|
+
[
|
|
445
|
+
node,
|
|
446
|
+
@log_plugins[log_plugins_for(node).first].logs_for(node, *(read_actions_results[node] || [nil, nil, nil]))
|
|
447
|
+
]
|
|
448
|
+
end.to_h
|
|
424
449
|
end
|
|
425
450
|
|
|
426
451
|
# Parse stdout and stderr of a given deploy run and get the list of tasks with their status
|
|
@@ -436,12 +461,41 @@ module HybridPlatformsConductor
|
|
|
436
461
|
# * *:changed*: The task has been changed
|
|
437
462
|
# * *:identical*: The task has not been changed
|
|
438
463
|
# * *diffs* (String): Differences, if any
|
|
439
|
-
def parse_deploy_output(
|
|
464
|
+
def parse_deploy_output(_node, stdout, stderr)
|
|
440
465
|
@services_handler.parse_deploy_output(stdout, stderr).map { |deploy_info| deploy_info[:tasks] }.flatten
|
|
441
466
|
end
|
|
442
467
|
|
|
443
468
|
private
|
|
444
469
|
|
|
470
|
+
# Safe-merge 2 hashes.
|
|
471
|
+
# Safe-merging is done by:
|
|
472
|
+
# * Merging values that are hashes.
|
|
473
|
+
# * Reporting errors when values conflict.
|
|
474
|
+
# When values are conflicting, the initial hash won't modify those conflicting values and will stop the merge.
|
|
475
|
+
#
|
|
476
|
+
# Parameters::
|
|
477
|
+
# * *hash* (Hash): Hash to be modified merging hash_to_merge
|
|
478
|
+
# * *hash_to_merge* (Hash): Hash to be merged into hash
|
|
479
|
+
# Result::
|
|
480
|
+
# * nil or Array<Object>: nil in case of success, or the keys path leading to a conflicting value in case of error
|
|
481
|
+
def safe_merge(hash, hash_to_merge)
|
|
482
|
+
conflicting_path = nil
|
|
483
|
+
hash_to_merge.each do |key, value_to_merge|
|
|
484
|
+
if hash.key?(key)
|
|
485
|
+
if hash[key].is_a?(Hash) && value_to_merge.is_a?(Hash)
|
|
486
|
+
sub_conflicting_path = safe_merge(hash[key], value_to_merge)
|
|
487
|
+
conflicting_path = [key] + sub_conflicting_path unless sub_conflicting_path.nil?
|
|
488
|
+
elsif hash[key] != value_to_merge
|
|
489
|
+
conflicting_path = [key]
|
|
490
|
+
end
|
|
491
|
+
else
|
|
492
|
+
hash[key] = value_to_merge
|
|
493
|
+
end
|
|
494
|
+
break unless conflicting_path.nil?
|
|
495
|
+
end
|
|
496
|
+
conflicting_path
|
|
497
|
+
end
|
|
498
|
+
|
|
445
499
|
# Get the list of retriable errors a node got from deployment logs.
|
|
446
500
|
# Useful to know if an error is non-deterministic (due to external and temporary factors).
|
|
447
501
|
#
|
|
@@ -452,7 +506,7 @@ module HybridPlatformsConductor
|
|
|
452
506
|
# * *stderr* (String): Deployment stderr
|
|
453
507
|
# Result::
|
|
454
508
|
# * Array<String>: List of retriable errors that have been matched
|
|
455
|
-
def retriable_errors_from(node,
|
|
509
|
+
def retriable_errors_from(node, _exit_status, stdout, stderr)
|
|
456
510
|
# List of retriable errors for this node, as exact string match or regexps.
|
|
457
511
|
# Array<String or Regexp>
|
|
458
512
|
retriable_errors_on_stdout = []
|
|
@@ -483,59 +537,55 @@ module HybridPlatformsConductor
|
|
|
483
537
|
# Result::
|
|
484
538
|
# * Hash<String, [Integer or Symbol, String, String]>: Exit status code (or Symbol in case of error or dry run), standard output and error for each node.
|
|
485
539
|
def deploy(services)
|
|
486
|
-
outputs = {}
|
|
487
|
-
|
|
488
540
|
# Get the ssh user directly from the connector
|
|
489
541
|
ssh_user = @actions_executor.connector(:ssh).ssh_user
|
|
490
542
|
|
|
491
543
|
# Deploy for real
|
|
492
544
|
@nodes_handler.prefetch_metadata_of services.keys, :image
|
|
493
545
|
outputs = @actions_executor.execute_actions(
|
|
494
|
-
|
|
546
|
+
services.map do |node, node_services|
|
|
495
547
|
image_id = @nodes_handler.get_image_of(node)
|
|
496
548
|
sudo = (ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} ")
|
|
497
|
-
# Install
|
|
549
|
+
# Install corporate certificates if present
|
|
498
550
|
certificate_actions =
|
|
499
551
|
if @local_environment && ENV['hpc_certificates']
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
remote_bash: "#{sudo}update-ca-certificates"
|
|
514
|
-
}
|
|
515
|
-
]
|
|
516
|
-
when 'centos_7'
|
|
517
|
-
[
|
|
518
|
-
{
|
|
519
|
-
remote_bash: "#{sudo}yum install -y ca-certificates"
|
|
552
|
+
raise "Missing path referenced by the hpc_certificates environment variable: #{ENV['hpc_certificates']}" unless File.exist?(ENV['hpc_certificates'])
|
|
553
|
+
|
|
554
|
+
log_debug "Deploy certificates from #{ENV['hpc_certificates']}"
|
|
555
|
+
case image_id
|
|
556
|
+
when 'debian_9', 'debian_10'
|
|
557
|
+
[
|
|
558
|
+
{
|
|
559
|
+
remote_bash: "#{sudo}apt update && #{sudo}apt install -y ca-certificates"
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
scp: {
|
|
563
|
+
ENV['hpc_certificates'] => '/usr/local/share/ca-certificates',
|
|
564
|
+
:sudo => ssh_user != 'root'
|
|
520
565
|
},
|
|
521
|
-
{
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
566
|
+
remote_bash: "#{sudo}update-ca-certificates"
|
|
567
|
+
}
|
|
568
|
+
]
|
|
569
|
+
when 'centos_7'
|
|
570
|
+
[
|
|
571
|
+
{
|
|
572
|
+
remote_bash: "#{sudo}yum install -y ca-certificates"
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
scp: Dir.glob("#{ENV['hpc_certificates']}/*.crt").map do |cert_file|
|
|
576
|
+
[
|
|
577
|
+
cert_file,
|
|
578
|
+
'/etc/pki/ca-trust/source/anchors'
|
|
531
579
|
]
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
580
|
+
end.to_h.merge(sudo: ssh_user != 'root'),
|
|
581
|
+
remote_bash: [
|
|
582
|
+
"#{sudo}update-ca-trust enable",
|
|
583
|
+
"#{sudo}update-ca-trust extract"
|
|
584
|
+
]
|
|
585
|
+
}
|
|
586
|
+
]
|
|
537
587
|
else
|
|
538
|
-
raise "
|
|
588
|
+
raise "Unknown image ID for node #{node}: #{image_id}. Check metadata for this node."
|
|
539
589
|
end
|
|
540
590
|
else
|
|
541
591
|
[]
|
|
@@ -552,19 +602,19 @@ module HybridPlatformsConductor
|
|
|
552
602
|
certificate_actions +
|
|
553
603
|
@services_handler.actions_to_deploy_on(node, node_services, @use_why_run)
|
|
554
604
|
]
|
|
555
|
-
end
|
|
605
|
+
end.to_h,
|
|
556
606
|
timeout: @timeout,
|
|
557
607
|
concurrent: @concurrent_execution,
|
|
558
608
|
log_to_stdout: !@concurrent_execution
|
|
559
609
|
)
|
|
560
610
|
# Free eventual locks
|
|
561
611
|
@actions_executor.execute_actions(
|
|
562
|
-
|
|
612
|
+
services.keys.map do |node|
|
|
563
613
|
[
|
|
564
614
|
node,
|
|
565
615
|
{ remote_bash: "#{ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock" }
|
|
566
616
|
]
|
|
567
|
-
end
|
|
617
|
+
end.to_h,
|
|
568
618
|
timeout: 10,
|
|
569
619
|
concurrent: true,
|
|
570
620
|
log_to_dir: nil
|
|
@@ -584,47 +634,48 @@ module HybridPlatformsConductor
|
|
|
584
634
|
# * *services* (Hash<String, Array<String>>): List of services that have been deployed, per node
|
|
585
635
|
def save_logs(logs, services)
|
|
586
636
|
section "Saving deployment logs for #{logs.size} nodes" do
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
end
|
|
637
|
+
ssh_user = @actions_executor.connector(:ssh).ssh_user
|
|
638
|
+
@actions_executor.execute_actions(
|
|
639
|
+
logs.map do |node, (exit_status, stdout, stderr)|
|
|
640
|
+
[
|
|
641
|
+
node,
|
|
642
|
+
log_plugins_for(node).
|
|
643
|
+
map do |log_plugin|
|
|
644
|
+
@log_plugins[log_plugin].actions_to_save_logs(
|
|
645
|
+
node,
|
|
646
|
+
services[node],
|
|
647
|
+
@services_handler.log_info_for(node, services[node]).merge(
|
|
648
|
+
date: Time.now.utc.strftime('%F %T'),
|
|
649
|
+
user: ssh_user
|
|
650
|
+
),
|
|
651
|
+
exit_status,
|
|
652
|
+
stdout,
|
|
653
|
+
stderr
|
|
654
|
+
)
|
|
655
|
+
end.
|
|
656
|
+
flatten(1)
|
|
657
|
+
]
|
|
658
|
+
end.to_h,
|
|
659
|
+
timeout: 10,
|
|
660
|
+
concurrent: true,
|
|
661
|
+
log_to_dir: nil,
|
|
662
|
+
progress_name: 'Saving logs'
|
|
663
|
+
)
|
|
664
|
+
end
|
|
665
|
+
end
|
|
666
|
+
|
|
667
|
+
# Get the list of log plugins to be used for a given node
|
|
668
|
+
#
|
|
669
|
+
# Parameters::
|
|
670
|
+
# * *node* (String): The node for which log plugins are queried
|
|
671
|
+
# Result::
|
|
672
|
+
# * Array<Symbol>: The list of log plugins
|
|
673
|
+
def log_plugins_for(node)
|
|
674
|
+
node_log_plugins = @nodes_handler.select_confs_for_node(node, @config.deployment_logs).inject([]) do |log_plugins, deployment_logs_info|
|
|
675
|
+
log_plugins + deployment_logs_info[:log_plugins]
|
|
627
676
|
end
|
|
677
|
+
node_log_plugins << :remote_fs if node_log_plugins.empty?
|
|
678
|
+
node_log_plugins
|
|
628
679
|
end
|
|
629
680
|
|
|
630
681
|
end
|