hybrid_platforms_conductor 32.13.4 → 32.16.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +60 -0
  3. data/bin/get_impacted_nodes +1 -1
  4. data/bin/setup +6 -1
  5. data/docs/plugins.md +1 -0
  6. data/docs/plugins/platform_handler/serverless_chef.md +111 -0
  7. data/lib/hybrid_platforms_conductor/cmd_runner.rb +13 -1
  8. data/lib/hybrid_platforms_conductor/connector.rb +4 -2
  9. data/lib/hybrid_platforms_conductor/deployer.rb +2 -1
  10. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +1 -1
  11. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +535 -0
  12. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +51 -0
  13. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +232 -0
  14. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/podman.rb +1 -1
  15. data/lib/hybrid_platforms_conductor/nodes_handler.rb +9 -5
  16. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  17. data/spec/hybrid_platforms_conductor_test.rb +3 -0
  18. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +7 -0
  19. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +23 -0
  20. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +11 -0
  21. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb +17 -0
  22. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/deploy_output_parsing_spec.rb +94 -0
  23. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +317 -0
  24. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/inventory_spec.rb +65 -0
  25. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/packaging_spec.rb +293 -0
  26. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +272 -0
  27. data/spec/hybrid_platforms_conductor_test/helpers/cmd_runner_helpers.rb +1 -1
  28. data/spec/hybrid_platforms_conductor_test/helpers/serverless_chef_helpers.rb +53 -0
  29. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/chef_versions.yml +3 -0
  30. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json +14 -0
  31. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/policyfiles/test_policy.rb +3 -0
  32. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/chef_versions.yml +3 -0
  33. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/data_bags/my_bag/my_item.json +4 -0
  34. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/nodes/node.json +14 -0
  35. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/policyfiles/test_policy.rb +3 -0
  36. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/chef_versions.yml +3 -0
  37. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/cookbooks/hpc_test/recipes/after_run.rb +1 -0
  38. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/cookbooks/hpc_test/recipes/before_run.rb +1 -0
  39. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/nodes/node.json +10 -0
  40. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/hpc_test/policyfiles/test_policy.rb +3 -0
  41. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
  42. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/libraries/default.rb +4 -0
  43. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/default.rb +1 -0
  44. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
  45. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
  46. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node1.json +10 -0
  47. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node2.json +10 -0
  48. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_1.rb +4 -0
  49. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_2.rb +4 -0
  50. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/config.rb +1 -0
  51. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
  52. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node1.json +10 -0
  53. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node2.json +10 -0
  54. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/libraries/default.rb +4 -0
  55. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/default.rb +1 -0
  56. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
  57. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
  58. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_1.rb +4 -0
  59. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_2.rb +4 -0
  60. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/chef_versions.yml +3 -0
  61. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/local.json +10 -0
  62. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node1.json +10 -0
  63. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node2.json +10 -0
  64. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_1.rb +3 -0
  65. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_2.rb +3 -0
  66. metadata +192 -143
@@ -0,0 +1,317 @@
1
+ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef do
2
+
3
+ context 'checking files diff impacts' do
4
+
5
+ it 'returns no impact for no diffs' do
6
+ with_serverless_chef_platforms('recipes') do |platform, repository|
7
+ expect(platform.impacts_from({})).to eq [
8
+ [],
9
+ [],
10
+ false
11
+ ]
12
+ end
13
+ end
14
+
15
+ it 'ignores files with no impact' do
16
+ with_serverless_chef_platforms('recipes') do |platform, repository|
17
+ expect(platform.impacts_from(
18
+ 'cookbooks/test_cookbook_1/README.md' => {}
19
+ )).to eq [
20
+ [],
21
+ [],
22
+ false
23
+ ]
24
+ end
25
+ end
26
+
27
+ it 'returns all nodes impact for global files' do
28
+ with_serverless_chef_platforms('recipes') do |platform, repository|
29
+ expect(platform.impacts_from(
30
+ 'global.rb' => {}
31
+ )).to eq [
32
+ [],
33
+ [],
34
+ true
35
+ ]
36
+ end
37
+ end
38
+
39
+ it 'returns direct impacted nodes' do
40
+ with_serverless_chef_platforms('recipes') do |platform, repository|
41
+ expect(platform.impacts_from(
42
+ 'nodes/node1.json' => {}
43
+ )).to eq [
44
+ %w[node1],
45
+ [],
46
+ false
47
+ ]
48
+ end
49
+ end
50
+
51
+ it 'returns direct impacted nodes with strange characters' do
52
+ with_serverless_chef_platforms('recipes') do |platform, repository|
53
+ expect(platform.impacts_from(
54
+ 'nodes/node-v45.env_@user.json' => {}
55
+ )).to eq [
56
+ ['node-v45.env_@user'],
57
+ [],
58
+ false
59
+ ]
60
+ end
61
+ end
62
+
63
+ it 'returns impacted service due to a change in its recipes' do
64
+ with_serverless_chef_platforms('recipes') do |platform, repository|
65
+ expect(platform.impacts_from(
66
+ 'cookbooks/test_cookbook_1/recipes/default.rb' => {}
67
+ )).to eq [
68
+ [],
69
+ %w[test_policy_1],
70
+ false
71
+ ]
72
+ end
73
+ end
74
+
75
+ it 'returns impacted service due to a change in its attributes' do
76
+ with_serverless_chef_platforms('recipes') do |platform, repository|
77
+ expect(platform.impacts_from(
78
+ 'cookbooks/test_cookbook_1/attributes/default.rb' => {}
79
+ )).to eq [
80
+ [],
81
+ %w[test_policy_1],
82
+ false
83
+ ]
84
+ end
85
+ end
86
+
87
+ it 'returns impacted service due to a change in an included template' do
88
+ with_serverless_chef_platforms('recipes') do |platform, repository|
89
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
90
+ template '/home/file' do
91
+ source 'test_template.erb'
92
+ end
93
+ EOS
94
+ expect(platform.impacts_from(
95
+ 'cookbooks/test_cookbook_1/templates/default/test_template.erb' => {}
96
+ )).to eq [
97
+ [],
98
+ %w[test_policy_1],
99
+ false
100
+ ]
101
+ end
102
+ end
103
+
104
+ it 'does not return impacted service due to a change in a non included template' do
105
+ with_serverless_chef_platforms('recipes') do |platform, repository|
106
+ expect(platform.impacts_from(
107
+ 'cookbooks/test_cookbook_1/templates/default/test_template.erb' => {}
108
+ )).to eq [
109
+ [],
110
+ [],
111
+ false
112
+ ]
113
+ end
114
+ end
115
+
116
+ it 'returns impacted service due to a change in an included file' do
117
+ with_serverless_chef_platforms('recipes') do |platform, repository|
118
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
119
+ file '/home/file' do
120
+ source 'test_file'
121
+ end
122
+ EOS
123
+ expect(platform.impacts_from(
124
+ 'cookbooks/test_cookbook_1/files/default/test_file' => {}
125
+ )).to eq [
126
+ [],
127
+ %w[test_policy_1],
128
+ false
129
+ ]
130
+ end
131
+ end
132
+
133
+ it 'does not return impacted service due to a change in a non included file' do
134
+ with_serverless_chef_platforms('recipes') do |platform, repository|
135
+ expect(platform.impacts_from(
136
+ 'cookbooks/test_cookbook_1/files/default/test_file' => {}
137
+ )).to eq [
138
+ [],
139
+ [],
140
+ false
141
+ ]
142
+ end
143
+ end
144
+
145
+ it 'returns impacted service due to a resource usage in a recipe' do
146
+ with_serverless_chef_platforms('recipes') do |platform, repository|
147
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
148
+ test_cookbook_2_my_resource
149
+ EOS
150
+ expect(platform.impacts_from(
151
+ 'cookbooks/test_cookbook_2/resources/my_resource.rb' => {}
152
+ )).to eq [
153
+ [],
154
+ %w[test_policy_1],
155
+ false
156
+ ]
157
+ end
158
+ end
159
+
160
+ it 'does not return impacted service due to a resource not being used in a recipe' do
161
+ with_serverless_chef_platforms('recipes') do |platform, repository|
162
+ expect(platform.impacts_from(
163
+ 'cookbooks/test_cookbook_2/resources/my_resource.rb' => {}
164
+ )).to eq [
165
+ [],
166
+ [],
167
+ false
168
+ ]
169
+ end
170
+ end
171
+
172
+ it 'returns impacted service due to a library helper usage in a recipe' do
173
+ with_serverless_chef_platforms('recipes') do |platform, repository|
174
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
175
+ a = my_library_helper(42)
176
+ EOS
177
+ expect(platform.impacts_from(
178
+ 'cookbooks/test_cookbook_2/libraries/default.rb' => {}
179
+ )).to eq [
180
+ [],
181
+ %w[test_policy_1],
182
+ false
183
+ ]
184
+ end
185
+ end
186
+
187
+ it 'ignored impacted service from an unknown helper' do
188
+ with_serverless_chef_platforms('recipes') do |platform, repository|
189
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
190
+ a = unknown_helper(42)
191
+ EOS
192
+ expect(platform.impacts_from(
193
+ 'cookbooks/test_cookbook_2/recipes/default.rb' => {}
194
+ )).to eq [
195
+ [],
196
+ %w[test_policy_2],
197
+ false
198
+ ]
199
+ end
200
+ end
201
+
202
+ it 'returns impacted service due to an unknown library helper usage that has been configured' do
203
+ with_serverless_chef_platforms(
204
+ 'recipes',
205
+ additional_config: <<~EOS
206
+ helpers_including_recipes(unknown_helper: ['test_cookbook_2'])
207
+ EOS
208
+ ) do |platform, repository|
209
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
210
+ a = unknown_helper(42)
211
+ EOS
212
+ expect(platform.impacts_from(
213
+ 'cookbooks/test_cookbook_2/recipes/default.rb' => {}
214
+ )).to eq [
215
+ [],
216
+ %w[test_policy_1 test_policy_2],
217
+ false
218
+ ]
219
+ end
220
+ end
221
+
222
+ it 'does not return impacted service due to a library helper not being used in a recipe' do
223
+ with_serverless_chef_platforms('recipes') do |platform, repository|
224
+ expect(platform.impacts_from(
225
+ 'cookbooks/test_cookbook_2/libraries/default.rb' => {}
226
+ )).to eq [
227
+ [],
228
+ [],
229
+ false
230
+ ]
231
+ end
232
+ end
233
+
234
+ it 'returns impacted service due to a usage of another cookbook\'s default recipe' do
235
+ with_serverless_chef_platforms('recipes') do |platform, repository|
236
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
237
+ include_recipe 'test_cookbook_2'
238
+ EOS
239
+ expect(platform.impacts_from(
240
+ 'cookbooks/test_cookbook_2/recipes/default.rb' => {}
241
+ )).to eq [
242
+ [],
243
+ %w[test_policy_1 test_policy_2],
244
+ false
245
+ ]
246
+ end
247
+ end
248
+
249
+ it 'returns impacted service due to a usage of another cookbook\'s recipe' do
250
+ with_serverless_chef_platforms('recipes') do |platform, repository|
251
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
252
+ include_recipe 'test_cookbook_2::other_recipe'
253
+ EOS
254
+ expect(platform.impacts_from(
255
+ 'cookbooks/test_cookbook_2/recipes/other_recipe.rb' => {}
256
+ )).to eq [
257
+ [],
258
+ %w[test_policy_1],
259
+ false
260
+ ]
261
+ end
262
+ end
263
+
264
+ it 'ignores cookbooks from cookbook paths that are not configured' do
265
+ with_serverless_chef_platforms('several_cookbooks') do |platform, repository|
266
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
267
+ include_recipe 'test_cookbook_2'
268
+ EOS
269
+ expect(platform.impacts_from(
270
+ 'other_cookbooks/test_cookbook_2/recipes/default.rb' => {}
271
+ )).to eq [
272
+ [],
273
+ %w[],
274
+ true
275
+ ]
276
+ end
277
+ end
278
+
279
+ it 'considers cookbooks from non-standard cookbook paths that are configured' do
280
+ with_serverless_chef_platforms('several_cookbooks') do |platform, repository|
281
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
282
+ include_recipe 'test_cookbook_2'
283
+ EOS
284
+ ENV['hpc_test_cookbooks_path'] = 'other_cookbooks'
285
+ expect(platform.impacts_from(
286
+ 'other_cookbooks/test_cookbook_2/recipes/default.rb' => {}
287
+ )).to eq [
288
+ [],
289
+ %w[test_policy_1 test_policy_2],
290
+ false
291
+ ]
292
+ end
293
+ end
294
+
295
+ it 'ignores cookbooks from cookbook paths that are configured but lie outside the platform' do
296
+ with_repository('other_cookbooks') do |other_repo|
297
+ FileUtils.mkdir_p("#{other_repo}/cookbooks/test_cookbook_2/recipes")
298
+ File.write("#{other_repo}/cookbooks/test_cookbook_2/recipes/default.rb", '')
299
+ with_serverless_chef_platforms('several_cookbooks') do |platform, repository|
300
+ File.write("#{repository}/cookbooks/test_cookbook_1/recipes/default.rb", <<~EOS)
301
+ include_recipe 'test_cookbook_2'
302
+ EOS
303
+ ENV['hpc_test_cookbooks_path'] = "#{other_repo}:other_cookbooks"
304
+ expect(platform.impacts_from(
305
+ 'unknown_cookbooks/test_cookbook_2/recipes/default.rb' => {}
306
+ )).to eq [
307
+ [],
308
+ %w[],
309
+ true
310
+ ]
311
+ end
312
+ end
313
+ end
314
+
315
+ end
316
+
317
+ end
@@ -0,0 +1,65 @@
1
+ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef do
2
+
3
+ context 'checking inventory' do
4
+
5
+ context 'with an empty platform' do
6
+
7
+ it 'returns no node' do
8
+ with_serverless_chef_platforms('empty') do |platform|
9
+ expect(platform.known_nodes).to eq []
10
+ end
11
+ end
12
+
13
+ it 'returns no nodes list' do
14
+ with_serverless_chef_platforms('empty') do |platform|
15
+ expect(platform.respond_to?(:known_nodes_lists)).to eq false
16
+ end
17
+ end
18
+
19
+ it 'returns no deployable services' do
20
+ with_serverless_chef_platforms('empty') do |platform|
21
+ expect(platform.deployable_services).to eq []
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ context 'with a platform having 1 node' do
28
+
29
+ it 'returns the node' do
30
+ with_serverless_chef_platforms('1_node') do |platform|
31
+ expect(platform.known_nodes).to eq ['node']
32
+ end
33
+ end
34
+
35
+ it 'returns correct metadata for this node' do
36
+ with_serverless_chef_platforms('1_node') do |platform|
37
+ expect(platform.metadata_for('node')).to eq(
38
+ description: 'Single test node',
39
+ image: 'debian_9',
40
+ private_ips: ['172.16.0.1'],
41
+ property1: {
42
+ 'property11' => 'value11'
43
+ },
44
+ property2: 'value2'
45
+ )
46
+ end
47
+ end
48
+
49
+ it 'returns correct service for this node' do
50
+ with_serverless_chef_platforms('1_node') do |platform|
51
+ expect(platform.services_for('node')).to eq %w[test_policy]
52
+ end
53
+ end
54
+
55
+ it 'returns deployable services' do
56
+ with_serverless_chef_platforms('1_node') do |platform|
57
+ expect(platform.deployable_services).to eq %w[test_policy]
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,293 @@
1
+ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef do
2
+
3
+ context 'checking services packaging' do
4
+
5
+ # Expect a repository to be packaged and mock it
6
+ #
7
+ # Parameters::
8
+ # * *repository* (String): Repository to be packaged
9
+ # * *policy* (String): Expected policy to be packaged [default: 'test_policy']
10
+ # * *policy_file* (String): Expected policy file used [default: "policyfiles/#{policy}.rb"]
11
+ # * *install* (Boolean): Are we expecting the chef install stage? [default: true]
12
+ # * *export* (Boolean): Are we expecting the chef export stage? [default: true]
13
+ # * *data_bags* (Boolean): Do we expect data bags copy? [default: false]
14
+ # * *env* (String): Expected environment being packaged [default: 'prod']
15
+ # * Proc: Code called with mock in place
16
+ def with_packaging_mocked(
17
+ repository,
18
+ policy: 'test_policy',
19
+ policy_file: "policyfiles/#{policy}.rb",
20
+ install: true,
21
+ export: true,
22
+ data_bags: false,
23
+ env: 'prod'
24
+ )
25
+ with_cmd_runner_mocked(
26
+ if install
27
+ [
28
+ [
29
+ "cd #{repository} && /opt/chef-workstation/bin/chef install #{policy_file}",
30
+ proc do
31
+ # Mock the run_list stored in the lock file
32
+ File.write(
33
+ "#{repository}/#{policy_file.gsub(/.rb$/, '.lock.json')}",
34
+ {
35
+ run_list: eval("[#{File.read("#{repository}/#{policy_file}").split("\n").select { |line| line =~ /^run_list.+$/ }.last.match(/^run_list(.+)$/)[1]}]").flatten
36
+ }.to_json
37
+ )
38
+ [0, 'Chef install done', '']
39
+ end
40
+ ]
41
+ ]
42
+ else
43
+ []
44
+ end +
45
+ if export
46
+ [
47
+ ['whoami', proc { [0, 'test_user', ''] }, { optional: true }],
48
+ [
49
+ /^cd #{Regexp.escape(repository)} &&\s+sudo rm -rf dist\/#{Regexp.escape(env)}\/#{Regexp.escape(policy)} &&\s+\/opt\/chef-workstation\/bin\/chef export #{Regexp.escape(policy_file)} dist\/#{Regexp.escape(env)}\/#{Regexp.escape(policy)}#{data_bags ? " && cp -ar data_bags/ dist/#{Regexp.escape(env)}/#{Regexp.escape(policy)}/" : ''}$/,
50
+ proc do
51
+ FileUtils.mkdir_p "#{repository}/dist/#{env}/#{policy}"
52
+ FileUtils.cp_r("#{repository}/data_bags", "#{repository}/dist/#{env}/#{policy}/") if data_bags
53
+ [0, 'Chef export done', '']
54
+ end
55
+ ]
56
+ ]
57
+ else
58
+ []
59
+ end
60
+ ) do
61
+ yield
62
+ end
63
+ end
64
+
65
+ context 'with an empty platform' do
66
+
67
+ it 'packages the repository doing nothing' do
68
+ with_serverless_chef_platforms('empty') do |platform, repository|
69
+ with_cmd_runner_mocked([]) do
70
+ platform.package(services: {}, secrets: {}, local_environment: false)
71
+ end
72
+ end
73
+ end
74
+
75
+ end
76
+
77
+ context 'with a platform having 1 node' do
78
+
79
+ it 'packages the repository for a given node and service' do
80
+ with_serverless_chef_platforms('1_node') do |platform, repository|
81
+ with_packaging_mocked(repository) do
82
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
83
+ end
84
+ end
85
+ end
86
+
87
+ it 'packages the repository without resolving dependencies when the lock file already exists' do
88
+ with_serverless_chef_platforms('1_node') do |platform, repository|
89
+ File.write("#{repository}/policyfiles/test_policy.lock.json", '{}')
90
+ with_packaging_mocked(repository, install: false) do
91
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
92
+ end
93
+ end
94
+ end
95
+
96
+ it 'packages the repository with secrets' do
97
+ with_serverless_chef_platforms('1_node') do |platform, repository|
98
+ with_packaging_mocked(repository) do
99
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: { secret: 'value' }, local_environment: false)
100
+ secret_file = "#{repository}/dist/prod/test_policy/data_bags/hpc_secrets/hpc_secrets.json"
101
+ expect(File.exist?(secret_file)).to eq true
102
+ expect(JSON.parse(File.read(secret_file))).to eq(
103
+ 'id' => 'hpc_secrets',
104
+ 'secret' => 'value'
105
+ )
106
+ end
107
+ end
108
+ end
109
+
110
+ it 'packages the repository for a given node and service in local mode' do
111
+ with_serverless_chef_platforms('1_node') do |platform, repository|
112
+ with_packaging_mocked(repository, policy_file: 'policyfiles/test_policy.local.rb', env: 'local') do
113
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: true)
114
+ local_policy_file = "#{repository}/policyfiles/test_policy.local.lock.json"
115
+ expect(File.exist?(local_policy_file)).to eq true
116
+ expect(JSON.parse(File.read(local_policy_file))).to eq('run_list' => ['recipe[test_cookbook]'])
117
+ end
118
+ end
119
+ end
120
+
121
+ it 'packages the repository without resolving dependencies when the lock file already exists' do
122
+ with_serverless_chef_platforms('1_node') do |platform, repository|
123
+ File.write("#{repository}/policyfiles/test_policy.lock.json", '{}')
124
+ with_packaging_mocked(repository, install: false) do
125
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
126
+ end
127
+ end
128
+ end
129
+
130
+ it 'does not package the repository twice for the same config' do
131
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
132
+ with_packaging_mocked(repository) do
133
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
134
+ end
135
+ with_cmd_runner_mocked([]) do
136
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
137
+ end
138
+ end
139
+ end
140
+
141
+ it 'packages the repository twice when the platform is not taken from git' do
142
+ with_serverless_chef_platforms('1_node') do |platform, repository|
143
+ with_packaging_mocked(repository) do
144
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
145
+ end
146
+ # Wait 2 seconds so that we are sure later Time.now will return different timestamps
147
+ sleep 2
148
+ with_packaging_mocked(repository, install: false) do
149
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
150
+ end
151
+ end
152
+ end
153
+
154
+ it 'packages the repository twice when the platform needs different secrets' do
155
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
156
+ with_packaging_mocked(repository) do
157
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: { secret: 'value1' }, local_environment: false)
158
+ end
159
+ with_packaging_mocked(repository, install: false) do
160
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: { secret: 'value2' }, local_environment: false)
161
+ end
162
+ end
163
+ end
164
+
165
+ it 'packages the repository twice when the platform has new local files' do
166
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
167
+ with_packaging_mocked(repository) do
168
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
169
+ end
170
+ # Make sure we clean the cache (this mocks another Platform Handler instance running)
171
+ platform.remove_instance_variable :@info
172
+ with_packaging_mocked(repository, install: false) do
173
+ File.write("#{repository}/new_file", 'New file')
174
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
175
+ end
176
+ end
177
+ end
178
+
179
+ it 'packages the repository twice when the platform has modified local files' do
180
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
181
+ with_packaging_mocked(repository) do
182
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
183
+ end
184
+ # Wait 2 seconds so that we are sure the modified file will return a different timestamp
185
+ sleep 2
186
+ with_packaging_mocked(repository, install: false) do
187
+ File.write("#{repository}/chef_versions.yml", File.read("#{repository}/chef_versions.yml") + "\n\n")
188
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
189
+ end
190
+ end
191
+ end
192
+
193
+ end
194
+
195
+ context 'with a platform having several nodes' do
196
+
197
+ it 'packages 1 service independently from another' do
198
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
199
+ with_packaging_mocked(repository, policy: 'test_policy_1') do
200
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
201
+ end
202
+ with_packaging_mocked(repository, policy: 'test_policy_2') do
203
+ platform.package(services: { 'node2' => %w[test_policy_2] }, secrets: {}, local_environment: false)
204
+ end
205
+ with_cmd_runner_mocked([]) do
206
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
207
+ end
208
+ end
209
+ end
210
+
211
+ it 'packages 1 service independently of the node on which it is to be deployed' do
212
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
213
+ with_packaging_mocked(repository, policy: 'test_policy_1') do
214
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
215
+ end
216
+ with_cmd_runner_mocked([]) do
217
+ platform.package(services: { 'node2' => %w[test_policy_1] }, secrets: {}, local_environment: false)
218
+ end
219
+ end
220
+ end
221
+
222
+ end
223
+
224
+ context 'with a platform having data bags' do
225
+
226
+ it 'packages data bags' do
227
+ with_serverless_chef_platforms('data_bags') do |platform, repository|
228
+ with_packaging_mocked(repository, data_bags: true) do
229
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
230
+ data_bag_file = "#{repository}/dist/prod/test_policy/data_bags/my_bag/my_item.json"
231
+ expect(File.exist?(data_bag_file)).to eq true
232
+ expect(JSON.parse(File.read(data_bag_file))).to eq(
233
+ 'id' => 'my_item',
234
+ 'content' => 'Bag content'
235
+ )
236
+ end
237
+ end
238
+ end
239
+
240
+ end
241
+
242
+ context 'with a platform having hpc_test cookbook' do
243
+
244
+ it 'packages the repository with before_run and after_run recipes wrapping the run list' do
245
+ with_serverless_chef_platforms('hpc_test') do |platform, repository|
246
+ with_packaging_mocked(repository, policy_file: 'policyfiles/test_policy.local.rb', env: 'local') do
247
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: true)
248
+ local_policy_file = "#{repository}/policyfiles/test_policy.local.lock.json"
249
+ expect(File.exist?(local_policy_file)).to eq true
250
+ expect(JSON.parse(File.read(local_policy_file))).to eq('run_list' => [
251
+ 'hpc_test::before_run',
252
+ 'recipe[test_cookbook]',
253
+ 'hpc_test::after_run'
254
+ ])
255
+ end
256
+ end
257
+ end
258
+
259
+ it 'packages the repository with before_run only recipe' do
260
+ with_serverless_chef_platforms('hpc_test') do |platform, repository|
261
+ File.unlink "#{repository}/cookbooks/hpc_test/recipes/after_run.rb"
262
+ with_packaging_mocked(repository, policy_file: 'policyfiles/test_policy.local.rb', env: 'local') do
263
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: true)
264
+ local_policy_file = "#{repository}/policyfiles/test_policy.local.lock.json"
265
+ expect(File.exist?(local_policy_file)).to eq true
266
+ expect(JSON.parse(File.read(local_policy_file))).to eq('run_list' => [
267
+ 'hpc_test::before_run',
268
+ 'recipe[test_cookbook]'
269
+ ])
270
+ end
271
+ end
272
+ end
273
+
274
+ it 'packages the repository with after_run only recipe' do
275
+ with_serverless_chef_platforms('hpc_test') do |platform, repository|
276
+ File.unlink "#{repository}/cookbooks/hpc_test/recipes/before_run.rb"
277
+ with_packaging_mocked(repository, policy_file: 'policyfiles/test_policy.local.rb', env: 'local') do
278
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: true)
279
+ local_policy_file = "#{repository}/policyfiles/test_policy.local.lock.json"
280
+ expect(File.exist?(local_policy_file)).to eq true
281
+ expect(JSON.parse(File.read(local_policy_file))).to eq('run_list' => [
282
+ 'recipe[test_cookbook]',
283
+ 'hpc_test::after_run'
284
+ ])
285
+ end
286
+ end
287
+ end
288
+
289
+ end
290
+
291
+ end
292
+
293
+ end