hybrid_platforms_conductor 32.16.3 → 33.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +6 -3
- data/bin/last_deploys +4 -1
- data/bin/nodes_to_deploy +5 -5
- data/docs/config_dsl.md +45 -1
- data/docs/executables.md +6 -7
- data/docs/executables/check-node.md +3 -3
- data/docs/executables/deploy.md +3 -3
- data/docs/executables/dump_nodes_json.md +3 -3
- data/docs/executables/test.md +3 -3
- data/docs/executables/topograph.md +3 -3
- data/docs/gen/mermaid/README.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/check-node.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/deploy.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/free_ips.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/get_impacted_nodes.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/last_deploys.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/nodes_to_deploy.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/report.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/run.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/ssh_config.md-0.png +0 -0
- data/docs/gen/mermaid/docs/executables/test.md-0.png +0 -0
- data/docs/plugins.md +47 -0
- data/docs/plugins/connector/ssh.md +1 -1
- data/docs/plugins/log/remote_fs.md +26 -0
- data/docs/plugins/secrets_reader/cli.md +31 -0
- data/docs/plugins/secrets_reader/thycotic.md +46 -0
- data/docs/plugins/test/bitbucket_conf.md +1 -1
- data/docs/plugins/test/check_deploy_and_idempotence.md +1 -1
- data/docs/plugins/test/connection.md +1 -0
- data/docs/plugins/test/deploy_removes_root_access.md +1 -1
- data/docs/plugins/test/file_system.md +1 -0
- data/docs/plugins/test/github_ci.md +48 -0
- data/docs/plugins/test/hostname.md +1 -0
- data/docs/plugins/test/ip.md +1 -0
- data/docs/plugins/test/jenkins_ci_conf.md +1 -1
- data/docs/plugins/test/jenkins_ci_masters_ok.md +1 -1
- data/docs/plugins/test/local_users.md +1 -0
- data/docs/plugins/test/mounts.md +1 -0
- data/docs/plugins/test/orphan_files.md +1 -0
- data/docs/plugins/test/ports.md +1 -0
- data/docs/plugins/test/spectre.md +1 -0
- data/docs/plugins/test/vulnerabilities.md +1 -0
- data/lib/hybrid_platforms_conductor/actions_executor.rb +8 -1
- data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +62 -0
- data/lib/hybrid_platforms_conductor/deployer.rb +193 -141
- data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +3 -3
- data/lib/hybrid_platforms_conductor/hpc_plugins/log/my_log_plugin.rb.sample +100 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +179 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/cli.rb +75 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/my_secrets_reader_plugin.rb.sample +46 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +87 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/check_deploy_and_idempotence.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/connection.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +7 -20
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_removes_root_access.rb +1 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +2 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +32 -0
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/ports.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +3 -1
- data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +2 -1
- data/lib/hybrid_platforms_conductor/log.rb +31 -0
- data/lib/hybrid_platforms_conductor/plugins.rb +1 -0
- data/lib/hybrid_platforms_conductor/secrets_reader.rb +31 -0
- data/lib/hybrid_platforms_conductor/test_only_remote_node.rb +18 -0
- data/lib/hybrid_platforms_conductor/version.rb +1 -1
- data/spec/hybrid_platforms_conductor_test.rb +27 -6
- data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/connections_spec.rb +3 -3
- data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +46 -4
- data/spec/hybrid_platforms_conductor_test/api/deployer/deploy_spec.rb +187 -212
- data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +223 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +4 -4
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/cli_spec.rb +63 -0
- data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +253 -0
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/global_spec.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +72 -0
- data/spec/hybrid_platforms_conductor_test/executables/last_deploys_spec.rb +146 -98
- data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +240 -83
- data/spec/hybrid_platforms_conductor_test/executables/options/common_spec.rb +2 -1
- data/spec/hybrid_platforms_conductor_test/executables/options/deployer_spec.rb +0 -182
- data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +1 -1
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +40 -53
- data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +251 -15
- data/spec/hybrid_platforms_conductor_test/test_log_no_read_plugin.rb +82 -0
- data/spec/hybrid_platforms_conductor_test/test_log_plugin.rb +103 -0
- data/spec/hybrid_platforms_conductor_test/test_secrets_reader_plugin.rb +45 -0
- metadata +41 -2
|
@@ -8,23 +8,43 @@ describe 'nodes_to_deploy executable' do
|
|
|
8
8
|
# * Parameters::
|
|
9
9
|
# * *repository* (String): Platform's repository
|
|
10
10
|
def with_test_platform_for_nodes_to_deploy(additional_platforms_content: '')
|
|
11
|
-
with_test_platform(
|
|
11
|
+
with_test_platform(
|
|
12
|
+
{ nodes: { 'node1' => {}, 'node2' => {} } },
|
|
13
|
+
false,
|
|
14
|
+
additional_platforms_content + "\nsend_logs_to :test_log"
|
|
15
|
+
) do |repository|
|
|
12
16
|
yield repository
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
|
|
16
20
|
it 'returns all nodes by default' do
|
|
17
21
|
with_test_platform_for_nodes_to_deploy do
|
|
18
|
-
|
|
19
|
-
expect(actions).to eq(
|
|
20
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
21
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
22
|
-
)
|
|
22
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
23
23
|
{
|
|
24
|
-
'node1' =>
|
|
25
|
-
|
|
24
|
+
'node1' => {
|
|
25
|
+
services: %w[service1],
|
|
26
|
+
deployment_info: {
|
|
27
|
+
repo_name_0: 'platform',
|
|
28
|
+
commit_id_0: 'abcdef1',
|
|
29
|
+
exit_status: 0
|
|
30
|
+
},
|
|
31
|
+
exit_status: 0,
|
|
32
|
+
stdout: '',
|
|
33
|
+
stderr: ''
|
|
34
|
+
},
|
|
35
|
+
'node2' => {
|
|
36
|
+
services: %w[service2],
|
|
37
|
+
deployment_info: {
|
|
38
|
+
repo_name_0: 'platform',
|
|
39
|
+
commit_id_0: 'abcdef2',
|
|
40
|
+
exit_status: 0
|
|
41
|
+
},
|
|
42
|
+
exit_status: 0,
|
|
43
|
+
stdout: '',
|
|
44
|
+
stderr: ''
|
|
45
|
+
}
|
|
26
46
|
}
|
|
27
|
-
end
|
|
47
|
+
end
|
|
28
48
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
29
49
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
30
50
|
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
@@ -41,14 +61,21 @@ describe 'nodes_to_deploy executable' do
|
|
|
41
61
|
|
|
42
62
|
it 'can filter nodes' do
|
|
43
63
|
with_test_platform_for_nodes_to_deploy do
|
|
44
|
-
|
|
45
|
-
expect(actions).to eq(
|
|
46
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
47
|
-
)
|
|
64
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node2]) do
|
|
48
65
|
{
|
|
49
|
-
'node2' =>
|
|
66
|
+
'node2' => {
|
|
67
|
+
services: %w[service2],
|
|
68
|
+
deployment_info: {
|
|
69
|
+
repo_name_0: 'platform',
|
|
70
|
+
commit_id_0: 'abcdef2',
|
|
71
|
+
exit_status: 0
|
|
72
|
+
},
|
|
73
|
+
exit_status: 0,
|
|
74
|
+
stdout: '',
|
|
75
|
+
stderr: ''
|
|
76
|
+
}
|
|
50
77
|
}
|
|
51
|
-
end
|
|
78
|
+
end
|
|
52
79
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
53
80
|
exit_code, stdout, stderr = run 'nodes_to_deploy', '--node', 'node2'
|
|
54
81
|
expect(exit_code).to eq 0
|
|
@@ -63,16 +90,32 @@ describe 'nodes_to_deploy executable' do
|
|
|
63
90
|
|
|
64
91
|
it 'does not return nodes that have no impact' do
|
|
65
92
|
with_test_platform_for_nodes_to_deploy do
|
|
66
|
-
|
|
67
|
-
expect(actions).to eq(
|
|
68
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
69
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
70
|
-
)
|
|
93
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
71
94
|
{
|
|
72
|
-
'node1' =>
|
|
73
|
-
|
|
95
|
+
'node1' => {
|
|
96
|
+
services: %w[service1],
|
|
97
|
+
deployment_info: {
|
|
98
|
+
repo_name_0: 'platform',
|
|
99
|
+
commit_id_0: 'abcdef1',
|
|
100
|
+
exit_status: 0
|
|
101
|
+
},
|
|
102
|
+
exit_status: 0,
|
|
103
|
+
stdout: '',
|
|
104
|
+
stderr: ''
|
|
105
|
+
},
|
|
106
|
+
'node2' => {
|
|
107
|
+
services: %w[service2],
|
|
108
|
+
deployment_info: {
|
|
109
|
+
repo_name_0: 'platform',
|
|
110
|
+
commit_id_0: 'abcdef2',
|
|
111
|
+
exit_status: 0
|
|
112
|
+
},
|
|
113
|
+
exit_status: 0,
|
|
114
|
+
stdout: '',
|
|
115
|
+
stderr: ''
|
|
116
|
+
}
|
|
74
117
|
}
|
|
75
|
-
end
|
|
118
|
+
end
|
|
76
119
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') { [%w[node1], [], [], false] }
|
|
77
120
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[], [], [], false] }
|
|
78
121
|
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
@@ -86,16 +129,28 @@ describe 'nodes_to_deploy executable' do
|
|
|
86
129
|
|
|
87
130
|
it 'considers nodes having no repository info in their logs to be deployed' do
|
|
88
131
|
with_test_platform_for_nodes_to_deploy do
|
|
89
|
-
|
|
90
|
-
expect(actions).to eq(
|
|
91
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
92
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
93
|
-
)
|
|
132
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
94
133
|
{
|
|
95
|
-
'node1' =>
|
|
96
|
-
|
|
134
|
+
'node1' => {
|
|
135
|
+
services: %w[service1],
|
|
136
|
+
deployment_info: {},
|
|
137
|
+
exit_status: 0,
|
|
138
|
+
stdout: '',
|
|
139
|
+
stderr: ''
|
|
140
|
+
},
|
|
141
|
+
'node2' => {
|
|
142
|
+
services: %w[service2],
|
|
143
|
+
deployment_info: {
|
|
144
|
+
repo_name_0: 'platform',
|
|
145
|
+
commit_id_0: 'abcdef2',
|
|
146
|
+
exit_status: 0
|
|
147
|
+
},
|
|
148
|
+
exit_status: 0,
|
|
149
|
+
stdout: '',
|
|
150
|
+
stderr: ''
|
|
151
|
+
}
|
|
97
152
|
}
|
|
98
|
-
end
|
|
153
|
+
end
|
|
99
154
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[], [], [], false] }
|
|
100
155
|
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
101
156
|
expect(exit_code).to eq 0
|
|
@@ -108,16 +163,32 @@ describe 'nodes_to_deploy executable' do
|
|
|
108
163
|
|
|
109
164
|
it 'considers nodes having invalid commit ids in their logs to be deployed' do
|
|
110
165
|
with_test_platform_for_nodes_to_deploy do
|
|
111
|
-
|
|
112
|
-
expect(actions).to eq(
|
|
113
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
114
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
115
|
-
)
|
|
166
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
116
167
|
{
|
|
117
|
-
'node1' =>
|
|
118
|
-
|
|
168
|
+
'node1' => {
|
|
169
|
+
services: %w[service1],
|
|
170
|
+
deployment_info: {
|
|
171
|
+
repo_name_0: 'platform',
|
|
172
|
+
commit_id_0: 'abcdef1',
|
|
173
|
+
exit_status: 0
|
|
174
|
+
},
|
|
175
|
+
exit_status: 0,
|
|
176
|
+
stdout: '',
|
|
177
|
+
stderr: ''
|
|
178
|
+
},
|
|
179
|
+
'node2' => {
|
|
180
|
+
services: %w[service2],
|
|
181
|
+
deployment_info: {
|
|
182
|
+
repo_name_0: 'platform',
|
|
183
|
+
commit_id_0: 'abcdef2',
|
|
184
|
+
exit_status: 0
|
|
185
|
+
},
|
|
186
|
+
exit_status: 0,
|
|
187
|
+
stdout: '',
|
|
188
|
+
stderr: ''
|
|
189
|
+
}
|
|
119
190
|
}
|
|
120
|
-
end
|
|
191
|
+
end
|
|
121
192
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') do
|
|
122
193
|
raise HybridPlatformsConductor::NodesHandler::GitError, 'Mocked git error due to an invalid commit id'
|
|
123
194
|
end
|
|
@@ -148,14 +219,21 @@ describe 'nodes_to_deploy executable' do
|
|
|
148
219
|
for_nodes(\'node1\') { deployment_schedule(IceCube::Schedule.new(Time.now.utc - 120, duration: 60)) }
|
|
149
220
|
for_nodes(\'node2\') { deployment_schedule(IceCube::Schedule.new(Time.now.utc - 60, duration: 120)) }
|
|
150
221
|
') do
|
|
151
|
-
|
|
152
|
-
expect(actions).to eq(
|
|
153
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
154
|
-
)
|
|
222
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node2]) do
|
|
155
223
|
{
|
|
156
|
-
'node2' =>
|
|
224
|
+
'node2' => {
|
|
225
|
+
services: %w[service2],
|
|
226
|
+
deployment_info: {
|
|
227
|
+
repo_name_0: 'platform',
|
|
228
|
+
commit_id_0: 'abcdef2',
|
|
229
|
+
exit_status: 0
|
|
230
|
+
},
|
|
231
|
+
exit_status: 0,
|
|
232
|
+
stdout: '',
|
|
233
|
+
stderr: ''
|
|
234
|
+
}
|
|
157
235
|
}
|
|
158
|
-
end
|
|
236
|
+
end
|
|
159
237
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
160
238
|
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
161
239
|
expect(exit_code).to eq 0
|
|
@@ -172,14 +250,21 @@ describe 'nodes_to_deploy executable' do
|
|
|
172
250
|
for_nodes(\'node1\') { deployment_schedule(IceCube::Schedule.new(Time.now.utc - 120, duration: 60)) }
|
|
173
251
|
for_nodes(\'node2\') { deployment_schedule(IceCube::Schedule.new(Time.now.utc - 60, duration: 120)) }
|
|
174
252
|
') do
|
|
175
|
-
|
|
176
|
-
expect(actions).to eq(
|
|
177
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
178
|
-
)
|
|
253
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1]) do
|
|
179
254
|
{
|
|
180
|
-
'node1' =>
|
|
255
|
+
'node1' => {
|
|
256
|
+
services: %w[service1],
|
|
257
|
+
deployment_info: {
|
|
258
|
+
repo_name_0: 'platform',
|
|
259
|
+
commit_id_0: 'abcdef1',
|
|
260
|
+
exit_status: 0
|
|
261
|
+
},
|
|
262
|
+
exit_status: 0,
|
|
263
|
+
stdout: '',
|
|
264
|
+
stderr: ''
|
|
265
|
+
}
|
|
181
266
|
}
|
|
182
|
-
end
|
|
267
|
+
end
|
|
183
268
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
184
269
|
# 90 seconds before now, the schedule should match only node1
|
|
185
270
|
exit_code, stdout, stderr = run 'nodes_to_deploy', '--deployment-time', (Time.now.utc - 90).strftime('%F %T')
|
|
@@ -197,16 +282,32 @@ describe 'nodes_to_deploy executable' do
|
|
|
197
282
|
for_nodes(\'node1\') { deployment_schedule(IceCube::Schedule.new(Time.now.utc - 120, duration: 60)) }
|
|
198
283
|
for_nodes(\'node2\') { deployment_schedule(IceCube::Schedule.new(Time.now.utc - 60, duration: 120)) }
|
|
199
284
|
') do
|
|
200
|
-
|
|
201
|
-
expect(actions).to eq(
|
|
202
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
203
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
204
|
-
)
|
|
285
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
205
286
|
{
|
|
206
|
-
'node1' =>
|
|
207
|
-
|
|
287
|
+
'node1' => {
|
|
288
|
+
services: %w[service1],
|
|
289
|
+
deployment_info: {
|
|
290
|
+
repo_name_0: 'platform',
|
|
291
|
+
commit_id_0: 'abcdef1',
|
|
292
|
+
exit_status: 0
|
|
293
|
+
},
|
|
294
|
+
exit_status: 0,
|
|
295
|
+
stdout: '',
|
|
296
|
+
stderr: ''
|
|
297
|
+
},
|
|
298
|
+
'node2' => {
|
|
299
|
+
services: %w[service2],
|
|
300
|
+
deployment_info: {
|
|
301
|
+
repo_name_0: 'platform',
|
|
302
|
+
commit_id_0: 'abcdef2',
|
|
303
|
+
exit_status: 0
|
|
304
|
+
},
|
|
305
|
+
exit_status: 0,
|
|
306
|
+
stdout: '',
|
|
307
|
+
stderr: ''
|
|
308
|
+
}
|
|
208
309
|
}
|
|
209
|
-
end
|
|
310
|
+
end
|
|
210
311
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef1', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
211
312
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform', from_commit: 'abcdef2', to_commit: 'master') { [%w[node1 node2], [], [], false] }
|
|
212
313
|
exit_code, stdout, stderr = run 'nodes_to_deploy', '--ignore-schedule'
|
|
@@ -225,16 +326,32 @@ describe 'nodes_to_deploy executable' do
|
|
|
225
326
|
'platform1' => { nodes: { 'node1' => {}, 'node2' => {} } },
|
|
226
327
|
'platform2' => { nodes: {} }
|
|
227
328
|
) do
|
|
228
|
-
|
|
229
|
-
expect(actions).to eq(
|
|
230
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
231
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
232
|
-
)
|
|
329
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
233
330
|
{
|
|
234
|
-
'node1' =>
|
|
235
|
-
|
|
331
|
+
'node1' => {
|
|
332
|
+
services: %w[service1],
|
|
333
|
+
deployment_info: {
|
|
334
|
+
repo_name_0: 'platform1',
|
|
335
|
+
commit_id_0: 'abcdef1',
|
|
336
|
+
exit_status: 0
|
|
337
|
+
},
|
|
338
|
+
exit_status: 0,
|
|
339
|
+
stdout: '',
|
|
340
|
+
stderr: ''
|
|
341
|
+
},
|
|
342
|
+
'node2' => {
|
|
343
|
+
services: %w[service2],
|
|
344
|
+
deployment_info: {
|
|
345
|
+
repo_name_0: 'platform2',
|
|
346
|
+
commit_id_0: 'abcdef2',
|
|
347
|
+
exit_status: 0
|
|
348
|
+
},
|
|
349
|
+
exit_status: 0,
|
|
350
|
+
stdout: '',
|
|
351
|
+
stderr: ''
|
|
352
|
+
}
|
|
236
353
|
}
|
|
237
|
-
end
|
|
354
|
+
end
|
|
238
355
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform1', from_commit: 'abcdef1', to_commit: 'master') { [%w[node1], [], [], false] }
|
|
239
356
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform2', from_commit: 'abcdef2', to_commit: 'master') { [%w[node2], [], [], false] }
|
|
240
357
|
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
@@ -253,16 +370,36 @@ describe 'nodes_to_deploy executable' do
|
|
|
253
370
|
'platform2' => { nodes: {} },
|
|
254
371
|
'platform3' => { nodes: {} }
|
|
255
372
|
) do
|
|
256
|
-
|
|
257
|
-
expect(actions).to eq(
|
|
258
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
259
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
260
|
-
)
|
|
373
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
261
374
|
{
|
|
262
|
-
'node1' =>
|
|
263
|
-
|
|
375
|
+
'node1' => {
|
|
376
|
+
services: %w[service1],
|
|
377
|
+
deployment_info: {
|
|
378
|
+
repo_name_0: 'platform1',
|
|
379
|
+
commit_id_0: 'abcdef1',
|
|
380
|
+
repo_name_1: 'platform2',
|
|
381
|
+
commit_id_1: '1234567',
|
|
382
|
+
exit_status: 0
|
|
383
|
+
},
|
|
384
|
+
exit_status: 0,
|
|
385
|
+
stdout: '',
|
|
386
|
+
stderr: ''
|
|
387
|
+
},
|
|
388
|
+
'node2' => {
|
|
389
|
+
services: %w[service2],
|
|
390
|
+
deployment_info: {
|
|
391
|
+
repo_name_0: 'platform2',
|
|
392
|
+
commit_id_0: 'abcdef2',
|
|
393
|
+
repo_name_1: 'platform3',
|
|
394
|
+
commit_id_1: '2345678',
|
|
395
|
+
exit_status: 0
|
|
396
|
+
},
|
|
397
|
+
exit_status: 0,
|
|
398
|
+
stdout: '',
|
|
399
|
+
stderr: ''
|
|
400
|
+
}
|
|
264
401
|
}
|
|
265
|
-
end
|
|
402
|
+
end
|
|
266
403
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform1', from_commit: 'abcdef1', to_commit: 'master') { [%w[], [], [], false] }
|
|
267
404
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform2', from_commit: '1234567', to_commit: 'master') { [%w[node1], [], [], false] }
|
|
268
405
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform2', from_commit: 'abcdef2', to_commit: 'master') { [%w[], [], [], false] }
|
|
@@ -283,16 +420,36 @@ describe 'nodes_to_deploy executable' do
|
|
|
283
420
|
'platform2' => { nodes: {} },
|
|
284
421
|
'platform3' => { nodes: {} }
|
|
285
422
|
) do
|
|
286
|
-
|
|
287
|
-
expect(actions).to eq(
|
|
288
|
-
'node1' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" },
|
|
289
|
-
'node2' => { remote_bash: "cd /var/log/deployments && ls -t | head -1 | xargs sed '/===== STDOUT =====/q'" }
|
|
290
|
-
)
|
|
423
|
+
expect(test_deployer).to receive(:deployment_info_from).with(%w[node1 node2]) do
|
|
291
424
|
{
|
|
292
|
-
'node1' =>
|
|
293
|
-
|
|
425
|
+
'node1' => {
|
|
426
|
+
services: %w[service1],
|
|
427
|
+
deployment_info: {
|
|
428
|
+
repo_name_0: 'platform1',
|
|
429
|
+
commit_id_0: 'abcdef1',
|
|
430
|
+
repo_name_1: 'platform2',
|
|
431
|
+
commit_id_1: '1234567',
|
|
432
|
+
exit_status: 0
|
|
433
|
+
},
|
|
434
|
+
exit_status: 0,
|
|
435
|
+
stdout: '',
|
|
436
|
+
stderr: ''
|
|
437
|
+
},
|
|
438
|
+
'node2' => {
|
|
439
|
+
services: %w[service2],
|
|
440
|
+
deployment_info: {
|
|
441
|
+
repo_name_0: 'platform2',
|
|
442
|
+
commit_id_0: 'abcdef2',
|
|
443
|
+
repo_name_1: 'platform3',
|
|
444
|
+
commit_id_1: '2345678',
|
|
445
|
+
exit_status: 0
|
|
446
|
+
},
|
|
447
|
+
exit_status: 0,
|
|
448
|
+
stdout: '',
|
|
449
|
+
stderr: ''
|
|
450
|
+
}
|
|
294
451
|
}
|
|
295
|
-
end
|
|
452
|
+
end
|
|
296
453
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform1', from_commit: 'abcdef1', to_commit: 'master') { [%w[node1], [], [], false] }
|
|
297
454
|
expect(test_nodes_handler).to receive(:impacted_nodes_from_git_diff).with('platform2', from_commit: 'abcdef2', to_commit: 'master') { [%w[node2], [], [], false] }
|
|
298
455
|
exit_code, stdout, stderr = run 'nodes_to_deploy'
|
|
@@ -12,7 +12,8 @@ describe 'executables\' common options' do
|
|
|
12
12
|
nodes: { 'node1' => { meta: { host_ip: '192.168.42.42' }, services: ['node1_service'] } },
|
|
13
13
|
deployable_services: %w[node1_service]
|
|
14
14
|
},
|
|
15
|
-
true
|
|
15
|
+
true,
|
|
16
|
+
'send_logs_to :test_log'
|
|
16
17
|
) do |repository|
|
|
17
18
|
yield repository
|
|
18
19
|
end
|
|
@@ -12,188 +12,6 @@ describe 'executables\' Deployer options' do
|
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
# Mock calls being made to a Thycotic SOAP API using Savon
|
|
16
|
-
#
|
|
17
|
-
# Parameters::
|
|
18
|
-
# * *url* (String): Mocked URL
|
|
19
|
-
# * *secret_id* (String): The mocked secret ID
|
|
20
|
-
# * *mocked_secrets_file* (String or nil): The mocked secrets file stored in Thycotic, or nil to mock a missing secret
|
|
21
|
-
# * *user* (String or nil): The user to be expected, or nil if it should be read from netrc [default: nil]
|
|
22
|
-
# * *password* (String or nil): The password to be expected, or nil if it should be read from netrc [default: nil]
|
|
23
|
-
def mock_thycotic_file_download_on(url, secret_id, mocked_secrets_file, user: nil, password: nil)
|
|
24
|
-
if user.nil?
|
|
25
|
-
user = 'thycotic_user_from_netrc'
|
|
26
|
-
password = 'thycotic_password_from_netrc'
|
|
27
|
-
expect(HybridPlatformsConductor::Credentials).to receive(:with_credentials_for) do |id, _logger, _logger_stderr, url: nil, &client_code|
|
|
28
|
-
expect(id).to eq :thycotic
|
|
29
|
-
expect(url).to eq url
|
|
30
|
-
client_code.call user, password
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
# Mock the Savon calls
|
|
34
|
-
mocked_savon_client = double 'Mocked Savon client'
|
|
35
|
-
expect(Savon).to receive(:client) do |params|
|
|
36
|
-
expect(params[:wsdl]).to eq "#{url}/webservices/SSWebservice.asmx?wsdl"
|
|
37
|
-
expect(params[:ssl_verify_mode]).to eq :none
|
|
38
|
-
mocked_savon_client
|
|
39
|
-
end
|
|
40
|
-
expect(mocked_savon_client).to receive(:call).with(
|
|
41
|
-
:authenticate,
|
|
42
|
-
message: {
|
|
43
|
-
username: user,
|
|
44
|
-
password: password,
|
|
45
|
-
domain: 'thycotic_auth_domain'
|
|
46
|
-
}
|
|
47
|
-
) do
|
|
48
|
-
{ authenticate_response: { authenticate_result: { token: 'soap_token' } } }
|
|
49
|
-
end
|
|
50
|
-
expect(mocked_savon_client).to receive(:call).with(
|
|
51
|
-
:get_secret,
|
|
52
|
-
message: {
|
|
53
|
-
token: 'soap_token',
|
|
54
|
-
secretId: secret_id
|
|
55
|
-
}
|
|
56
|
-
) do
|
|
57
|
-
{
|
|
58
|
-
get_secret_response: {
|
|
59
|
-
get_secret_result:
|
|
60
|
-
if mocked_secrets_file
|
|
61
|
-
{ secret: { items: { secret_item: { id: '4242' } } } }
|
|
62
|
-
else
|
|
63
|
-
{ errors: { string: 'Access Denied'}, secret_error: { error_code: 'LOAD', error_message: 'Access Denied', allows_response: false } }
|
|
64
|
-
end
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
end
|
|
68
|
-
if mocked_secrets_file
|
|
69
|
-
expect(mocked_savon_client).to receive(:call).with(
|
|
70
|
-
:download_file_attachment_by_item_id,
|
|
71
|
-
message: {
|
|
72
|
-
token: 'soap_token',
|
|
73
|
-
secretId: secret_id,
|
|
74
|
-
secretItemId: '4242'
|
|
75
|
-
}
|
|
76
|
-
) do
|
|
77
|
-
{
|
|
78
|
-
download_file_attachment_by_item_id_response: {
|
|
79
|
-
download_file_attachment_by_item_id_result: {
|
|
80
|
-
file_attachment: Base64.encode64(mocked_secrets_file)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
ENV['hpc_domain_for_thycotic'] = 'thycotic_auth_domain'
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
it 'gets secrets from a file' do
|
|
90
|
-
with_test_platform_for_deployer_options do |repository|
|
|
91
|
-
secrets_file = "#{repository}/my_secrets.json"
|
|
92
|
-
File.write(secrets_file, '{ "secret_name": "secret_value" }')
|
|
93
|
-
expect(test_deployer).to receive(:deploy_on).with(['node']) do
|
|
94
|
-
expect(test_deployer.secrets).to eq [{ 'secret_name' => 'secret_value' }]
|
|
95
|
-
{}
|
|
96
|
-
end
|
|
97
|
-
exit_code, stdout, stderr = run 'deploy', '--node', 'node', '--secrets', secrets_file
|
|
98
|
-
expect(exit_code).to eq 0
|
|
99
|
-
expect(stderr).to eq ''
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it 'gets secrets from several files' do
|
|
104
|
-
with_test_platform_for_deployer_options do |repository|
|
|
105
|
-
secrets_file1 = "#{repository}/my_secrets1.json"
|
|
106
|
-
File.write(secrets_file1, '{ "secret1": "value1" }')
|
|
107
|
-
secrets_file2 = "#{repository}/my_secrets2.json"
|
|
108
|
-
File.write(secrets_file2, '{ "secret2": "value2" }')
|
|
109
|
-
expect(test_deployer).to receive(:deploy_on).with(['node']) do
|
|
110
|
-
expect(test_deployer.secrets).to eq [{ 'secret1' => 'value1' }, { 'secret2' => 'value2' }]
|
|
111
|
-
{}
|
|
112
|
-
end
|
|
113
|
-
exit_code, stdout, stderr = run 'deploy', '--node', 'node', '--secrets', secrets_file1, '--secrets', secrets_file2
|
|
114
|
-
expect(exit_code).to eq 0
|
|
115
|
-
expect(stderr).to eq ''
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
it 'fails to get secrets from a missing file' do
|
|
120
|
-
with_test_platform_for_deployer_options do
|
|
121
|
-
expect do
|
|
122
|
-
run 'deploy', '--node', 'node', '--secrets', 'unknown_file.json'
|
|
123
|
-
end.to raise_error 'Missing secret file: unknown_file.json'
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
it 'gets secrets from a Thycotic Secret Server' do
|
|
128
|
-
with_test_platform_for_deployer_options do
|
|
129
|
-
expect(test_deployer).to receive(:deploy_on).with(['node']) do
|
|
130
|
-
expect(test_deployer.secrets).to eq [{ 'secret_name' => 'secret_value' }]
|
|
131
|
-
{}
|
|
132
|
-
end
|
|
133
|
-
mock_thycotic_file_download_on('https://my_thycotic.domain.com/SecretServer', '1107', '{ "secret_name": "secret_value" }')
|
|
134
|
-
exit_code, stdout, stderr = run 'deploy', '--node', 'node', '--secrets', 'https://my_thycotic.domain.com/SecretServer:1107'
|
|
135
|
-
expect(exit_code).to eq 0
|
|
136
|
-
expect(stderr).to eq ''
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it 'gets secrets from a Thycotic Secret Server using env variables' do
|
|
141
|
-
with_test_platform_for_deployer_options do
|
|
142
|
-
expect(test_deployer).to receive(:deploy_on).with(['node']) do
|
|
143
|
-
expect(test_deployer.secrets).to eq [{ 'secret_name' => 'secret_value' }]
|
|
144
|
-
{}
|
|
145
|
-
end
|
|
146
|
-
mock_thycotic_file_download_on(
|
|
147
|
-
'https://my_thycotic.domain.com/SecretServer',
|
|
148
|
-
'1107',
|
|
149
|
-
'{ "secret_name": "secret_value" }',
|
|
150
|
-
user: 'thycotic_user_from_env',
|
|
151
|
-
password: 'thycotic_password_from_env'
|
|
152
|
-
)
|
|
153
|
-
ENV['hpc_user_for_thycotic'] = 'thycotic_user_from_env'
|
|
154
|
-
ENV['hpc_password_for_thycotic'] = 'thycotic_password_from_env'
|
|
155
|
-
exit_code, stdout, stderr = run 'deploy', '--node', 'node', '--secrets', 'https://my_thycotic.domain.com/SecretServer:1107'
|
|
156
|
-
expect(exit_code).to eq 0
|
|
157
|
-
expect(stderr).to eq ''
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
it 'gets secrets from several Thycotic Secret Servers and files' do
|
|
162
|
-
with_test_platform_for_deployer_options do |repository|
|
|
163
|
-
secrets_file1 = "#{repository}/my_secrets1.json"
|
|
164
|
-
File.write(secrets_file1, '{ "secret1": "value1" }')
|
|
165
|
-
secrets_file3 = "#{repository}/my_secrets3.json"
|
|
166
|
-
File.write(secrets_file3, '{ "secret3": "value3" }')
|
|
167
|
-
expect(test_deployer).to receive(:deploy_on).with(['node']) do
|
|
168
|
-
expect(test_deployer.secrets).to eq [
|
|
169
|
-
{ 'secret1' => 'value1' },
|
|
170
|
-
{ 'secret2' => 'value2' },
|
|
171
|
-
{ 'secret3' => 'value3' },
|
|
172
|
-
{ 'secret4' => 'value4' }
|
|
173
|
-
]
|
|
174
|
-
{}
|
|
175
|
-
end
|
|
176
|
-
mock_thycotic_file_download_on('https://my_thycotic2.domain.com/SecretServer', '110702', '{ "secret2": "value2" }')
|
|
177
|
-
mock_thycotic_file_download_on('https://my_thycotic4.domain.com/SecretServer', '110704', '{ "secret4": "value4" }')
|
|
178
|
-
exit_code, stdout, stderr = run 'deploy', '--node', 'node',
|
|
179
|
-
'--secrets', secrets_file1,
|
|
180
|
-
'--secrets', 'https://my_thycotic2.domain.com/SecretServer:110702',
|
|
181
|
-
'--secrets', secrets_file3,
|
|
182
|
-
'--secrets', 'https://my_thycotic4.domain.com/SecretServer:110704'
|
|
183
|
-
expect(exit_code).to eq 0
|
|
184
|
-
expect(stderr).to eq ''
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
it 'fails to get secrets from a missing Thycotic Secret Server' do
|
|
189
|
-
with_test_platform_for_deployer_options do
|
|
190
|
-
mock_thycotic_file_download_on('https://my_thycotic.domain.com/SecretServer', '1107', nil)
|
|
191
|
-
expect do
|
|
192
|
-
run 'deploy', '--node', 'node', '--secrets', 'https://my_thycotic.domain.com/SecretServer:1107'
|
|
193
|
-
end.to raise_error 'Unable to fetch secret file ID https://my_thycotic.domain.com/SecretServer:1107'
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
15
|
it 'uses parallel mode' do
|
|
198
16
|
with_test_platform_for_deployer_options do |repository|
|
|
199
17
|
expect(test_deployer).to receive(:deploy_on).with(['node']) do
|