hybrid_platforms_conductor 32.3.6
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 +7 -0
- data/bin/check-node +24 -0
- data/bin/deploy +12 -0
- data/bin/dump_nodes_json +12 -0
- data/bin/free_ips +23 -0
- data/bin/free_veids +17 -0
- data/bin/get_impacted_nodes +43 -0
- data/bin/last_deploys +56 -0
- data/bin/nodes_to_deploy +104 -0
- data/bin/report +10 -0
- data/bin/run +39 -0
- data/bin/setup +11 -0
- data/bin/ssh_config +14 -0
- data/bin/test +13 -0
- data/bin/topograph +54 -0
- data/lib/hybrid_platforms_conductor/action.rb +82 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +307 -0
- data/lib/hybrid_platforms_conductor/bitbucket.rb +123 -0
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +188 -0
- data/lib/hybrid_platforms_conductor/cmdb.rb +34 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +78 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/confluence.rb +43 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/file_system_tests.rb +110 -0
- data/lib/hybrid_platforms_conductor/common_config_dsl/idempotence_tests.rb +38 -0
- data/lib/hybrid_platforms_conductor/config.rb +263 -0
- data/lib/hybrid_platforms_conductor/confluence.rb +119 -0
- data/lib/hybrid_platforms_conductor/connector.rb +84 -0
- data/lib/hybrid_platforms_conductor/credentials.rb +127 -0
- data/lib/hybrid_platforms_conductor/current_dir_monitor.rb +42 -0
- data/lib/hybrid_platforms_conductor/deployer.rb +598 -0
- data/lib/hybrid_platforms_conductor/executable.rb +145 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +44 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/interactive.rb +44 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/my_action.rb.sample +79 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +63 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/ruby.rb +69 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/scp.rb +61 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/config.rb +78 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_ip.rb +104 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/host_keys.rb +114 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/my_cmdb.rb.sample +129 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/cmdb/platform_handlers.rb +66 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +156 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +702 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/platform_handler_plugin.rb.sample +292 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/docker.rb +148 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/my_provisioner.rb.sample +103 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +125 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +522 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/proxmox_waiter.rb +707 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +122 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +69 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/mediawiki.rb +164 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/my_report_plugin.rb.sample +88 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/stdout.rb +61 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/templates/confluence_inventory.html.erb +33 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +137 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/can_be_checked.rb +21 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +112 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_from_scratch.rb +35 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +28 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +44 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_from_scratch.rb +36 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +49 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/divergence.rb +25 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/executables.rb +46 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +45 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system_hdfs.rb +45 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +25 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/idempotence.rb +77 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +38 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +56 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +54 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/linear_strategy.rb +47 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +82 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +120 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/my_test_plugin.rb.sample +143 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +74 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +85 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/private_ips.rb +38 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/public_ips.rb +38 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre-meltdown-checker.sh +1930 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +56 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/veids.rb +31 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +159 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +122 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/my_test_report.rb.sample +48 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/stdout.rb +120 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_errors_status.html.erb +46 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/_confluence_gauge.html.erb +49 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/templates/confluence.html.erb +242 -0
- data/lib/hybrid_platforms_conductor/io_router.rb +70 -0
- data/lib/hybrid_platforms_conductor/json_dumper.rb +88 -0
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +319 -0
- data/lib/hybrid_platforms_conductor/mutex_dir +76 -0
- data/lib/hybrid_platforms_conductor/nodes_handler.rb +597 -0
- data/lib/hybrid_platforms_conductor/parallel_threads.rb +97 -0
- data/lib/hybrid_platforms_conductor/platform_handler.rb +188 -0
- data/lib/hybrid_platforms_conductor/platforms_handler.rb +118 -0
- data/lib/hybrid_platforms_conductor/plugin.rb +53 -0
- data/lib/hybrid_platforms_conductor/plugins.rb +101 -0
- data/lib/hybrid_platforms_conductor/provisioner.rb +181 -0
- data/lib/hybrid_platforms_conductor/report.rb +31 -0
- data/lib/hybrid_platforms_conductor/reports_handler.rb +84 -0
- data/lib/hybrid_platforms_conductor/services_handler.rb +274 -0
- data/lib/hybrid_platforms_conductor/test.rb +141 -0
- data/lib/hybrid_platforms_conductor/test_by_service.rb +22 -0
- data/lib/hybrid_platforms_conductor/test_report.rb +282 -0
- data/lib/hybrid_platforms_conductor/tests_runner.rb +590 -0
- data/lib/hybrid_platforms_conductor/thycotic.rb +92 -0
- data/lib/hybrid_platforms_conductor/topographer.rb +859 -0
- data/lib/hybrid_platforms_conductor/topographer/plugin.rb +20 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +127 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/json.rb +72 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/my_topographer_output_plugin.rb.sample +37 -0
- data/lib/hybrid_platforms_conductor/topographer/plugins/svg.rb +30 -0
- data/lib/hybrid_platforms_conductor/version.rb +5 -0
- data/spec/hybrid_platforms_conductor_test.rb +159 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +43 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/interactive_spec.rb +18 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +102 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/ruby_spec.rb +108 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/scp_spec.rb +79 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions_spec.rb +199 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connection_spec.rb +212 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/cli_options_spec.rb +125 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +50 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connectable_nodes_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +448 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb +313 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb +32 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +134 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb +256 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb +338 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb +101 -0
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +165 -0
- data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +238 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/check_spec.rb +9 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +243 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/parse_deploy_output_spec.rb +104 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +131 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker/Dockerfile +10 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/docker_spec.rb +123 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/podman_spec.rb +211 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/config_dsl_spec.rb +126 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/create_spec.rb +290 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/destroy_spec.rb +43 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/ip_spec.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/proxmox.json +3 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/destroy_vm_spec.rb +82 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/expired_containers_spec.rb +786 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/ips_assignment_spec.rb +112 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/other_lxc_containers_resources_spec.rb +190 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/pve_node_resources_spec.rb +200 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/retries_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/reserve_proxmox_container/vm_ids_assignment_spec.rb +67 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/start_spec.rb +79 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/state_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioners/proxmox/stop_spec.rb +41 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/config_spec.rb +33 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_ip_spec.rb +64 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/host_keys_spec.rb +133 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb +19 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +446 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +127 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb +318 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb +132 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/several_platforms_spec.rb +58 -0
- data/spec/hybrid_platforms_conductor_test/api/platform_handler_spec.rb +97 -0
- data/spec/hybrid_platforms_conductor_test/api/platforms_handler_spec.rb +104 -0
- data/spec/hybrid_platforms_conductor_test/api/plugins_spec.rb +243 -0
- data/spec/hybrid_platforms_conductor_test/api/reports_handler_spec.rb +44 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/actions_to_deploy_spec.rb +121 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/deploy_allowed_spec.rb +142 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/log_info_spec.rb +101 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/package_spec.rb +388 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/parse_deploy_output_spec.rb +274 -0
- data/spec/hybrid_platforms_conductor_test/api/services_handler/prepare_for_deploy_spec.rb +264 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/common_spec.rb +194 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +37 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_check_spec.rb +194 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_spec.rb +137 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/node_ssh_spec.rb +257 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/platform_spec.rb +110 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/reports_spec.rb +367 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +111 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_reports_plugins/confluence_spec.rb +29 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb.rb +166 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb2.rb +93 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/cmdb_plugins/test_cmdb_others2.rb +58 -0
- data/spec/hybrid_platforms_conductor_test/executables/check-node_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/executables/deploy_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/executables/get_impacted_nodes_spec.rb +158 -0
- data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +173 -0
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +283 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/actions_executor_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/cmd_runner_spec.rb +28 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +67 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +251 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/nodes_handler_spec.rb +111 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/nodes_selectors_spec.rb +71 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/reports_handler_spec.rb +54 -0
- data/spec/hybrid_platforms_conductor_test/executables/options/tests_runner_spec.rb +139 -0
- data/spec/hybrid_platforms_conductor_test/executables/report_spec.rb +60 -0
- data/spec/hybrid_platforms_conductor_test/executables/run_spec.rb +173 -0
- data/spec/hybrid_platforms_conductor_test/executables/ssh_config_spec.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/executables/test_spec.rb +41 -0
- data/spec/hybrid_platforms_conductor_test/helpers/actions_executor_helpers.rb +98 -0
- data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +92 -0
- data/spec/hybrid_platforms_conductor_test/helpers/cmdb_helpers.rb +37 -0
- data/spec/hybrid_platforms_conductor_test/helpers/config_helpers.rb +20 -0
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +130 -0
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +149 -0
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +812 -0
- data/spec/hybrid_platforms_conductor_test/helpers/executables_helpers.rb +96 -0
- data/spec/hybrid_platforms_conductor_test/helpers/nodes_handler_helpers.rb +20 -0
- data/spec/hybrid_platforms_conductor_test/helpers/platform_handler_helpers.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/helpers/platforms_handler_helpers.rb +127 -0
- data/spec/hybrid_platforms_conductor_test/helpers/plugins_helpers.rb +48 -0
- data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +789 -0
- data/spec/hybrid_platforms_conductor_test/helpers/reports_handler_helpers.rb +29 -0
- data/spec/hybrid_platforms_conductor_test/helpers/services_handler_helpers.rb +20 -0
- data/spec/hybrid_platforms_conductor_test/helpers/tests_runner_helpers.rb +38 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id1.rb +22 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem/hpc_plugins/test_plugin_type/test_plugin_id2.rb +22 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type/test_plugin_id3.rb +26 -0
- data/spec/hybrid_platforms_conductor_test/mocked_lib/my_test_gem2/sub_dir/hpc_plugins/test_plugin_type2/test_plugin_id4.rb +26 -0
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test.rb +225 -0
- data/spec/hybrid_platforms_conductor_test/platform_handler_plugins/test2.rb +11 -0
- data/spec/hybrid_platforms_conductor_test/report_plugin.rb +35 -0
- data/spec/hybrid_platforms_conductor_test/test_action.rb +66 -0
- data/spec/hybrid_platforms_conductor_test/test_connector.rb +151 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/global.rb +30 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node.rb +53 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node_check.rb +47 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/node_ssh.rb +42 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/platform.rb +50 -0
- data/spec/hybrid_platforms_conductor_test/test_plugins/several_checks.rb +50 -0
- data/spec/hybrid_platforms_conductor_test/test_provisioner.rb +95 -0
- data/spec/hybrid_platforms_conductor_test/tests_report_plugin.rb +49 -0
- data/spec/spec_helper.rb +111 -0
- metadata +566 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'hybrid_platforms_conductor/logger_helpers'
|
|
2
|
+
require 'hybrid_platforms_conductor/plugin'
|
|
3
|
+
|
|
4
|
+
module HybridPlatformsConductor
|
|
5
|
+
|
|
6
|
+
# Base class for any action that could be run on a node.
|
|
7
|
+
class Action < Plugin
|
|
8
|
+
|
|
9
|
+
# Constructor
|
|
10
|
+
#
|
|
11
|
+
# Parameters::
|
|
12
|
+
# * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
|
|
13
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
|
14
|
+
# * *config* (Config): Config to be used. [default: Config.new]
|
|
15
|
+
# * *cmd_runner* (CmdRunner): Command executor to be used. [default: CmdRunner.new]
|
|
16
|
+
# * *actions_executor* (ActionsExecutor): Actions Executor to be used. [default: ActionsExecutor.new]
|
|
17
|
+
# * *action_info* (Object or nil): Action info needed to setup the action, or nil if none [default: nil]
|
|
18
|
+
def initialize(
|
|
19
|
+
logger: Logger.new(STDOUT),
|
|
20
|
+
logger_stderr: Logger.new(STDERR),
|
|
21
|
+
config: Config.new,
|
|
22
|
+
cmd_runner: CmdRunner.new,
|
|
23
|
+
actions_executor: ActionsExecutor.new,
|
|
24
|
+
action_info: nil
|
|
25
|
+
)
|
|
26
|
+
super(logger: logger, logger_stderr: logger_stderr, config: config)
|
|
27
|
+
@cmd_runner = cmd_runner
|
|
28
|
+
@actions_executor = actions_executor
|
|
29
|
+
@action_info = action_info
|
|
30
|
+
setup(@action_info) if self.respond_to?(:setup)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Do we need a connector to execute this action on a node?
|
|
34
|
+
#
|
|
35
|
+
# Result::
|
|
36
|
+
# * Boolean: Do we need a connector to execute this action on a node?
|
|
37
|
+
def need_connector?
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Prepare an action to be run for a given node in a given context.
|
|
42
|
+
# It is required to call this method before executing the action.
|
|
43
|
+
#
|
|
44
|
+
# Paramaters::
|
|
45
|
+
# * *node* (String): The node this actions is targetting
|
|
46
|
+
# * *connector* (Connector or nil): Connector to use to connect to this node, or nil if none
|
|
47
|
+
# * *timeout* (Integer or nil): Timeout this action should have (in seconds), or nil if none
|
|
48
|
+
# * *stdout_io* (IO): IO to log stdout to
|
|
49
|
+
# * *stderr_io* (IO): IO to log stderr to
|
|
50
|
+
def prepare_for(node, connector, timeout, stdout_io, stderr_io)
|
|
51
|
+
@node = node
|
|
52
|
+
@connector = connector
|
|
53
|
+
@timeout = timeout
|
|
54
|
+
@stdout_io = stdout_io
|
|
55
|
+
@stderr_io = stderr_io
|
|
56
|
+
@connector.prepare_for(@node, @timeout, @stdout_io, @stderr_io) if @connector
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
# Run a command.
|
|
62
|
+
# Handle the redirection of standard output and standard error to file and stdout depending on the context of the run.
|
|
63
|
+
#
|
|
64
|
+
# Parameters::
|
|
65
|
+
# * *cmd* (String): The command to be run
|
|
66
|
+
# Result::
|
|
67
|
+
# * Integer: Exit code
|
|
68
|
+
# * String: Standard output
|
|
69
|
+
# * String: Error output
|
|
70
|
+
def run_cmd(cmd)
|
|
71
|
+
@cmd_runner.run_cmd(
|
|
72
|
+
cmd,
|
|
73
|
+
timeout: @timeout,
|
|
74
|
+
log_to_stdout: false,
|
|
75
|
+
log_stdout_to_io: @stdout_io,
|
|
76
|
+
log_stderr_to_io: @stderr_io
|
|
77
|
+
)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'futex'
|
|
3
|
+
require 'logger'
|
|
4
|
+
require 'securerandom'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
require 'hybrid_platforms_conductor/action'
|
|
7
|
+
require 'hybrid_platforms_conductor/cmd_runner'
|
|
8
|
+
require 'hybrid_platforms_conductor/connector'
|
|
9
|
+
require 'hybrid_platforms_conductor/io_router'
|
|
10
|
+
require 'hybrid_platforms_conductor/logger_helpers'
|
|
11
|
+
require 'hybrid_platforms_conductor/nodes_handler'
|
|
12
|
+
require 'hybrid_platforms_conductor/plugins'
|
|
13
|
+
|
|
14
|
+
module HybridPlatformsConductor
|
|
15
|
+
|
|
16
|
+
# Gives ways to execute actions on the nodes
|
|
17
|
+
class ActionsExecutor
|
|
18
|
+
|
|
19
|
+
# Error class returned when the issue is due to a connection issue to the node
|
|
20
|
+
class ConnectionError < RuntimeError
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
include LoggerHelpers
|
|
24
|
+
|
|
25
|
+
# Maximum number of threads to spawn in parallel [default: 8]
|
|
26
|
+
# Integer
|
|
27
|
+
attr_accessor :max_threads
|
|
28
|
+
|
|
29
|
+
# Constructor
|
|
30
|
+
#
|
|
31
|
+
# Parameters::
|
|
32
|
+
# * *logger* (Logger): Logger to be used [default = Logger.new(STDOUT)]
|
|
33
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default = Logger.new(STDERR)]
|
|
34
|
+
# * *config* (Config): Config to be used. [default = Config.new]
|
|
35
|
+
# * *cmd_runner* (CmdRunner): Command runner to be used. [default = CmdRunner.new]
|
|
36
|
+
# * *nodes_handler* (NodesHandler): Nodes handler to be used. [default = NodesHandler.new]
|
|
37
|
+
def initialize(logger: Logger.new(STDOUT), logger_stderr: Logger.new(STDERR), config: Config.new, cmd_runner: CmdRunner.new, nodes_handler: NodesHandler.new)
|
|
38
|
+
init_loggers(logger, logger_stderr)
|
|
39
|
+
@config = config
|
|
40
|
+
@cmd_runner = cmd_runner
|
|
41
|
+
@nodes_handler = nodes_handler
|
|
42
|
+
# Default values
|
|
43
|
+
@max_threads = 16
|
|
44
|
+
@action_plugins = Plugins.new(:action, logger: @logger, logger_stderr: @logger_stderr)
|
|
45
|
+
@connector_plugins = Plugins.new(
|
|
46
|
+
:connector,
|
|
47
|
+
logger: @logger,
|
|
48
|
+
logger_stderr: @logger_stderr,
|
|
49
|
+
init_plugin: proc do |plugin_class|
|
|
50
|
+
plugin_class.new(
|
|
51
|
+
logger: @logger,
|
|
52
|
+
logger_stderr: @logger_stderr,
|
|
53
|
+
config: @config,
|
|
54
|
+
cmd_runner: @cmd_runner,
|
|
55
|
+
nodes_handler: @nodes_handler
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Complete an option parser with options meant to control this Actions Executor
|
|
62
|
+
#
|
|
63
|
+
# Parameters::
|
|
64
|
+
# * *options_parser* (OptionParser): The option parser to complete
|
|
65
|
+
# * *parallel* (Boolean): Do we activate options regarding parallel execution? [default = true]
|
|
66
|
+
def options_parse(options_parser, parallel: true)
|
|
67
|
+
if parallel
|
|
68
|
+
options_parser.separator ''
|
|
69
|
+
options_parser.separator 'Actions Executor options:'
|
|
70
|
+
options_parser.on('-m', '--max-threads NBR', "Set the number of threads to use for concurrent queries (defaults to #{@max_threads})") do |nbr_threads|
|
|
71
|
+
@max_threads = nbr_threads.to_i
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
# Display options connectors might have
|
|
75
|
+
@connector_plugins.each do |connector_name, connector|
|
|
76
|
+
if connector.respond_to?(:options_parse)
|
|
77
|
+
options_parser.separator ''
|
|
78
|
+
options_parser.separator "Connector #{connector_name} options:"
|
|
79
|
+
connector.options_parse(options_parser)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Validate that parsed parameters are valid
|
|
85
|
+
def validate_params
|
|
86
|
+
@connector_plugins.values.each do |connector|
|
|
87
|
+
connector.validate_params if connector.respond_to?(:validate_params)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Execute actions on nodes.
|
|
92
|
+
#
|
|
93
|
+
# Parameters::
|
|
94
|
+
# * *actions_per_nodes* (Hash<Object, Hash<Symbol,Object> or Array< Hash<Symbol,Object> >): Actions (as a Hash of actions or a list of Hash), per nodes selector.
|
|
95
|
+
# See NodesHandler#select_nodes for details about possible nodes selectors.
|
|
96
|
+
# See each action's setup in actions directory to know about the possible action types and data.
|
|
97
|
+
# * *timeout* (Integer): Timeout in seconds, or nil if none. [default: nil]
|
|
98
|
+
# * *concurrent* (Boolean): Do we run the commands in parallel? If yes, then stdout of commands is stored in log files. [default: false]
|
|
99
|
+
# * *log_to_dir* (String or nil): Directory name to store log files. Can be nil to not store log files. [default: "#{@config.hybrid_platforms_dir}/run_logs"]
|
|
100
|
+
# * *log_to_stdout* (Boolean): Do we log the command result on stdout? [default: true]
|
|
101
|
+
# * *progress_name* (String): Name to display on the progress bar [default: 'Executing actions']
|
|
102
|
+
# Result::
|
|
103
|
+
# * 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.
|
|
104
|
+
def execute_actions(actions_per_nodes, timeout: nil, concurrent: false, log_to_dir: "#{@config.hybrid_platforms_dir}/run_logs", log_to_stdout: true, progress_name: 'Executing actions')
|
|
105
|
+
# Keep a list of nodes that will need remote access
|
|
106
|
+
nodes_needing_connectors = []
|
|
107
|
+
# Compute the ordered list of actions per selected node
|
|
108
|
+
# Hash< String, Array< [Symbol, Object ]> >
|
|
109
|
+
# Hash< node, Array< [action_type, action_data]> >
|
|
110
|
+
actions_per_node = {}
|
|
111
|
+
actions_per_nodes.each do |nodes_selector, nodes_actions|
|
|
112
|
+
# Resolved actions, as Action objects
|
|
113
|
+
resolved_nodes_actions = []
|
|
114
|
+
need_remote = false
|
|
115
|
+
(nodes_actions.is_a?(Array) ? nodes_actions : [nodes_actions]).each do |nodes_actions_set|
|
|
116
|
+
nodes_actions_set.each do |action_type, action_info|
|
|
117
|
+
raise 'Cannot have concurrent executions for interactive sessions' if concurrent && action_type == :interactive && action_info
|
|
118
|
+
raise "Unknown action type #{action_type}" unless @action_plugins.key?(action_type)
|
|
119
|
+
action = @action_plugins[action_type].new(
|
|
120
|
+
logger: @logger,
|
|
121
|
+
logger_stderr: @logger_stderr,
|
|
122
|
+
config: @config,
|
|
123
|
+
cmd_runner: @cmd_runner,
|
|
124
|
+
actions_executor: self,
|
|
125
|
+
action_info: action_info
|
|
126
|
+
)
|
|
127
|
+
need_remote = true if action.need_connector?
|
|
128
|
+
resolved_nodes_actions << action
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
# Resolve nodes
|
|
132
|
+
resolved_nodes = @nodes_handler.select_nodes(nodes_selector)
|
|
133
|
+
nodes_needing_connectors.concat(resolved_nodes) if need_remote
|
|
134
|
+
resolved_nodes.each do |node|
|
|
135
|
+
actions_per_node[node] = [] unless actions_per_node.key?(node)
|
|
136
|
+
actions_per_node[node].concat(resolved_nodes_actions)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
result = Hash[actions_per_node.keys.map { |node| [node, nil] }]
|
|
140
|
+
with_connections_prepared_to(nodes_needing_connectors, no_exception: true) do |connected_nodes|
|
|
141
|
+
missing_nodes = []
|
|
142
|
+
connected_nodes.each do |node, connector|
|
|
143
|
+
if connector.is_a?(Symbol)
|
|
144
|
+
result[node] = [connector, '', "Unable to get a connector to #{node}"]
|
|
145
|
+
missing_nodes << node
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
accessible_nodes = actions_per_node.keys - missing_nodes
|
|
149
|
+
log_debug "Running actions on #{accessible_nodes.size} nodes#{log_to_dir.nil? ? '' : " (logs dumped in #{log_to_dir})"}"
|
|
150
|
+
# Prepare the result (stdout or nil per node)
|
|
151
|
+
unless accessible_nodes.empty?
|
|
152
|
+
# If we run in parallel then clone the connectors, so that each node has its own instance for thread-safe code.
|
|
153
|
+
connected_nodes = Hash[connected_nodes.map { |node, connector| [node, connector.clone] }] if concurrent
|
|
154
|
+
@nodes_handler.for_each_node_in(
|
|
155
|
+
accessible_nodes,
|
|
156
|
+
parallel: concurrent,
|
|
157
|
+
nbr_threads_max: @max_threads,
|
|
158
|
+
progress: progress_name
|
|
159
|
+
) do |node|
|
|
160
|
+
node_actions = actions_per_node[node]
|
|
161
|
+
# If we run in parallel then clone the actions, so that each node has its own instance for thread-safe code.
|
|
162
|
+
node_actions.map!(&:clone) if concurrent
|
|
163
|
+
result[node] = execute_actions_on(
|
|
164
|
+
node,
|
|
165
|
+
node_actions,
|
|
166
|
+
connected_nodes[node],
|
|
167
|
+
timeout: timeout,
|
|
168
|
+
log_to_file: log_to_dir.nil? ? nil : "#{log_to_dir}/#{node}.stdout",
|
|
169
|
+
log_to_stdout: log_to_stdout
|
|
170
|
+
)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
result
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Prepare connections to a set of nodes
|
|
178
|
+
#
|
|
179
|
+
# Parameters::
|
|
180
|
+
# * *nodes* (Array<String>): List of nodes to connect to
|
|
181
|
+
# * *no_exception* (Boolean): Should we continue even if some nodes can't be connected to? [default: false]
|
|
182
|
+
# * Proc: Code called with connections prepared
|
|
183
|
+
# * Parameters::
|
|
184
|
+
# * *connected_nodes* (Hash<String, Connector or Symbol>): Prepared connectors (or Symbol in case of failure with no_exception), per node name
|
|
185
|
+
def with_connections_prepared_to(nodes, no_exception: false)
|
|
186
|
+
# Make sure every node needing connectors finds a connector
|
|
187
|
+
nodes_needing_connectors = Hash[nodes.map { |node| [node, nil] }]
|
|
188
|
+
@connector_plugins.each do |connector_name, connector|
|
|
189
|
+
nodes_without_connectors = nodes_needing_connectors.select { |_node, selected_connector| selected_connector.nil? }.keys
|
|
190
|
+
break if nodes_without_connectors.empty?
|
|
191
|
+
(connector.connectable_nodes_from(nodes_without_connectors) & nodes_without_connectors).each do |node|
|
|
192
|
+
nodes_needing_connectors[node] = connector if nodes_needing_connectors[node].nil?
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
# If some nodes need connectors but can't find any, then fail
|
|
196
|
+
nodes_without_connectors = nodes_needing_connectors.select { |_node, selected_connector| selected_connector.nil? }.keys
|
|
197
|
+
unless nodes_without_connectors.empty?
|
|
198
|
+
message = "The following nodes have no possible connector to them: #{nodes_without_connectors.sort.join(', ')}"
|
|
199
|
+
log_warn message
|
|
200
|
+
raise message unless no_exception
|
|
201
|
+
end
|
|
202
|
+
# Prepare the connectors to operate on the nodes they have been assigned to
|
|
203
|
+
preparation_code = proc do |remaining_plugins_to_prepare|
|
|
204
|
+
connector_name = remaining_plugins_to_prepare.first
|
|
205
|
+
if connector_name.nil?
|
|
206
|
+
# All plugins have been prepared.
|
|
207
|
+
# Call our client code.
|
|
208
|
+
yield Hash[nodes_needing_connectors.map do |node, selected_connector|
|
|
209
|
+
[
|
|
210
|
+
node,
|
|
211
|
+
selected_connector.nil? ? :no_connector : selected_connector
|
|
212
|
+
]
|
|
213
|
+
end]
|
|
214
|
+
else
|
|
215
|
+
connector = @connector_plugins[connector_name]
|
|
216
|
+
selected_nodes = nodes_needing_connectors.select { |_node, selected_connector| selected_connector == connector }.keys
|
|
217
|
+
if selected_nodes.empty?
|
|
218
|
+
preparation_code.call(remaining_plugins_to_prepare[1..-1])
|
|
219
|
+
else
|
|
220
|
+
connector.with_connection_to(selected_nodes, no_exception: no_exception) do |connected_nodes|
|
|
221
|
+
(selected_nodes - connected_nodes).each do |node_in_error|
|
|
222
|
+
nodes_needing_connectors[node_in_error] = :connection_error
|
|
223
|
+
end
|
|
224
|
+
preparation_code.call(remaining_plugins_to_prepare[1..-1])
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
preparation_code.call(@connector_plugins.select { |_connector_name, connector| connector.respond_to?(:with_connection_to) }.keys)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Get a given connector
|
|
233
|
+
#
|
|
234
|
+
# Parameters::
|
|
235
|
+
# * *connector_name* (Symbol): The connector name
|
|
236
|
+
# Result::
|
|
237
|
+
# * Connector or nil: The connector, or nil if none found
|
|
238
|
+
def connector(connector_name)
|
|
239
|
+
@connector_plugins[connector_name]
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
private
|
|
243
|
+
|
|
244
|
+
# Execute a list of actions for a node, and return exit codes, stdout and stderr of those actions.
|
|
245
|
+
#
|
|
246
|
+
# Parameters::
|
|
247
|
+
# * *node* (String): The node
|
|
248
|
+
# * *actions* (Array<Action>): Ordered list of actions to perform.
|
|
249
|
+
# * *connector* (Connector or nil): Connector to use to connect to this node, or nil if none.
|
|
250
|
+
# * *timeout* (Integer): Timeout in seconds, or nil if none. [default: nil]
|
|
251
|
+
# * *log_to_file* (String or nil): Log file capturing stdout and stderr (or nil for none). [default: nil]
|
|
252
|
+
# * *log_to_stdout* (Boolean): Do we send the output to stdout and stderr? [default: true]
|
|
253
|
+
# Result::
|
|
254
|
+
# * Integer or Symbol: Exit status of the last command, or Symbol in case of error
|
|
255
|
+
# * String: Standard output of the commands
|
|
256
|
+
# * String: Standard error output of the commands
|
|
257
|
+
def execute_actions_on(node, actions, connector, timeout: nil, log_to_file: nil, log_to_stdout: true)
|
|
258
|
+
remaining_timeout = timeout
|
|
259
|
+
exit_status = 0
|
|
260
|
+
file_output =
|
|
261
|
+
if log_to_file
|
|
262
|
+
FileUtils.mkdir_p(File.dirname(log_to_file))
|
|
263
|
+
File.open(log_to_file, 'w')
|
|
264
|
+
else
|
|
265
|
+
nil
|
|
266
|
+
end
|
|
267
|
+
stdout_queue = Queue.new
|
|
268
|
+
stderr_queue = Queue.new
|
|
269
|
+
stdout = ''
|
|
270
|
+
stderr = ''
|
|
271
|
+
IoRouter.with_io_router(
|
|
272
|
+
stdout_queue => [stdout] +
|
|
273
|
+
(log_to_stdout ? [@logger] : []) +
|
|
274
|
+
(file_output.nil? ? [] : [file_output]),
|
|
275
|
+
stderr_queue => [stderr] +
|
|
276
|
+
(log_to_stdout ? [@logger_stderr] : []) +
|
|
277
|
+
(file_output.nil? ? [] : [file_output])
|
|
278
|
+
) do
|
|
279
|
+
begin
|
|
280
|
+
log_debug "[#{node}] - Execute #{actions.size} actions on #{node}..."
|
|
281
|
+
actions.each do |action|
|
|
282
|
+
action.prepare_for(node, connector, remaining_timeout, stdout_queue, stderr_queue)
|
|
283
|
+
start_time = Time.now
|
|
284
|
+
action.execute
|
|
285
|
+
remaining_timeout -= Time.now - start_time unless remaining_timeout.nil?
|
|
286
|
+
end
|
|
287
|
+
rescue ConnectionError
|
|
288
|
+
exit_status = :connection_error
|
|
289
|
+
stderr_queue << "#{$!}\n"
|
|
290
|
+
rescue CmdRunner::UnexpectedExitCodeError
|
|
291
|
+
exit_status = :failed_command
|
|
292
|
+
stderr_queue << "#{$!}\n"
|
|
293
|
+
rescue CmdRunner::TimeoutError
|
|
294
|
+
# Error has already been logged in stderr
|
|
295
|
+
exit_status = :timeout
|
|
296
|
+
rescue
|
|
297
|
+
log_error "Uncaught exception while executing actions on #{node}: #{$!}\n#{$!.backtrace.join("\n")}"
|
|
298
|
+
stderr_queue << "#{$!}\n"
|
|
299
|
+
exit_status = :failed_action
|
|
300
|
+
end
|
|
301
|
+
end
|
|
302
|
+
[exit_status, stdout, stderr]
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'logger'
|
|
3
|
+
require 'open-uri'
|
|
4
|
+
require 'uri'
|
|
5
|
+
require 'hybrid_platforms_conductor/credentials'
|
|
6
|
+
require 'hybrid_platforms_conductor/logger_helpers'
|
|
7
|
+
|
|
8
|
+
module HybridPlatformsConductor
|
|
9
|
+
|
|
10
|
+
# Object used to access Bitbucket API
|
|
11
|
+
class Bitbucket
|
|
12
|
+
|
|
13
|
+
include LoggerHelpers
|
|
14
|
+
|
|
15
|
+
# Provide a Bitbucket connector, and make sure the password is being cleaned when exiting.
|
|
16
|
+
#
|
|
17
|
+
# Parameters::
|
|
18
|
+
# * *bitbucket_url* (String): The Bitbucket URL
|
|
19
|
+
# * *logger* (Logger): Logger to be used
|
|
20
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr
|
|
21
|
+
# * Proc: Code called with the Bitbucket instance.
|
|
22
|
+
# * *bitbucket* (Bitbucket): The Bitbucket instance to use.
|
|
23
|
+
def self.with_bitbucket(bitbucket_url, logger, logger_stderr)
|
|
24
|
+
Credentials.with_credentials_for(:bitbucket, logger, logger_stderr, url: bitbucket_url) do |bitbucket_user, bitbucket_password|
|
|
25
|
+
yield Bitbucket.new(bitbucket_url, bitbucket_user, bitbucket_password, logger: logger, logger_stderr: logger_stderr)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# The Bitbucket URL
|
|
30
|
+
# String
|
|
31
|
+
attr_reader :bitbucket_url
|
|
32
|
+
|
|
33
|
+
# Constructor
|
|
34
|
+
#
|
|
35
|
+
# Parameters::
|
|
36
|
+
# * *bitbucket_url* (String): The Bitbucket URL
|
|
37
|
+
# * *bitbucket_user_name* (String): Bitbucket user name to be used when querying the API
|
|
38
|
+
# * *bitbucket_password* (String): Bitbucket password to be used when querying the API
|
|
39
|
+
# * *logger* (Logger): Logger to be used [default = Logger.new(STDOUT)]
|
|
40
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default = Logger.new(STDERR)]
|
|
41
|
+
def initialize(bitbucket_url, bitbucket_user_name, bitbucket_password, logger: Logger.new(STDOUT), logger_stderr: Logger.new(STDERR))
|
|
42
|
+
init_loggers(logger, logger_stderr)
|
|
43
|
+
@bitbucket_url = bitbucket_url
|
|
44
|
+
@bitbucket_user_name = bitbucket_user_name
|
|
45
|
+
@bitbucket_password = bitbucket_password
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Get the repositories of a given project.
|
|
49
|
+
# Limit to 1000 results max.
|
|
50
|
+
#
|
|
51
|
+
# Parameters::
|
|
52
|
+
# * *project* (String): Project name
|
|
53
|
+
# Result::
|
|
54
|
+
# * Object: Corresponding JSON
|
|
55
|
+
def repos(project)
|
|
56
|
+
get_api("projects/#{project}/repos?limit=1000")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Get the PR settings of a given repository
|
|
60
|
+
#
|
|
61
|
+
# Parameters::
|
|
62
|
+
# * *project* (String): Project name
|
|
63
|
+
# * *repo* (String): Repository name
|
|
64
|
+
# Result::
|
|
65
|
+
# * Object: Corresponding JSON
|
|
66
|
+
def settings_pr(project, repo)
|
|
67
|
+
get_api("projects/#{project}/repos/#{repo}/settings/pull-requests")
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Get the default reviewers of a given repository
|
|
71
|
+
#
|
|
72
|
+
# Parameters::
|
|
73
|
+
# * *project* (String): Project name
|
|
74
|
+
# * *repo* (String): Repository name
|
|
75
|
+
# Result::
|
|
76
|
+
# * Object: Corresponding JSON
|
|
77
|
+
def default_reviewers(project, repo)
|
|
78
|
+
get_api("projects/#{project}/repos/#{repo}/conditions", api_domain: 'default-reviewers')
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Get the branch permissions of a given repository
|
|
82
|
+
#
|
|
83
|
+
# Parameters::
|
|
84
|
+
# * *project* (String): Project name
|
|
85
|
+
# * *repo* (String): Repository name
|
|
86
|
+
# Result::
|
|
87
|
+
# * Object: Corresponding JSON
|
|
88
|
+
def branch_permissions(project, repo)
|
|
89
|
+
# Put 3 retries here as the Bitbucket installation has a very unstable API 2.0 and often returns random 401 errors.
|
|
90
|
+
get_api("projects/#{project}/repos/#{repo}/restrictions", api_domain: 'branch-permissions', api_version: '2.0', retries: 3)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Issue an HTTP get on the API.
|
|
94
|
+
# Handle authentication.
|
|
95
|
+
#
|
|
96
|
+
# Parameters::
|
|
97
|
+
# * *path* (String): API path to access
|
|
98
|
+
# * *api_domain* (String): API domain to access [default: 'api']
|
|
99
|
+
# * *api_version* (String): API version to access [default: '1.0']
|
|
100
|
+
# * *retries* (Integer): Number of retries in case of failures [default: 0]
|
|
101
|
+
# Result::
|
|
102
|
+
# * Object: Returned JSON
|
|
103
|
+
def get_api(path, api_domain: 'api', api_version: '1.0', retries: 0)
|
|
104
|
+
api_url = "#{@bitbucket_url}/rest/#{api_domain}/#{api_version}/#{path}"
|
|
105
|
+
log_debug "Call Bitbucket API #{@bitbucket_user_name}@#{api_url}..."
|
|
106
|
+
http_response = nil
|
|
107
|
+
loop do
|
|
108
|
+
begin
|
|
109
|
+
http_response = URI.open(api_url, http_basic_authentication: [@bitbucket_user_name, @bitbucket_password])
|
|
110
|
+
rescue
|
|
111
|
+
raise if retries == 0
|
|
112
|
+
log_warn "Got error #{$!} on #{@bitbucket_user_name}@#{api_url}. Will retry #{retries} times..."
|
|
113
|
+
retries -= 1
|
|
114
|
+
sleep 1
|
|
115
|
+
end
|
|
116
|
+
break unless http_response.nil?
|
|
117
|
+
end
|
|
118
|
+
JSON.parse(http_response.read)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|