hybrid_platforms_conductor 32.16.3 → 33.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +6 -3
  4. data/bin/last_deploys +4 -1
  5. data/bin/nodes_to_deploy +5 -5
  6. data/docs/config_dsl.md +45 -1
  7. data/docs/executables.md +6 -7
  8. data/docs/executables/check-node.md +3 -3
  9. data/docs/executables/deploy.md +3 -3
  10. data/docs/executables/dump_nodes_json.md +3 -3
  11. data/docs/executables/test.md +3 -3
  12. data/docs/executables/topograph.md +3 -3
  13. data/docs/gen/mermaid/README.md-0.png +0 -0
  14. data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
  15. data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
  16. data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
  17. data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
  18. data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
  19. data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
  20. data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
  21. data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
  22. data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
  23. data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
  24. data/docs/plugins.md +47 -0
  25. data/docs/plugins/connector/ssh.md +1 -1
  26. data/docs/plugins/log/remote_fs.md +26 -0
  27. data/docs/plugins/secrets_reader/cli.md +31 -0
  28. data/docs/plugins/secrets_reader/thycotic.md +46 -0
  29. data/docs/plugins/test/bitbucket_conf.md +1 -1
  30. data/docs/plugins/test/check_deploy_and_idempotence.md +1 -1
  31. data/docs/plugins/test/connection.md +1 -0
  32. data/docs/plugins/test/deploy_removes_root_access.md +1 -1
  33. data/docs/plugins/test/file_system.md +1 -0
  34. data/docs/plugins/test/github_ci.md +48 -0
  35. data/docs/plugins/test/hostname.md +1 -0
  36. data/docs/plugins/test/ip.md +1 -0
  37. data/docs/plugins/test/jenkins_ci_conf.md +1 -1
  38. data/docs/plugins/test/jenkins_ci_masters_ok.md +1 -1
  39. data/docs/plugins/test/local_users.md +1 -0
  40. data/docs/plugins/test/mounts.md +1 -0
  41. data/docs/plugins/test/orphan_files.md +1 -0
  42. data/docs/plugins/test/ports.md +1 -0
  43. data/docs/plugins/test/spectre.md +1 -0
  44. data/docs/plugins/test/vulnerabilities.md +1 -0
  45. data/lib/hybrid_platforms_conductor/actions_executor.rb +8 -1
  46. data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +62 -0
  47. data/lib/hybrid_platforms_conductor/deployer.rb +193 -141
  48. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +3 -3
  49. data/lib/hybrid_platforms_conductor/hpc_plugins/log/my_log_plugin.rb.sample +100 -0
  50. data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +179 -0
  51. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/cli.rb +75 -0
  52. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/my_secrets_reader_plugin.rb.sample +46 -0
  53. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +87 -0
  54. data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +1 -1
  55. data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +3 -1
  56. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +7 -20
  57. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +1 -1
  58. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +2 -1
  59. data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +32 -0
  60. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +3 -1
  61. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +3 -1
  62. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +3 -1
  63. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +3 -1
  64. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +3 -1
  65. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +3 -1
  66. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +3 -1
  67. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +2 -1
  68. data/lib/hybrid_platforms_conductor/log.rb +31 -0
  69. data/lib/hybrid_platforms_conductor/plugins.rb +1 -0
  70. data/lib/hybrid_platforms_conductor/secrets_reader.rb +31 -0
  71. data/lib/hybrid_platforms_conductor/test_only_remote_node.rb +18 -0
  72. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  73. data/spec/hybrid_platforms_conductor_test.rb +27 -6
  74. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +3 -3
  75. data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +46 -4
  76. data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +187 -212
  77. data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +223 -0
  78. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +4 -4
  79. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/cli_spec.rb +63 -0
  80. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +253 -0
  81. data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +1 -1
  82. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +72 -0
  83. data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +146 -98
  84. data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +240 -83
  85. data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +2 -1
  86. data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +0 -182
  87. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +1 -1
  88. data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +40 -53
  89. data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +251 -15
  90. data/spec/hybrid_platforms_conductor_test/test_log_no_read_plugin.rb +82 -0
  91. data/spec/hybrid_platforms_conductor_test/test_log_plugin.rb +103 -0
  92. data/spec/hybrid_platforms_conductor_test/test_secrets_reader_plugin.rb +45 -0
  93. metadata +41 -2
@@ -54,8 +54,8 @@ describe HybridPlatformsConductor::Deployer do
54
54
  with_test_platform(
55
55
  {
56
56
  nodes: {
57
- 'node1' => { meta: { host_ip: '192.168.42.1', ssh_session_exec: 'false' } },
58
- 'node2' => { meta: { host_ip: '192.168.42.2', ssh_session_exec: 'false' } }
57
+ 'node1' => { meta: { host_ip: '192.168.42.1', ssh_session_exec: false } },
58
+ 'node2' => { meta: { host_ip: '192.168.42.2', ssh_session_exec: false } }
59
59
  }
60
60
  },
61
61
  false,
@@ -75,8 +75,8 @@ describe HybridPlatformsConductor::Deployer do
75
75
  block.call
76
76
  end
77
77
  test_deployer.with_test_provisioned_instance(:test_provisioner, 'node1', environment: 'hpc_testing_provisioner') do |sub_test_deployer, test_instance|
78
- expect(sub_test_deployer.instance_eval { @nodes_handler.get_ssh_session_exec_of('node1') }).to eq 'true'
79
- expect(sub_test_deployer.instance_eval { @nodes_handler.get_ssh_session_exec_of('node2') }).to eq 'false'
78
+ expect(sub_test_deployer.instance_eval { @nodes_handler.get_ssh_session_exec_of('node1') }).to eq true
79
+ expect(sub_test_deployer.instance_eval { @nodes_handler.get_ssh_session_exec_of('node2') }).to eq false
80
80
  ssh_transforms = test_instance.instance_eval { @config.ssh_connection_transforms }
81
81
  expect(ssh_transforms.size).to eq 1
82
82
  expect(ssh_transforms[0][:nodes_selectors_stack]).to eq [%w[node2]]
@@ -0,0 +1,63 @@
1
+ describe HybridPlatformsConductor::Deployer do
2
+
3
+ context 'checking secrets_reader plugins' do
4
+
5
+ context 'cli' do
6
+
7
+ # Setup a platform for tests
8
+ #
9
+ # Parameters::
10
+ # * Proc: Code called when the platform is setup
11
+ # * Parameters::
12
+ # * *repository* (String): Platform's repository
13
+ def with_test_platform_for_cli_test
14
+ with_test_platform(
15
+ { nodes: { 'node' => { services: %w[service] } } },
16
+ false,
17
+ 'read_secrets_from :cli'
18
+ ) do |repository|
19
+ yield repository
20
+ end
21
+ end
22
+
23
+ it 'gets secrets from a file' do
24
+ with_test_platform_for_cli_test do |repository|
25
+ secrets_file = "#{repository}/my_secrets.json"
26
+ File.write(secrets_file, '{ "secret_name": "secret_value" }')
27
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
28
+ services: { 'node' => %w[service] },
29
+ secrets: { 'secret_name' => 'secret_value' },
30
+ local_environment: false
31
+ ) { 'Abort as testing secrets is enough' }
32
+ expect { run 'deploy', '--node', 'node', '--secrets', secrets_file }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
33
+ end
34
+ end
35
+
36
+ it 'gets secrets from several files' do
37
+ with_test_platform_for_cli_test do |repository|
38
+ secrets_file1 = "#{repository}/my_secrets1.json"
39
+ File.write(secrets_file1, '{ "secret1": "value1" }')
40
+ secrets_file2 = "#{repository}/my_secrets2.json"
41
+ File.write(secrets_file2, '{ "secret2": "value2" }')
42
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
43
+ services: { 'node' => %w[service] },
44
+ secrets: { 'secret1' => 'value1', 'secret2' => 'value2' },
45
+ local_environment: false
46
+ ) { 'Abort as testing secrets is enough' }
47
+ expect { run 'deploy', '--node', 'node', '--secrets', secrets_file1, '--secrets', secrets_file2 }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
48
+ end
49
+ end
50
+
51
+ it 'fails to get secrets from a missing file' do
52
+ with_test_platform_for_cli_test do
53
+ expect do
54
+ run 'deploy', '--node', 'node', '--secrets', 'unknown_file.json'
55
+ end.to raise_error 'Missing secrets file: unknown_file.json'
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+
63
+ end
@@ -0,0 +1,253 @@
1
+ require 'savon'
2
+
3
+ describe HybridPlatformsConductor::Deployer do
4
+
5
+ context 'checking secrets_reader plugins' do
6
+
7
+ context 'thycotic' do
8
+
9
+ # Setup a platform for tests
10
+ #
11
+ # Parameters::
12
+ # * *additional_config* (String): Additional config
13
+ # * *platform_info* (Hash): Platform configuration [default: 1 node having 1 service]
14
+ # * Proc: Code called when the platform is setup
15
+ def with_test_platform_for_thycotic_test(additional_config = '', platform_info: { nodes: { 'node' => { services: %w[service] } } })
16
+ with_test_platform(
17
+ platform_info,
18
+ false,
19
+ "read_secrets_from :thycotic\n" + additional_config
20
+ ) do
21
+ yield
22
+ end
23
+ end
24
+
25
+ # Mock calls being made to a Thycotic SOAP API using Savon
26
+ #
27
+ # Parameters::
28
+ # * *url* (String): Mocked URL
29
+ # * *secret_id* (String): The mocked secret ID
30
+ # * *mocked_secrets_file* (String or nil): The mocked secrets file stored in Thycotic, or nil to mock a missing secret
31
+ # * *user* (String or nil): The user to be expected, or nil if it should be read from netrc [default: nil]
32
+ # * *password* (String or nil): The password to be expected, or nil if it should be read from netrc [default: nil]
33
+ def mock_thycotic_file_download_on(url, secret_id, mocked_secrets_file, user: nil, password: nil)
34
+ if user.nil?
35
+ user = 'thycotic_user_from_netrc'
36
+ password = 'thycotic_password_from_netrc'
37
+ expect(HybridPlatformsConductor::Credentials).to receive(:with_credentials_for) do |id, _logger, _logger_stderr, url: nil, &client_code|
38
+ expect(id).to eq :thycotic
39
+ expect(url).to eq url
40
+ client_code.call user, password
41
+ end
42
+ end
43
+ # Mock the Savon calls
44
+ mocked_savon_client = double 'Mocked Savon client'
45
+ expect(Savon).to receive(:client) do |params|
46
+ expect(params[:wsdl]).to eq "#{url}/webservices/SSWebservice.asmx?wsdl"
47
+ expect(params[:ssl_verify_mode]).to eq :none
48
+ mocked_savon_client
49
+ end
50
+ expect(mocked_savon_client).to receive(:call).with(
51
+ :authenticate,
52
+ message: {
53
+ username: user,
54
+ password: password,
55
+ domain: 'thycotic_auth_domain'
56
+ }
57
+ ) do
58
+ { authenticate_response: { authenticate_result: { token: 'soap_token' } } }
59
+ end
60
+ expect(mocked_savon_client).to receive(:call).with(
61
+ :get_secret,
62
+ message: {
63
+ token: 'soap_token',
64
+ secretId: secret_id
65
+ }
66
+ ) do
67
+ {
68
+ get_secret_response: {
69
+ get_secret_result:
70
+ if mocked_secrets_file
71
+ { secret: { items: { secret_item: { id: '4242' } } } }
72
+ else
73
+ { errors: { string: 'Access Denied'}, secret_error: { error_code: 'LOAD', error_message: 'Access Denied', allows_response: false } }
74
+ end
75
+ }
76
+ }
77
+ end
78
+ if mocked_secrets_file
79
+ expect(mocked_savon_client).to receive(:call).with(
80
+ :download_file_attachment_by_item_id,
81
+ message: {
82
+ token: 'soap_token',
83
+ secretId: secret_id,
84
+ secretItemId: '4242'
85
+ }
86
+ ) do
87
+ {
88
+ download_file_attachment_by_item_id_response: {
89
+ download_file_attachment_by_item_id_result: {
90
+ file_attachment: Base64.encode64(mocked_secrets_file)
91
+ }
92
+ }
93
+ }
94
+ end
95
+ end
96
+ ENV['hpc_domain_for_thycotic'] = 'thycotic_auth_domain'
97
+ end
98
+
99
+ it 'gets secrets from a Thycotic Secret Server' do
100
+ with_test_platform_for_thycotic_test(
101
+ <<~EOS
102
+ secrets_from_thycotic(
103
+ thycotic_url: 'https://my_thycotic.domain.com/SecretServer',
104
+ secret_id: 1107
105
+ )
106
+ EOS
107
+ ) do
108
+ mock_thycotic_file_download_on('https://my_thycotic.domain.com/SecretServer', 1107, '{ "secret_name": "secret_value" }')
109
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
110
+ services: { 'node' => %w[service] },
111
+ secrets: { 'secret_name' => 'secret_value' },
112
+ local_environment: false
113
+ ) { 'Abort as testing secrets is enough' }
114
+ expect { test_deployer.deploy_on(%w[node]) }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
115
+ end
116
+ end
117
+
118
+ it 'gets secrets from a Thycotic Secret Server for several nodes' do
119
+ additional_config = <<~EOS
120
+ secrets_from_thycotic(
121
+ thycotic_url: 'https://my_thycotic.domain.com/SecretServer',
122
+ secret_id: 1107
123
+ )
124
+ EOS
125
+ with_test_platform_for_thycotic_test(additional_config, platform_info: { nodes: { 'node1' => { services: %w[service1] }, 'node2' => { services: %w[service2] } } }) do
126
+ mock_thycotic_file_download_on('https://my_thycotic.domain.com/SecretServer', 1107, '{ "secret_name": "secret_value" }')
127
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
128
+ services: { 'node1' => %w[service1], 'node2' => %w[service2] },
129
+ secrets: { 'secret_name' => 'secret_value' },
130
+ local_environment: false
131
+ ) { 'Abort as testing secrets is enough' }
132
+ expect { test_deployer.deploy_on(%w[node1 node2]) }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
133
+ end
134
+ end
135
+
136
+ it 'gets secrets from a Thycotic Secret Server using env variables' do
137
+ with_test_platform_for_thycotic_test(
138
+ <<~EOS
139
+ secrets_from_thycotic(
140
+ thycotic_url: 'https://my_thycotic.domain.com/SecretServer',
141
+ secret_id: 1107
142
+ )
143
+ EOS
144
+ ) do
145
+ mock_thycotic_file_download_on(
146
+ 'https://my_thycotic.domain.com/SecretServer',
147
+ 1107,
148
+ '{ "secret_name": "secret_value" }',
149
+ user: 'thycotic_user_from_env',
150
+ password: 'thycotic_password_from_env'
151
+ )
152
+ ENV['hpc_user_for_thycotic'] = 'thycotic_user_from_env'
153
+ ENV['hpc_password_for_thycotic'] = 'thycotic_password_from_env'
154
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
155
+ services: { 'node' => %w[service] },
156
+ secrets: { 'secret_name' => 'secret_value' },
157
+ local_environment: false
158
+ ) { 'Abort as testing secrets is enough' }
159
+ expect { test_deployer.deploy_on(%w[node]) }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
160
+ end
161
+ end
162
+
163
+ it 'gets secrets from several Thycotic Secret Servers' do
164
+ additional_config = <<~EOS
165
+ secrets_from_thycotic(
166
+ thycotic_url: 'https://my_thycotic1.domain.com/SecretServer',
167
+ secret_id: 110701
168
+ )
169
+ for_nodes('node2') do
170
+ secrets_from_thycotic(
171
+ thycotic_url: 'https://my_thycotic2.domain.com/SecretServer',
172
+ secret_id: 110702
173
+ )
174
+ end
175
+ EOS
176
+ with_test_platform_for_thycotic_test(additional_config, platform_info: { nodes: { 'node1' => { services: %w[service1] }, 'node2' => { services: %w[service2] } } }) do
177
+ mock_thycotic_file_download_on('https://my_thycotic1.domain.com/SecretServer', 110701, '{ "secret1": "value1" }')
178
+ mock_thycotic_file_download_on('https://my_thycotic2.domain.com/SecretServer', 110702, '{ "secret2": "value2" }')
179
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
180
+ services: { 'node1' => %w[service1], 'node2' => %w[service2] },
181
+ secrets: { 'secret1' => 'value1', 'secret2' => 'value2' },
182
+ local_environment: false
183
+ ) { 'Abort as testing secrets is enough' }
184
+ expect { test_deployer.deploy_on(%w[node1 node2]) }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
185
+ end
186
+ end
187
+
188
+ it 'merges secrets from several Thycotic Secret Servers' do
189
+ with_test_platform_for_thycotic_test(
190
+ <<~EOS
191
+ secrets_from_thycotic(
192
+ thycotic_url: 'https://my_thycotic1.domain.com/SecretServer',
193
+ secret_id: 110701
194
+ )
195
+ for_nodes('node') do
196
+ secrets_from_thycotic(
197
+ thycotic_url: 'https://my_thycotic2.domain.com/SecretServer',
198
+ secret_id: 110702
199
+ )
200
+ end
201
+ EOS
202
+ ) do
203
+ mock_thycotic_file_download_on('https://my_thycotic1.domain.com/SecretServer', 110701, '{ "secret1": "value1", "secret2": "value2" }')
204
+ mock_thycotic_file_download_on('https://my_thycotic2.domain.com/SecretServer', 110702, '{ "secret2": "value2", "secret3": "value3" }')
205
+ expect(test_services_handler).to receive(:deploy_allowed?).with(
206
+ services: { 'node' => %w[service] },
207
+ secrets: { 'secret1' => 'value1', 'secret2' => 'value2', 'secret3' => 'value3' },
208
+ local_environment: false
209
+ ) { 'Abort as testing secrets is enough' }
210
+ expect { test_deployer.deploy_on(%w[node]) }.to raise_error 'Deployment not allowed: Abort as testing secrets is enough'
211
+ end
212
+ end
213
+
214
+ it 'fails in case of secrets conflicts from several Thycotic Secret Servers' do
215
+ with_test_platform_for_thycotic_test(
216
+ <<~EOS
217
+ secrets_from_thycotic(
218
+ thycotic_url: 'https://my_thycotic1.domain.com/SecretServer',
219
+ secret_id: 110701
220
+ )
221
+ for_nodes('node') do
222
+ secrets_from_thycotic(
223
+ thycotic_url: 'https://my_thycotic2.domain.com/SecretServer',
224
+ secret_id: 110702
225
+ )
226
+ end
227
+ EOS
228
+ ) do
229
+ mock_thycotic_file_download_on('https://my_thycotic1.domain.com/SecretServer', 110701, '{ "secret1": "value1", "secret2": "value2" }')
230
+ mock_thycotic_file_download_on('https://my_thycotic2.domain.com/SecretServer', 110702, '{ "secret2": "other_value", "secret3": "value3" }')
231
+ expect { test_deployer.deploy_on(%w[node]) }.to raise_error 'Thycotic secret secret2 served by https://my_thycotic2.domain.com/SecretServer from secret ID 110702 has conflicting values between different secrets.'
232
+ end
233
+ end
234
+
235
+ it 'fails to get secrets from a missing Thycotic Secret Server' do
236
+ with_test_platform_for_thycotic_test(
237
+ <<~EOS
238
+ secrets_from_thycotic(
239
+ thycotic_url: 'https://my_thycotic.domain.com/SecretServer',
240
+ secret_id: 1107
241
+ )
242
+ EOS
243
+ ) do
244
+ mock_thycotic_file_download_on('https://my_thycotic.domain.com/SecretServer', 1107, nil)
245
+ expect { test_deployer.deploy_on(%w[node]) }.to raise_error 'Unable to fetch secret file ID 1107 from https://my_thycotic.domain.com/SecretServer'
246
+ end
247
+ end
248
+
249
+ end
250
+
251
+ end
252
+
253
+ end
@@ -5,7 +5,7 @@ describe HybridPlatformsConductor::TestsRunner do
5
5
  # Prepare the test platform with test plugins
6
6
  #
7
7
  # Parameters::
8
- # * *platforms_info* (Hash): The platofrms info [default: {}]
8
+ # * *platforms_info* (Hash): The platforms info [default: {}]
9
9
  def with_test_platform_for_global_tests(platforms_info: {})
10
10
  with_test_platform(platforms_info) do
11
11
  register_test_plugins(test_tests_runner,
@@ -0,0 +1,72 @@
1
+ describe HybridPlatformsConductor::TestsRunner do
2
+
3
+ context 'checking test plugins' do
4
+
5
+ context 'checking github_ci' do
6
+
7
+ it 'iterates over defined Github repos' do
8
+ with_repository do |repository|
9
+ platforms = <<~EOS
10
+ github_repos(
11
+ url: 'https://my_gh.my_domain.com',
12
+ user: 'GH-User1',
13
+ repos: [
14
+ 'repo1',
15
+ 'repo2'
16
+ ]
17
+ )
18
+ github_repos(
19
+ user: 'GH-User2',
20
+ repos: [
21
+ 'repo3',
22
+ 'repo4'
23
+ ]
24
+ )
25
+ EOS
26
+ with_platforms platforms do
27
+ repos = []
28
+ test_config.for_each_github_repo do |github, repo_info|
29
+ repos << {
30
+ github_url: github.api_endpoint,
31
+ repo_info: repo_info
32
+ }
33
+ end
34
+ expect(repos).to eq [
35
+ {
36
+ github_url: 'https://my_gh.my_domain.com/',
37
+ repo_info: {
38
+ name: 'repo1',
39
+ slug: 'GH-User1/repo1'
40
+ }
41
+ },
42
+ {
43
+ github_url: 'https://my_gh.my_domain.com/',
44
+ repo_info: {
45
+ name: 'repo2',
46
+ slug: 'GH-User1/repo2'
47
+ }
48
+ },
49
+ {
50
+ github_url: 'https://api.github.com/',
51
+ repo_info: {
52
+ name: 'repo3',
53
+ slug: 'GH-User2/repo3'
54
+ }
55
+ },
56
+ {
57
+ github_url: 'https://api.github.com/',
58
+ repo_info: {
59
+ name: 'repo4',
60
+ slug: 'GH-User2/repo4'
61
+ }
62
+ }
63
+ ]
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -14,33 +14,45 @@ describe 'last_deploys executable' do
14
14
 
15
15
  it 'checks all nodes by default' do
16
16
  with_test_platform_for_last_deploys do
17
- expect_actions_executor_runs([proc do |actions, timeout: nil, concurrent: false, log_to_dir: 'run_logs', log_to_stdout: true|
18
- expect(actions).to eq(
19
- 'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
20
- 'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
21
- )
17
+ expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
22
18
  {
23
- 'node1' => [0, <<~EOS, ''],
24
- date: 2019-08-21 10:12:15
25
- user: admin_user1
26
- services: service1
27
- EOS
28
- 'node2' => [0, <<~EOS, '']
29
- date: 2019-08-22 10:12:15
30
- user: admin_user2
31
- services: service1, service2
32
- EOS
19
+ 'node1' => {
20
+ services: %w[service1],
21
+ deployment_info: {
22
+ repo_name_0: 'platform',
23
+ commit_id_0: 'abcdef1',
24
+ exit_status: 0,
25
+ date: Time.parse('2019-08-21 10:12:15 UTC'),
26
+ user: 'admin_user1'
27
+ },
28
+ exit_status: 0,
29
+ stdout: '',
30
+ stderr: ''
31
+ },
32
+ 'node2' => {
33
+ services: %w[service1 service2],
34
+ deployment_info: {
35
+ repo_name_0: 'platform',
36
+ commit_id_0: 'abcdef2',
37
+ exit_status: 0,
38
+ date: Time.parse('2019-08-22 10:12:15 UTC'),
39
+ user: 'admin_user2'
40
+ },
41
+ exit_status: 0,
42
+ stdout: '',
43
+ stderr: ''
44
+ }
33
45
  }
34
- end])
46
+ end
35
47
  exit_code, stdout, stderr = run 'last_deploys'
36
48
  expect(exit_code).to eq 0
37
49
  expect(stdout).to eq(<<~EOS)
38
- +-------+---------------------+-------------+--------------------+-------+
39
- | Node | Date | Admin | Services | Error |
40
- +-------+---------------------+-------------+--------------------+-------+
41
- | node1 | 2019-08-21 10:12:15 | admin_user1 | service1 | |
42
- | node2 | 2019-08-22 10:12:15 | admin_user2 | service1, service2 | |
43
- +-------+---------------------+-------------+--------------------+-------+
50
+ +-------+-------------------------+-------------+--------------------+-------+
51
+ | Node | Date | Admin | Services | Error |
52
+ +-------+-------------------------+-------------+--------------------+-------+
53
+ | node1 | 2019-08-21 10:12:15 UTC | admin_user1 | service1 | |
54
+ | node2 | 2019-08-22 10:12:15 UTC | admin_user2 | service1, service2 | |
55
+ +-------+-------------------------+-------------+--------------------+-------+
44
56
  EOS
45
57
  expect(stderr).to eq ''
46
58
  end
@@ -48,33 +60,45 @@ describe 'last_deploys executable' do
48
60
 
49
61
  it 'sorts results by user' do
50
62
  with_test_platform_for_last_deploys do
51
- expect_actions_executor_runs([proc do |actions, timeout: nil, concurrent: false, log_to_dir: 'run_logs', log_to_stdout: true|
52
- expect(actions).to eq(
53
- 'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
54
- 'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
55
- )
63
+ expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
56
64
  {
57
- 'node1' => [0, <<~EOS, ''],
58
- date: 2019-08-21 10:12:15
59
- user: admin_user2
60
- services: service1
61
- EOS
62
- 'node2' => [0, <<~EOS, '']
63
- date: 2019-08-22 10:12:15
64
- user: admin_user1
65
- services: service1, service2
66
- EOS
65
+ 'node1' => {
66
+ services: %w[service1],
67
+ deployment_info: {
68
+ repo_name_0: 'platform',
69
+ commit_id_0: 'abcdef1',
70
+ exit_status: 0,
71
+ date: Time.parse('2019-08-21 10:12:15 UTC'),
72
+ user: 'admin_user2'
73
+ },
74
+ exit_status: 0,
75
+ stdout: '',
76
+ stderr: ''
77
+ },
78
+ 'node2' => {
79
+ services: %w[service1 service2],
80
+ deployment_info: {
81
+ repo_name_0: 'platform',
82
+ commit_id_0: 'abcdef2',
83
+ exit_status: 0,
84
+ date: Time.parse('2019-08-22 10:12:15 UTC'),
85
+ user: 'admin_user1'
86
+ },
87
+ exit_status: 0,
88
+ stdout: '',
89
+ stderr: ''
90
+ }
67
91
  }
68
- end])
92
+ end
69
93
  exit_code, stdout, stderr = run 'last_deploys', '--sort-by', 'user'
70
94
  expect(exit_code).to eq 0
71
95
  expect(stdout).to eq(<<~EOS)
72
- +-------+---------------------+-------------+--------------------+-------+
73
- | Node | Date | Admin | Services | Error |
74
- +-------+---------------------+-------------+--------------------+-------+
75
- | node2 | 2019-08-22 10:12:15 | admin_user1 | service1, service2 | |
76
- | node1 | 2019-08-21 10:12:15 | admin_user2 | service1 | |
77
- +-------+---------------------+-------------+--------------------+-------+
96
+ +-------+-------------------------+-------------+--------------------+-------+
97
+ | Node | Date | Admin | Services | Error |
98
+ +-------+-------------------------+-------------+--------------------+-------+
99
+ | node2 | 2019-08-22 10:12:15 UTC | admin_user1 | service1, service2 | |
100
+ | node1 | 2019-08-21 10:12:15 UTC | admin_user2 | service1 | |
101
+ +-------+-------------------------+-------------+--------------------+-------+
78
102
  EOS
79
103
  expect(stderr).to eq ''
80
104
  end
@@ -82,33 +106,45 @@ describe 'last_deploys executable' do
82
106
 
83
107
  it 'sorts results by user descending' do
84
108
  with_test_platform_for_last_deploys do
85
- expect_actions_executor_runs([proc do |actions, timeout: nil, concurrent: false, log_to_dir: 'run_logs', log_to_stdout: true|
86
- expect(actions).to eq(
87
- 'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
88
- 'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
89
- )
109
+ expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
90
110
  {
91
- 'node1' => [0, <<~EOS, ''],
92
- date: 2019-08-21 10:12:15
93
- user: admin_user2
94
- services: service1
95
- EOS
96
- 'node2' => [0, <<~EOS, '']
97
- date: 2019-08-22 10:12:15
98
- user: admin_user1
99
- services: service1, service2
100
- EOS
111
+ 'node1' => {
112
+ services: %w[service1],
113
+ deployment_info: {
114
+ repo_name_0: 'platform',
115
+ commit_id_0: 'abcdef1',
116
+ exit_status: 0,
117
+ date: Time.parse('2019-08-21 10:12:15 UTC'),
118
+ user: 'admin_user2'
119
+ },
120
+ exit_status: 0,
121
+ stdout: '',
122
+ stderr: ''
123
+ },
124
+ 'node2' => {
125
+ services: %w[service1 service2],
126
+ deployment_info: {
127
+ repo_name_0: 'platform',
128
+ commit_id_0: 'abcdef2',
129
+ exit_status: 0,
130
+ date: Time.parse('2019-08-22 10:12:15 UTC'),
131
+ user: 'admin_user1'
132
+ },
133
+ exit_status: 0,
134
+ stdout: '',
135
+ stderr: ''
136
+ }
101
137
  }
102
- end])
138
+ end
103
139
  exit_code, stdout, stderr = run 'last_deploys', '--sort-by', 'user_desc'
104
140
  expect(exit_code).to eq 0
105
141
  expect(stdout).to eq(<<~EOS)
106
- +-------+---------------------+-------------+--------------------+-------+
107
- | Node | Date | Admin | Services | Error |
108
- +-------+---------------------+-------------+--------------------+-------+
109
- | node1 | 2019-08-21 10:12:15 | admin_user2 | service1 | |
110
- | node2 | 2019-08-22 10:12:15 | admin_user1 | service1, service2 | |
111
- +-------+---------------------+-------------+--------------------+-------+
142
+ +-------+-------------------------+-------------+--------------------+-------+
143
+ | Node | Date | Admin | Services | Error |
144
+ +-------+-------------------------+-------------+--------------------+-------+
145
+ | node1 | 2019-08-21 10:12:15 UTC | admin_user2 | service1 | |
146
+ | node2 | 2019-08-22 10:12:15 UTC | admin_user1 | service1, service2 | |
147
+ +-------+-------------------------+-------------+--------------------+-------+
112
148
  EOS
113
149
  expect(stderr).to eq ''
114
150
  end
@@ -116,24 +152,31 @@ describe 'last_deploys executable' do
116
152
 
117
153
  it 'displays only the selected nodes' do
118
154
  with_test_platform_for_last_deploys do
119
- expect_actions_executor_runs([proc do |actions, timeout: nil, concurrent: false, log_to_dir: 'run_logs', log_to_stdout: true|
120
- expect(actions).to eq('node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" })
155
+ expect(test_deployer).to receive(:deployment_info_from).with(%w[node1]) do
121
156
  {
122
- 'node1' => [0, <<~EOS, ''],
123
- date: 2019-08-21 10:12:15
124
- user: admin_user1
125
- services: service1
126
- EOS
157
+ 'node1' => {
158
+ services: %w[service1],
159
+ deployment_info: {
160
+ repo_name_0: 'platform',
161
+ commit_id_0: 'abcdef1',
162
+ exit_status: 0,
163
+ date: Time.parse('2019-08-21 10:12:15 UTC'),
164
+ user: 'admin_user1'
165
+ },
166
+ exit_status: 0,
167
+ stdout: '',
168
+ stderr: ''
169
+ }
127
170
  }
128
- end])
171
+ end
129
172
  exit_code, stdout, stderr = run 'last_deploys', '--node', 'node1'
130
173
  expect(exit_code).to eq 0
131
174
  expect(stdout).to eq(<<~EOS)
132
- +-------+---------------------+-------------+----------+-------+
133
- | Node | Date | Admin | Services | Error |
134
- +-------+---------------------+-------------+----------+-------+
135
- | node1 | 2019-08-21 10:12:15 | admin_user1 | service1 | |
136
- +-------+---------------------+-------------+----------+-------+
175
+ +-------+-------------------------+-------------+----------+-------+
176
+ | Node | Date | Admin | Services | Error |
177
+ +-------+-------------------------+-------------+----------+-------+
178
+ | node1 | 2019-08-21 10:12:15 UTC | admin_user1 | service1 | |
179
+ +-------+-------------------------+-------------+----------+-------+
137
180
  EOS
138
181
  expect(stderr).to eq ''
139
182
  end
@@ -141,30 +184,35 @@ describe 'last_deploys executable' do
141
184
 
142
185
  it 'displays errors when we can\'t get info from some nodes' do
143
186
  with_test_platform_for_last_deploys do
144
- expect_actions_executor_runs([proc do |actions, timeout: nil, concurrent: false, log_to_dir: 'run_logs', log_to_stdout: true|
145
- expect(actions).to eq(
146
- 'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
147
- 'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
148
- )
187
+ expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
149
188
  {
150
- 'node1' => [:connection_error, 'Error on stdout', 'Error on stderr'],
151
- 'node2' => [0, <<~EOS, '']
152
- date: 2019-08-22 10:12:15
153
- user: admin_user1
154
- services: service1, service2
155
- EOS
189
+ 'node1' => {
190
+ error: 'Error while getting logs'
191
+ },
192
+ 'node2' => {
193
+ services: %w[service1 service2],
194
+ deployment_info: {
195
+ repo_name_0: 'platform',
196
+ commit_id_0: 'abcdef2',
197
+ exit_status: 0,
198
+ date: Time.parse('2019-08-22 10:12:15 UTC'),
199
+ user: 'admin_user2'
200
+ },
201
+ exit_status: 0,
202
+ stdout: '',
203
+ stderr: ''
204
+ }
156
205
  }
157
- end])
206
+ end
158
207
  exit_code, stdout, stderr = run 'last_deploys', '--sort-by', 'user_desc'
159
208
  expect(exit_code).to eq 0
160
209
  expect(stdout).to eq(<<~EOS)
161
- +-------+---------------------+-------------+--------------------+-------------------------+
162
- | Node | Date | Admin | Services | Error |
163
- +-------+---------------------+-------------+--------------------+-------------------------+
164
- | node2 | 2019-08-22 10:12:15 | admin_user1 | service1, service2 | |
165
- | node1 | | | | Error: connection_error |
166
- | | | | | Error on stderr |
167
- +-------+---------------------+-------------+--------------------+-------------------------+
210
+ +-------+-------------------------+-------------+--------------------+--------------------------+
211
+ | Node | Date | Admin | Services | Error |
212
+ +-------+-------------------------+-------------+--------------------+--------------------------+
213
+ | node2 | 2019-08-22 10:12:15 UTC | admin_user2 | service1, service2 | |
214
+ | node1 | | | | Error while getting logs |
215
+ +-------+-------------------------+-------------+--------------------+--------------------------+
168
216
  EOS
169
217
  expect(stderr).to eq ''
170
218
  end