hybrid_platforms_conductor 33.2.2 → 33.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -0
- data/README.md +29 -2
- data/docs/config_dsl.md +45 -0
- data/docs/plugins.md +1 -0
- data/docs/plugins/secrets_reader/keepass.md +62 -0
- data/lib/hybrid_platforms_conductor/bitbucket.rb +134 -90
- data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
- data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +12 -44
- data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +9 -31
- data/lib/hybrid_platforms_conductor/config.rb +0 -35
- data/lib/hybrid_platforms_conductor/confluence.rb +93 -88
- data/lib/hybrid_platforms_conductor/connector.rb +1 -1
- data/lib/hybrid_platforms_conductor/core_extensions/bundler/without_bundled_env.rb +18 -1
- data/lib/hybrid_platforms_conductor/credentials.rb +122 -97
- data/lib/hybrid_platforms_conductor/deployer.rb +37 -30
- data/lib/hybrid_platforms_conductor/github.rb +39 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +27 -17
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +4 -2
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +29 -20
- data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +5 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +1 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +174 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +4 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +7 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +8 -4
- data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +3 -1
- data/lib/hybrid_platforms_conductor/logger_helpers.rb +24 -1
- data/lib/hybrid_platforms_conductor/plugins.rb +1 -0
- data/lib/hybrid_platforms_conductor/safe_merge.rb +37 -0
- data/lib/hybrid_platforms_conductor/thycotic.rb +80 -75
- data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +5 -3
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test.rb +10 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +15 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +9 -0
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +8 -6
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +38 -0
- data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +21 -1
- data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +48 -72
- data/spec/hybrid_platforms_conductor_test/api/credentials_spec.rb +251 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +36 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/keepass_spec.rb +680 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +2 -2
- data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +49 -69
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +29 -39
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +21 -15
- data/spec/hybrid_platforms_conductor_test/test_connector.rb +2 -2
- metadata +188 -139
@@ -14,6 +14,8 @@ module HybridPlatformsConductor
|
|
14
14
|
|
15
15
|
extend_config_dsl_with CommonConfigDsl::Confluence, :init_confluence
|
16
16
|
|
17
|
+
include HybridPlatformsConductor::Confluence
|
18
|
+
|
17
19
|
# Maximum errors to be reported by item
|
18
20
|
MAX_ERROR_ITEMS_DISPLAYED = 10
|
19
21
|
|
@@ -28,7 +30,7 @@ module HybridPlatformsConductor
|
|
28
30
|
confluence_info = @config.confluence_info
|
29
31
|
if confluence_info
|
30
32
|
if confluence_info[:tests_report_page_id]
|
31
|
-
|
33
|
+
with_confluence(confluence_info[:url]) do |confluence|
|
32
34
|
# Get previous percentages for the evolution
|
33
35
|
@previous_success_percentages = confluence.page_storage_format(confluence_info[:tests_report_page_id]).
|
34
36
|
at('h1:contains("Evolution")').
|
@@ -1,6 +1,23 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
require 'logger'
|
3
3
|
require 'ruby-progressbar'
|
4
|
+
require 'secret_string'
|
5
|
+
|
6
|
+
# Add colorization methods to SecretString, but always directed to the silenced string as we NEVER want to modiy/clone a secret
|
7
|
+
class SecretString
|
8
|
+
|
9
|
+
extend Colorize::ClassMethods
|
10
|
+
|
11
|
+
def_delegators :@silenced_str, *%i[
|
12
|
+
colorize
|
13
|
+
uncolorize
|
14
|
+
colorized?
|
15
|
+
]
|
16
|
+
|
17
|
+
color_methods
|
18
|
+
modes_methods
|
19
|
+
|
20
|
+
end
|
4
21
|
|
5
22
|
module HybridPlatformsConductor
|
6
23
|
|
@@ -88,7 +105,13 @@ module HybridPlatformsConductor
|
|
88
105
|
define_method("log_#{level}") do |message|
|
89
106
|
(LEVELS_TO_STDERR.include?(level) ? @logger_stderr : @logger).send(
|
90
107
|
level,
|
91
|
-
defined?(@log_component)
|
108
|
+
if defined?(@log_component)
|
109
|
+
@log_component
|
110
|
+
else
|
111
|
+
# Handle the case when the class is unnamed
|
112
|
+
class_name = self.class.name
|
113
|
+
class_name.nil? ? '<Unnamed class>' : class_name.split('::').last
|
114
|
+
end
|
92
115
|
) { message }
|
93
116
|
end
|
94
117
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module HybridPlatformsConductor
|
2
|
+
|
3
|
+
# Provide an easy way to safe-merge hashes
|
4
|
+
module SafeMerge
|
5
|
+
|
6
|
+
# Safe-merge 2 hashes.
|
7
|
+
# Safe-merging is done by:
|
8
|
+
# * Merging values that are hashes.
|
9
|
+
# * Reporting errors when values conflict.
|
10
|
+
# When values are conflicting, the initial hash won't modify those conflicting values and will stop the merge.
|
11
|
+
#
|
12
|
+
# Parameters::
|
13
|
+
# * *hash* (Hash): Hash to be modified merging hash_to_merge
|
14
|
+
# * *hash_to_merge* (Hash): Hash to be merged into hash
|
15
|
+
# Result::
|
16
|
+
# * nil or Array<Object>: nil in case of success, or the keys path leading to a conflicting value in case of error
|
17
|
+
def safe_merge(hash, hash_to_merge)
|
18
|
+
conflicting_path = nil
|
19
|
+
hash_to_merge.each do |key, value_to_merge|
|
20
|
+
if hash.key?(key)
|
21
|
+
if hash[key].is_a?(Hash) && value_to_merge.is_a?(Hash)
|
22
|
+
sub_conflicting_path = safe_merge(hash[key], value_to_merge)
|
23
|
+
conflicting_path = [key] + sub_conflicting_path unless sub_conflicting_path.nil?
|
24
|
+
elsif hash[key] != value_to_merge
|
25
|
+
conflicting_path = [key]
|
26
|
+
end
|
27
|
+
else
|
28
|
+
hash[key] = value_to_merge
|
29
|
+
end
|
30
|
+
break unless conflicting_path.nil?
|
31
|
+
end
|
32
|
+
conflicting_path
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -5,95 +5,100 @@ require 'hybrid_platforms_conductor/logger_helpers'
|
|
5
5
|
|
6
6
|
module HybridPlatformsConductor
|
7
7
|
|
8
|
-
#
|
9
|
-
|
8
|
+
# Mixin giving ways to query the Thycotic SOAP API at a given URL
|
9
|
+
module Thycotic
|
10
10
|
|
11
|
-
include
|
11
|
+
include Credentials
|
12
12
|
|
13
13
|
# Provide a Thycotic connector, and make sure the password is being cleaned when exiting.
|
14
14
|
#
|
15
15
|
# Parameters::
|
16
16
|
# * *thycotic_url* (String): The Thycotic URL
|
17
|
-
# * *logger* (Logger): Logger to be used
|
18
|
-
# * *logger_stderr* (Logger): Logger to be used for stderr
|
19
17
|
# * *domain* (String): Domain to use for authentication to Thycotic [default: ENV['hpc_domain_for_thycotic']]
|
20
18
|
# * Proc: Code called with the Thyctotic instance.
|
21
|
-
# * *thycotic* (
|
22
|
-
def
|
23
|
-
|
24
|
-
yield
|
19
|
+
# * *thycotic* (ThyctoticApi): The Thycotic instance to use.
|
20
|
+
def with_thycotic(thycotic_url, domain: ENV['hpc_domain_for_thycotic'])
|
21
|
+
with_credentials_for(:thycotic, resource: thycotic_url) do |thycotic_user, thycotic_password|
|
22
|
+
yield ThycoticApi.new(thycotic_url, thycotic_user, thycotic_password, domain: domain, logger: @logger, logger_stderr: @logger_stderr)
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
|
-
#
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
ssl_verify_mode: :none,
|
50
|
-
logger: @logger,
|
51
|
-
log: log_debug?
|
26
|
+
# Access to the Thycotic API
|
27
|
+
class ThycoticApi
|
28
|
+
|
29
|
+
include LoggerHelpers
|
30
|
+
|
31
|
+
# Constructor
|
32
|
+
#
|
33
|
+
# Parameters::
|
34
|
+
# * *url* (String): URL of the Thycotic Secret Server
|
35
|
+
# * *user* (String): User name to be used to connect to Thycotic
|
36
|
+
# * *password* (SecretString): Password to be used to connect to Thycotic
|
37
|
+
# * *domain* (String): Domain to use for authentication to Thycotic [default: ENV['hpc_domain_for_thycotic']]
|
38
|
+
# * *logger* (Logger): Logger to be used [default: Logger.new(STDOUT)]
|
39
|
+
# * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new(STDERR)]
|
40
|
+
def initialize(
|
41
|
+
url,
|
42
|
+
user,
|
43
|
+
password,
|
44
|
+
domain: ENV['hpc_domain_for_thycotic'],
|
45
|
+
logger: Logger.new($stdout),
|
46
|
+
logger_stderr: Logger.new($stderr)
|
52
47
|
)
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
48
|
+
init_loggers(logger, logger_stderr)
|
49
|
+
# Get a token to this SOAP API
|
50
|
+
@client = Savon.client(
|
51
|
+
wsdl: "#{url}/webservices/SSWebservice.asmx?wsdl",
|
52
|
+
ssl_verify_mode: :none,
|
53
|
+
logger: @logger,
|
54
|
+
log: log_debug?
|
55
|
+
)
|
56
|
+
@token = @client.call(
|
57
|
+
:authenticate,
|
58
|
+
message: {
|
59
|
+
username: user,
|
60
|
+
password: password&.to_unprotected,
|
61
|
+
domain: domain
|
62
|
+
}
|
63
|
+
).to_hash.dig(:authenticate_response, :authenticate_result, :token)
|
64
|
+
raise "Unable to get token from SOAP authentication to #{url}" if @token.nil?
|
65
|
+
end
|
63
66
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
67
|
+
# Return secret corresponding to a given secret ID
|
68
|
+
#
|
69
|
+
# Parameters::
|
70
|
+
# * *secret_id* (Object): The secret ID
|
71
|
+
# Result::
|
72
|
+
# * Hash: The corresponding API result
|
73
|
+
def get_secret(secret_id)
|
74
|
+
@client.call(
|
75
|
+
:get_secret,
|
76
|
+
message: {
|
77
|
+
token: @token,
|
78
|
+
secretId: secret_id
|
79
|
+
}
|
80
|
+
).to_hash.dig(:get_secret_response, :get_secret_result)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get a file attached to a given secret
|
84
|
+
#
|
85
|
+
# Parameters::
|
86
|
+
# * *secret_id* (Object): The secret ID
|
87
|
+
# * *secret_item_id* (Object): The secret item id
|
88
|
+
# Result::
|
89
|
+
# * String or nil: The file content, or nil if none
|
90
|
+
def download_file_attachment_by_item_id(secret_id, secret_item_id)
|
91
|
+
encoded_file = @client.call(
|
92
|
+
:download_file_attachment_by_item_id,
|
93
|
+
message: {
|
94
|
+
token: @token,
|
95
|
+
secretId: secret_id,
|
96
|
+
secretItemId: secret_item_id
|
97
|
+
}
|
98
|
+
).to_hash.dig(:download_file_attachment_by_item_id_response, :download_file_attachment_by_item_id_result, :file_attachment)
|
99
|
+
encoded_file.nil? ? nil : Base64.decode64(encoded_file)
|
100
|
+
end
|
79
101
|
|
80
|
-
# Get a file attached to a given secret
|
81
|
-
#
|
82
|
-
# Parameters::
|
83
|
-
# * *secret_id* (Object): The secret ID
|
84
|
-
# * *secret_item_id* (Object): The secret item id
|
85
|
-
# Result::
|
86
|
-
# * String or nil: The file content, or nil if none
|
87
|
-
def download_file_attachment_by_item_id(secret_id, secret_item_id)
|
88
|
-
encoded_file = @client.call(
|
89
|
-
:download_file_attachment_by_item_id,
|
90
|
-
message: {
|
91
|
-
token: @token,
|
92
|
-
secretId: secret_id,
|
93
|
-
secretItemId: secret_item_id
|
94
|
-
}
|
95
|
-
).to_hash.dig(:download_file_attachment_by_item_id_response, :download_file_attachment_by_item_id_result, :file_attachment)
|
96
|
-
encoded_file.nil? ? nil : Base64.decode64(encoded_file)
|
97
102
|
end
|
98
103
|
|
99
104
|
end
|
@@ -17,9 +17,11 @@ module HybridPlatformsConductor
|
|
17
17
|
@topographer.force_cluster_strict_hierarchy
|
18
18
|
# Write a Graphviz file
|
19
19
|
File.open(file_name, 'w') do |f|
|
20
|
-
f.puts
|
21
|
-
|
22
|
-
|
20
|
+
f.puts <<~EO_GRAPHVIZ
|
21
|
+
digraph unix {
|
22
|
+
size="6,6";
|
23
|
+
node [style=filled];
|
24
|
+
EO_GRAPHVIZ
|
23
25
|
# First write the definition of all nodes
|
24
26
|
# Find all nodes belonging to no cluster
|
25
27
|
orphan_nodes = @topographer.nodes_graph.keys
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'tmpdir'
|
3
|
+
require 'webmock/rspec'
|
3
4
|
require 'hybrid_platforms_conductor/config'
|
4
5
|
require 'hybrid_platforms_conductor/platforms_handler'
|
5
6
|
require 'hybrid_platforms_conductor/actions_executor'
|
@@ -83,6 +84,9 @@ module HybridPlatformsConductorTest
|
|
83
84
|
# Make sure the tested components are being reset before each test case
|
84
85
|
RSpec.configure do |config|
|
85
86
|
config.before do
|
87
|
+
# We allow for connections by default.
|
88
|
+
# Tests that need to test specifically connections at a given point call WebMock.disable_net_connect!
|
89
|
+
WebMock.allow_net_connect!
|
86
90
|
@actions_executor = nil
|
87
91
|
@cmd_runner = nil
|
88
92
|
@config = nil
|
@@ -95,12 +99,18 @@ module HybridPlatformsConductorTest
|
|
95
99
|
ENV.delete 'hpc_platforms'
|
96
100
|
ENV.delete 'hpc_ssh_gateways_conf'
|
97
101
|
ENV.delete 'hpc_ssh_gateway_user'
|
102
|
+
ENV.delete 'hpc_user_for_github'
|
103
|
+
ENV.delete 'hpc_password_for_github'
|
98
104
|
ENV.delete 'hpc_user_for_proxmox'
|
99
105
|
ENV.delete 'hpc_password_for_proxmox'
|
100
106
|
ENV.delete 'hpc_realm_for_proxmox'
|
101
107
|
ENV.delete 'hpc_user_for_thycotic'
|
102
108
|
ENV.delete 'hpc_password_for_thycotic'
|
103
109
|
ENV.delete 'hpc_domain_for_thycotic'
|
110
|
+
ENV.delete 'hpc_user_for_keepass'
|
111
|
+
ENV.delete 'hpc_password_for_keepass'
|
112
|
+
ENV.delete 'hpc_password_enc_for_keepass'
|
113
|
+
ENV.delete 'hpc_key_file_for_keepass'
|
104
114
|
ENV.delete 'hpc_certificates'
|
105
115
|
ENV.delete 'hpc_interactive'
|
106
116
|
ENV.delete 'hpc_test_cookbooks_path'
|
@@ -17,6 +17,21 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
it 'executes local Bash code from a SecretString' do
|
21
|
+
with_test_platform_for_action_plugins do |repository|
|
22
|
+
expect(
|
23
|
+
test_actions_executor.execute_actions(
|
24
|
+
{
|
25
|
+
'node' => {
|
26
|
+
bash: SecretString.new("echo TestContent >#{repository}/test_file ; echo TestStdout ; echo TestStderr 1>&2", silenced_str: '__INVALID_BASH__')
|
27
|
+
}
|
28
|
+
}
|
29
|
+
)['node']
|
30
|
+
).to eq [0, "TestStdout\n", "TestStderr\n"]
|
31
|
+
expect(File.read("#{repository}/test_file")).to eq "TestContent\n"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
20
35
|
it 'executes local Bash code with timeout' do
|
21
36
|
with_test_platform_for_action_plugins do
|
22
37
|
expect(test_actions_executor.execute_actions(
|
@@ -13,6 +13,17 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'executes remote Bash code from a SecretString' do
|
17
|
+
with_test_platform_for_action_plugins do
|
18
|
+
test_actions_executor.execute_actions({ 'node' => { remote_bash: SecretString.new('remote_bash_cmd.bash', silenced_str: '__INVALID_BASH__') } })
|
19
|
+
expect(test_actions_executor.connector(:test_connector).calls).to eq [
|
20
|
+
[:connectable_nodes_from, ['node']],
|
21
|
+
[:with_connection_to, ['node'], { no_exception: true }],
|
22
|
+
[:remote_bash, 'remote_bash_cmd.bash']
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
16
27
|
it 'executes remote Bash code with timeout' do
|
17
28
|
with_test_platform_for_action_plugins do
|
18
29
|
test_actions_executor.connector(:test_connector).remote_bash_code = proc do |_stdout, _stderr, connector|
|
@@ -124,6 +135,27 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
124
135
|
end
|
125
136
|
end
|
126
137
|
|
138
|
+
it 'executes remote Bash code with environment variables set using SecretStrings' do
|
139
|
+
with_test_platform_for_action_plugins do
|
140
|
+
test_actions_executor.execute_actions(
|
141
|
+
{
|
142
|
+
'node' => { remote_bash: {
|
143
|
+
commands: 'bash_cmd.bash',
|
144
|
+
env: {
|
145
|
+
'var1' => SecretString.new('value1', silenced_str: 'SILENCED_VALUE'),
|
146
|
+
'var2' => 'value2'
|
147
|
+
}
|
148
|
+
} }
|
149
|
+
}
|
150
|
+
)
|
151
|
+
expect(test_actions_executor.connector(:test_connector).calls).to eq [
|
152
|
+
[:connectable_nodes_from, ['node']],
|
153
|
+
[:with_connection_to, ['node'], { no_exception: true }],
|
154
|
+
[:remote_bash, "export var1='value1'\nexport var2='value2'\nbash_cmd.bash"]
|
155
|
+
]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
127
159
|
end
|
128
160
|
|
129
161
|
end
|
@@ -54,6 +54,15 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
it 'executes bash commands remotely from a SecretString' do
|
58
|
+
with_test_platform_for_remote_testing(
|
59
|
+
expected_cmds: [['cd /tmp/hpc_local_workspaces/node ; bash_cmd.bash', proc { [0, 'Bash commands executed on node', ''] }]],
|
60
|
+
expected_stdout: 'Bash commands executed on node'
|
61
|
+
) do
|
62
|
+
test_connector.remote_bash(SecretString.new('bash_cmd.bash', silenced_str: '__INVALID_BASH__'))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
57
66
|
it 'executes bash commands remotely with timeout' do
|
58
67
|
with_test_platform_for_remote_testing(
|
59
68
|
expected_cmds: [
|
data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb
CHANGED
@@ -13,10 +13,10 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'returns 1 defined gateway with its content' do
|
16
|
-
ssh_gateway =
|
16
|
+
ssh_gateway = <<~EO_CONFIG
|
17
17
|
Host gateway
|
18
18
|
Hostname mygateway.com
|
19
|
-
|
19
|
+
EO_CONFIG
|
20
20
|
with_repository do
|
21
21
|
with_platforms "gateway :gateway_1, '#{ssh_gateway}'" do
|
22
22
|
expect(test_config.ssh_for_gateway(:gateway_1)).to eq ssh_gateway
|
@@ -34,10 +34,12 @@ describe HybridPlatformsConductor::ActionsExecutor do
|
|
34
34
|
|
35
35
|
it 'returns several defined gateways' do
|
36
36
|
with_repository do
|
37
|
-
with_platforms
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
with_platforms(
|
38
|
+
<<~EO_CONFIG
|
39
|
+
gateway :gateway_1, ''
|
40
|
+
gateway :gateway_2, ''
|
41
|
+
EO_CONFIG
|
42
|
+
) do
|
41
43
|
expect(test_config.known_gateways.sort).to eq %i[gateway_1 gateway_2].sort
|
42
44
|
end
|
43
45
|
end
|