hybrid_platforms_conductor 32.13.0 → 32.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +10 -3
  4. data/bin/get_impacted_nodes +1 -1
  5. data/bin/setup +6 -1
  6. data/docs/executables/check-node.md +1 -1
  7. data/docs/executables/deploy.md +1 -1
  8. data/docs/executables/free_ips.md +1 -1
  9. data/docs/executables/free_veids.md +1 -1
  10. data/docs/executables/get_impacted_nodes.md +1 -1
  11. data/docs/executables/last_deploys.md +1 -1
  12. data/docs/executables/nodes_to_deploy.md +1 -1
  13. data/docs/executables/report.md +1 -1
  14. data/docs/executables/run.md +1 -1
  15. data/docs/executables/setup.md +1 -1
  16. data/docs/executables/ssh_config.md +1 -1
  17. data/docs/executables/test.md +1 -1
  18. data/docs/plugins.md +1 -0
  19. data/docs/plugins/platform_handler/serverless_chef.md +105 -0
  20. data/docs/tutorial.md +10 -6
  21. data/docs/tutorial/01_installation.md +14 -12
  22. data/docs/tutorial/02_first_node.md +14 -12
  23. data/docs/tutorial/03_scale.md +14 -12
  24. data/docs/tutorial/04_test.md +26 -14
  25. data/docs/tutorial/05_extend_with_plugins.md +17 -17
  26. data/examples/tutorial/01_installation/my-platforms/Gemfile +3 -0
  27. data/examples/tutorial/01_installation/my-platforms/hpc_config.rb +0 -0
  28. data/examples/tutorial/02_first_node/my-platforms/Gemfile +3 -0
  29. data/examples/tutorial/02_first_node/my-platforms/hpc_config.rb +1 -0
  30. data/examples/tutorial/02_first_node/my-service-conf-repo/inventory.yaml +13 -0
  31. data/examples/tutorial/02_first_node/my-service-conf-repo/my-service.conf.erb +3 -0
  32. data/examples/tutorial/02_first_node/my-service-conf-repo/service_my-service.rb +58 -0
  33. data/examples/tutorial/02_first_node/node/my-service.conf +4 -0
  34. data/examples/tutorial/03_scale/my-platforms/Gemfile +3 -0
  35. data/examples/tutorial/03_scale/my-platforms/hpc_config.rb +1 -0
  36. data/examples/tutorial/03_scale/my-platforms/my_commands.bash +2 -0
  37. data/examples/tutorial/03_scale/my-service-conf-repo/inventory.yaml +90 -0
  38. data/examples/tutorial/03_scale/my-service-conf-repo/my-service.conf.erb +3 -0
  39. data/examples/tutorial/03_scale/my-service-conf-repo/service_my-service.rb +58 -0
  40. data/examples/tutorial/03_scale/my-service-conf-repo/service_web-hello.rb +43 -0
  41. data/examples/tutorial/03_scale/node/my-service.conf +4 -0
  42. data/examples/tutorial/03_scale/web_docker_image/Dockerfile +33 -0
  43. data/examples/tutorial/03_scale/web_docker_image/hello_world.txt +1 -0
  44. data/examples/tutorial/03_scale/web_docker_image/hpc_root.key +27 -0
  45. data/examples/tutorial/03_scale/web_docker_image/hpc_root.key.pub +1 -0
  46. data/examples/tutorial/03_scale/web_docker_image/main.go +43 -0
  47. data/examples/tutorial/03_scale/web_docker_image/start.sh +7 -0
  48. data/examples/tutorial/03_scale/web_docker_image/test.bash +6 -0
  49. data/examples/tutorial/04_test/my-platforms/Gemfile +3 -0
  50. data/examples/tutorial/04_test/my-platforms/hpc_config.rb +12 -0
  51. data/examples/tutorial/04_test/my-platforms/images/debian_10/Dockerfile +13 -0
  52. data/examples/tutorial/04_test/my-platforms/my_commands.bash +2 -0
  53. data/examples/tutorial/04_test/my-service-conf-repo/inventory.yaml +100 -0
  54. data/examples/tutorial/04_test/my-service-conf-repo/my-service.conf.erb +3 -0
  55. data/examples/tutorial/04_test/my-service-conf-repo/service_my-service.rb +58 -0
  56. data/examples/tutorial/04_test/my-service-conf-repo/service_web-hello.rb +43 -0
  57. data/examples/tutorial/04_test/node/my-service.conf +4 -0
  58. data/examples/tutorial/04_test/web_docker_image/Dockerfile +33 -0
  59. data/examples/tutorial/04_test/web_docker_image/hello_world.txt +1 -0
  60. data/examples/tutorial/04_test/web_docker_image/hpc_root.key +27 -0
  61. data/examples/tutorial/04_test/web_docker_image/hpc_root.key.pub +1 -0
  62. data/examples/tutorial/04_test/web_docker_image/main.go +43 -0
  63. data/examples/tutorial/04_test/web_docker_image/start.sh +7 -0
  64. data/examples/tutorial/04_test/web_docker_image/test.bash +6 -0
  65. data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/hosts.json +12 -0
  66. data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-gcc.bash +14 -0
  67. data/examples/tutorial/05_extend_with_plugins/dev-servers-conf-repo/install-python.bash +14 -0
  68. data/examples/tutorial/05_extend_with_plugins/dev_docker_image/Dockerfile +20 -0
  69. data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key +27 -0
  70. data/examples/tutorial/05_extend_with_plugins/dev_docker_image/hpc_root.key.pub +1 -0
  71. data/examples/tutorial/05_extend_with_plugins/my-platforms/Gemfile +4 -0
  72. data/examples/tutorial/05_extend_with_plugins/my-platforms/hpc_config.rb +13 -0
  73. data/examples/tutorial/05_extend_with_plugins/my-platforms/images/debian_10/Dockerfile +13 -0
  74. data/examples/tutorial/05_extend_with_plugins/my-platforms/my_commands.bash +2 -0
  75. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/inventory.yaml +100 -0
  76. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/my-service.conf.erb +3 -0
  77. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_my-service.rb +58 -0
  78. data/examples/tutorial/05_extend_with_plugins/my-service-conf-repo/service_web-hello.rb +43 -0
  79. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/platform_handler/json_bash.rb +115 -0
  80. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/report/web_report.rb +52 -0
  81. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/lib/my_hpc_plugins/hpc_plugins/test/root_space.rb +44 -0
  82. data/examples/tutorial/05_extend_with_plugins/my_hpc_plugins/my_hpc_plugins.gemspec +15 -0
  83. data/examples/tutorial/05_extend_with_plugins/node/my-service.conf +4 -0
  84. data/examples/tutorial/05_extend_with_plugins/web_docker_image/Dockerfile +33 -0
  85. data/examples/tutorial/05_extend_with_plugins/web_docker_image/hello_world.txt +1 -0
  86. data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key +27 -0
  87. data/examples/tutorial/05_extend_with_plugins/web_docker_image/hpc_root.key.pub +1 -0
  88. data/examples/tutorial/05_extend_with_plugins/web_docker_image/main.go +43 -0
  89. data/examples/tutorial/05_extend_with_plugins/web_docker_image/start.sh +7 -0
  90. data/examples/tutorial/05_extend_with_plugins/web_docker_image/test.bash +6 -0
  91. data/lib/hybrid_platforms_conductor/deployer.rb +2 -1
  92. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +440 -0
  93. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/dsl_parser.rb +51 -0
  94. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef/recipes_tree_builder.rb +271 -0
  95. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -0
  96. data/lib/hybrid_platforms_conductor/nodes_handler.rb +9 -5
  97. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  98. data/spec/hybrid_platforms_conductor_test.rb +3 -0
  99. data/spec/hybrid_platforms_conductor_test/api/deployer/provisioner_spec.rb +23 -0
  100. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +11 -0
  101. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/config_dsl_spec.rb +17 -0
  102. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/deploy_output_parsing_spec.rb +94 -0
  103. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/diff_impacts_spec.rb +317 -0
  104. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/inventory_spec.rb +65 -0
  105. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/packaging_spec.rb +213 -0
  106. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +268 -0
  107. data/spec/hybrid_platforms_conductor_test/helpers/serverless_chef_helpers.rb +53 -0
  108. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/chef_versions.yml +3 -0
  109. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json +14 -0
  110. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/policyfiles/test_policy.rb +3 -0
  111. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/chef_versions.yml +3 -0
  112. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/data_bags/my_bag/my_item.json +4 -0
  113. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/nodes/node.json +14 -0
  114. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/data_bags/policyfiles/test_policy.rb +3 -0
  115. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
  116. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/libraries/default.rb +4 -0
  117. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/default.rb +1 -0
  118. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
  119. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
  120. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node1.json +10 -0
  121. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/nodes/node2.json +10 -0
  122. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_1.rb +4 -0
  123. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/recipes/policyfiles/test_policy_2.rb +4 -0
  124. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/config.rb +1 -0
  125. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/cookbooks/test_cookbook_1/recipes/default.rb +1 -0
  126. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node1.json +10 -0
  127. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/nodes/node2.json +10 -0
  128. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/libraries/default.rb +4 -0
  129. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/default.rb +1 -0
  130. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/recipes/other_recipe.rb +1 -0
  131. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/other_cookbooks/test_cookbook_2/resources/my_resource.rb +1 -0
  132. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_1.rb +4 -0
  133. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_cookbooks/policyfiles/test_policy_2.rb +4 -0
  134. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/chef_versions.yml +3 -0
  135. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/local.json +10 -0
  136. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node1.json +10 -0
  137. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/nodes/node2.json +10 -0
  138. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_1.rb +3 -0
  139. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/several_nodes/policyfiles/test_policy_2.rb +3 -0
  140. data/tools/generate_mermaid +1 -1
  141. metadata +260 -86
@@ -0,0 +1,213 @@
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
+ # * *install* (Boolean): Are we expecting the chef install stage? [default: true]
11
+ # * *export* (Boolean): Are we expecting the chef export stage? [default: true]
12
+ # * *data_bags* (Boolean): Do we expect data bags copy? [default: false]
13
+ # * Proc: Code called with mock in place
14
+ def with_packaging_mocked(
15
+ repository,
16
+ policy: 'test_policy',
17
+ install: true,
18
+ export: true,
19
+ data_bags: false
20
+ )
21
+ with_cmd_runner_mocked(
22
+ if install
23
+ [
24
+ [
25
+ "cd #{repository} && /opt/chef-workstation/bin/chef install policyfiles/#{policy}.rb",
26
+ proc do
27
+ File.write("#{repository}/policyfiles/#{policy}.lock.json", '{}')
28
+ [0, 'Chef install done', '']
29
+ end
30
+ ]
31
+ ]
32
+ else
33
+ []
34
+ end +
35
+ if export
36
+ [
37
+ [
38
+ /^cd #{Regexp.escape(repository)} &&\s+sudo rm -rf dist\/prod\/#{Regexp.escape(policy)} &&\s+\/opt\/chef-workstation\/bin\/chef export policyfiles\/#{Regexp.escape(policy)}.rb dist\/prod\/#{Regexp.escape(policy)}#{data_bags ? " && cp -ar data_bags/ dist/prod/#{Regexp.escape(policy)}/" : ''}$/,
39
+ proc do
40
+ FileUtils.mkdir_p "#{repository}/dist/prod/#{policy}"
41
+ FileUtils.cp_r("#{repository}/data_bags", "#{repository}/dist/prod/#{policy}/") if data_bags
42
+ [0, 'Chef export done', '']
43
+ end
44
+ ]
45
+ ]
46
+ else
47
+ []
48
+ end
49
+ ) do
50
+ yield
51
+ end
52
+ end
53
+
54
+ context 'with an empty platform' do
55
+
56
+ it 'packages the repository doing nothing' do
57
+ with_serverless_chef_platforms('empty') do |platform, repository|
58
+ with_cmd_runner_mocked([]) do
59
+ platform.package(services: {}, secrets: {}, local_environment: false)
60
+ end
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ context 'with a platform having 1 node' do
67
+
68
+ it 'packages the repository for a given node and service' do
69
+ with_serverless_chef_platforms('1_node') do |platform, repository|
70
+ with_packaging_mocked(repository) do
71
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
72
+ end
73
+ end
74
+ end
75
+
76
+ it 'packages the repository without resolving dependencies when the lock file already exists' do
77
+ with_serverless_chef_platforms('1_node') do |platform, repository|
78
+ File.write("#{repository}/policyfiles/test_policy.lock.json", '{}')
79
+ with_packaging_mocked(repository, install: false) do
80
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
81
+ end
82
+ end
83
+ end
84
+
85
+ it 'packages the repository with secrets' do
86
+ with_serverless_chef_platforms('1_node') do |platform, repository|
87
+ with_packaging_mocked(repository) do
88
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: { secret: 'value' }, local_environment: false)
89
+ secret_file = "#{repository}/dist/prod/test_policy/data_bags/hpc_secrets/hpc_secrets.json"
90
+ expect(File.exist?(secret_file)).to eq true
91
+ expect(JSON.parse(File.read(secret_file))).to eq(
92
+ 'id' => 'hpc_secrets',
93
+ 'secret' => 'value'
94
+ )
95
+ end
96
+ end
97
+ end
98
+
99
+ it 'does not package the repository twice for the same config' do
100
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
101
+ with_packaging_mocked(repository) do
102
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
103
+ end
104
+ with_cmd_runner_mocked([]) do
105
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
106
+ end
107
+ end
108
+ end
109
+
110
+ it 'packages the repository twice when the platform is not taken from git' do
111
+ with_serverless_chef_platforms('1_node') do |platform, repository|
112
+ with_packaging_mocked(repository) do
113
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
114
+ end
115
+ # Wait 2 seconds so that we are sure later Time.now will return different timestamps
116
+ sleep 2
117
+ with_packaging_mocked(repository, install: false) do
118
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
119
+ end
120
+ end
121
+ end
122
+
123
+ it 'packages the repository twice when the platform needs different secrets' do
124
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
125
+ with_packaging_mocked(repository) do
126
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: { secret: 'value1' }, local_environment: false)
127
+ end
128
+ with_packaging_mocked(repository, install: false) do
129
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: { secret: 'value2' }, local_environment: false)
130
+ end
131
+ end
132
+ end
133
+
134
+ it 'packages the repository twice when the platform has new local files' do
135
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
136
+ with_packaging_mocked(repository) do
137
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
138
+ end
139
+ # Make sure we clean the cache (this mocks another Platform Handler instance running)
140
+ platform.remove_instance_variable :@info
141
+ with_packaging_mocked(repository, install: false) do
142
+ File.write("#{repository}/new_file", 'New file')
143
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
144
+ end
145
+ end
146
+ end
147
+
148
+ it 'packages the repository twice when the platform has modified local files' do
149
+ with_serverless_chef_platforms('1_node', as_git: true) do |platform, repository|
150
+ with_packaging_mocked(repository) do
151
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
152
+ end
153
+ # Wait 2 seconds so that we are sure the modified file will return a different timestamp
154
+ sleep 2
155
+ with_packaging_mocked(repository, install: false) do
156
+ File.write("#{repository}/chef_versions.yml", File.read("#{repository}/chef_versions.yml") + "\n\n")
157
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
158
+ end
159
+ end
160
+ end
161
+
162
+ end
163
+
164
+ context 'with a platform having several nodes' do
165
+
166
+ it 'packages 1 service independently from another' do
167
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
168
+ with_packaging_mocked(repository, policy: 'test_policy_1') do
169
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
170
+ end
171
+ with_packaging_mocked(repository, policy: 'test_policy_2') do
172
+ platform.package(services: { 'node2' => %w[test_policy_2] }, secrets: {}, local_environment: false)
173
+ end
174
+ with_cmd_runner_mocked([]) do
175
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
176
+ end
177
+ end
178
+ end
179
+
180
+ it 'packages 1 service independently of the node on which it is to be deployed' do
181
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
182
+ with_packaging_mocked(repository, policy: 'test_policy_1') do
183
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
184
+ end
185
+ with_cmd_runner_mocked([]) do
186
+ platform.package(services: { 'node2' => %w[test_policy_1] }, secrets: {}, local_environment: false)
187
+ end
188
+ end
189
+ end
190
+
191
+ end
192
+
193
+ context 'with a platform having data bags' do
194
+
195
+ it 'packages data bags' do
196
+ with_serverless_chef_platforms('data_bags') do |platform, repository|
197
+ with_packaging_mocked(repository, data_bags: true) do
198
+ platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
199
+ data_bag_file = "#{repository}/dist/prod/test_policy/data_bags/my_bag/my_item.json"
200
+ expect(File.exist?(data_bag_file)).to eq true
201
+ expect(JSON.parse(File.read(data_bag_file))).to eq(
202
+ 'id' => 'my_item',
203
+ 'content' => 'Bag content'
204
+ )
205
+ end
206
+ end
207
+ end
208
+
209
+ end
210
+
211
+ end
212
+
213
+ end
@@ -0,0 +1,268 @@
1
+ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef do
2
+
3
+ context 'checking services deployment' do
4
+
5
+ # Simulate a packaging of a given repository
6
+ #
7
+ # Parameters::
8
+ # * *repository* (String): The repository we package
9
+ # * *service* (String): The service being packaged in this repository [default: 'test_policy']
10
+ def mock_package(repository, service: 'test_policy')
11
+ FileUtils.mkdir_p "#{repository}/dist/prod/#{service}"
12
+ end
13
+
14
+ # Get expected actions to deploy a service on a given node
15
+ #
16
+ # Parameters::
17
+ # * *repository* (String): Platform repository
18
+ # * *check_mode* (Boolean): Are we expected check-mode? [default: false]
19
+ # * *sudo* (String): sudo prefix command [default: 'sudo -u root ']
20
+ # * *env* (String): Environment expected to be packaged [default: 'prod']
21
+ # * *policy* (String): Expected policy to be packaged [default: 'test_policy']
22
+ # * *node* (String): Expected node to be deployed [default: 'node']
23
+ # Result::
24
+ # * Array: Expected actions
25
+ def expected_actions_to_deploy_chef(
26
+ repository,
27
+ check_mode: false,
28
+ sudo: 'sudo -u root ',
29
+ env: 'prod',
30
+ policy: 'test_policy',
31
+ node: 'node'
32
+ )
33
+ [
34
+ {
35
+ remote_bash: [
36
+ 'set -e',
37
+ 'set -o pipefail',
38
+ "if [ -n \"$(command -v apt)\" ]; then #{sudo}apt update && #{sudo}apt install -y curl build-essential ; else #{sudo}yum groupinstall 'Development Tools' && #{sudo}yum install -y curl ; fi",
39
+ 'mkdir -p ./hpc_deploy',
40
+ "curl --location https://omnitruck.chef.io/install.sh | tac | tac | #{sudo}bash -s -- -d /opt/artefacts -v 17.0 -s once"
41
+ ]
42
+ },
43
+ {
44
+ scp: { "#{repository}/dist/#{env}/#{policy}" => './hpc_deploy' },
45
+ remote_bash: [
46
+ 'set -e',
47
+ "cd ./hpc_deploy/#{policy}",
48
+ "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/bin/chef-client --local-mode --chef-license=accept --json-attributes nodes/#{node}.json#{check_mode ? ' --why-run' : ''}",
49
+ 'cd ..',
50
+ "#{sudo}rm -rf #{policy}"
51
+ ]
52
+ }
53
+ ]
54
+ end
55
+
56
+ context 'with an empty platform' do
57
+
58
+ it 'prepares for deploy' do
59
+ with_serverless_chef_platforms('empty') do |platform, repository|
60
+ platform.prepare_for_deploy(
61
+ services: {},
62
+ secrets: {},
63
+ local_environment: false,
64
+ why_run: false
65
+ )
66
+ end
67
+ end
68
+
69
+ it 'prepares for deploy in why-run mode' do
70
+ with_serverless_chef_platforms('empty') do |platform, repository|
71
+ platform.prepare_for_deploy(
72
+ services: {},
73
+ secrets: {},
74
+ local_environment: false,
75
+ why_run: true
76
+ )
77
+ end
78
+ end
79
+
80
+ it 'prepares for deploy in local mode' do
81
+ with_serverless_chef_platforms('empty') do |platform, repository|
82
+ platform.prepare_for_deploy(
83
+ services: {},
84
+ secrets: {},
85
+ local_environment: true,
86
+ why_run: false
87
+ )
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ context 'with a platform having 1 node' do
94
+
95
+ it 'returns actions to deploy on this node' do
96
+ with_serverless_chef_platforms('1_node') do |platform, repository|
97
+ mock_package(repository)
98
+ platform.prepare_for_deploy(
99
+ services: { 'node' => %w[test_policy] },
100
+ secrets: {},
101
+ local_environment: false,
102
+ why_run: false
103
+ )
104
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository)
105
+ end
106
+ end
107
+
108
+ it 'returns actions to deploy on this node with node attributes setup from metadata' do
109
+ with_serverless_chef_platforms('1_node') do |platform, repository|
110
+ test_nodes_handler.override_metadata_of 'node', :new_metadata, 'new_value'
111
+ mock_package(repository)
112
+ platform.prepare_for_deploy(
113
+ services: { 'node' => %w[test_policy] },
114
+ secrets: {},
115
+ local_environment: false,
116
+ why_run: false
117
+ )
118
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository)
119
+ attributes_file = "#{repository}/dist/prod/test_policy/nodes/node.json"
120
+ expect(File.exist?(attributes_file)).to eq true
121
+ expect(JSON.parse(File.read(attributes_file))).to eq(
122
+ 'description' => 'Single test node',
123
+ 'image' => 'debian_9',
124
+ 'new_metadata' => 'new_value',
125
+ 'private_ips' => ['172.16.0.1'],
126
+ 'property1' => { 'property11' => 'value11' },
127
+ 'property2' => 'value2',
128
+ )
129
+ end
130
+ end
131
+
132
+ it 'returns actions to deploy on this node with secrets' do
133
+ with_serverless_chef_platforms('1_node') do |platform, repository|
134
+ mock_package(repository)
135
+ platform.prepare_for_deploy(
136
+ services: { 'node' => %w[test_policy] },
137
+ secrets: { 'my_secret' => 'secret_value' },
138
+ local_environment: false,
139
+ why_run: false
140
+ )
141
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository)
142
+ end
143
+ end
144
+
145
+ it 'returns actions to deploy on this node in why-run mode' do
146
+ with_serverless_chef_platforms('1_node') do |platform, repository|
147
+ mock_package(repository)
148
+ platform.prepare_for_deploy(
149
+ services: { 'node' => %w[test_policy] },
150
+ secrets: {},
151
+ local_environment: false,
152
+ why_run: true
153
+ )
154
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: true)).to eq expected_actions_to_deploy_chef(repository, check_mode: true)
155
+ end
156
+ end
157
+
158
+ it 'returns actions to deploy on this node using local mode' do
159
+ with_serverless_chef_platforms('1_node') do |platform, repository|
160
+ mock_package(repository)
161
+ platform.prepare_for_deploy(
162
+ services: { 'node' => %w[test_policy] },
163
+ secrets: {},
164
+ local_environment: true,
165
+ why_run: false
166
+ )
167
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository, env: 'local')
168
+ end
169
+ end
170
+
171
+ it 'returns actions to deploy on this node in why-run mode and local mode' do
172
+ with_serverless_chef_platforms('1_node') do |platform, repository|
173
+ mock_package(repository)
174
+ platform.prepare_for_deploy(
175
+ services: { 'node' => %w[test_policy] },
176
+ secrets: {},
177
+ local_environment: true,
178
+ why_run: true
179
+ )
180
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: true)).to eq expected_actions_to_deploy_chef(repository, env: 'local', check_mode: true)
181
+ end
182
+ end
183
+
184
+ it 'returns actions to deploy on this node using root user' do
185
+ with_serverless_chef_platforms('1_node') do |platform, repository|
186
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
187
+ mock_package(repository)
188
+ platform.prepare_for_deploy(
189
+ services: { 'node' => %w[test_policy] },
190
+ secrets: {},
191
+ local_environment: false,
192
+ why_run: false
193
+ )
194
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository, sudo: '')
195
+ end
196
+ end
197
+
198
+ it 'fails with a nice message when chef_versions.yml is missing' do
199
+ with_serverless_chef_platforms('1_node') do |platform, repository|
200
+ mock_package(repository)
201
+ platform.prepare_for_deploy(
202
+ services: { 'node' => %w[test_policy] },
203
+ secrets: {},
204
+ local_environment: false,
205
+ why_run: false
206
+ )
207
+ File.unlink("#{repository}/chef_versions.yml")
208
+ expect { platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false) }.to raise_error "Missing file #{repository}/chef_versions.yml specifying the Chef Infra Client version to be deployed"
209
+ end
210
+ end
211
+
212
+ end
213
+
214
+ context 'with a platform having several nodes' do
215
+
216
+ it 'deploys services declared on 1 node on another node if asked' do
217
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
218
+ mock_package(repository)
219
+ platform.prepare_for_deploy(
220
+ services: { 'node2' => %w[test_policy_1] },
221
+ secrets: {},
222
+ local_environment: false,
223
+ why_run: false
224
+ )
225
+ expect(platform.actions_to_deploy_on('node2', 'test_policy_1', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository, policy: 'test_policy_1', node: 'node2')
226
+ end
227
+ end
228
+
229
+ it 'deploys local nodes' do
230
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
231
+ mock_package(repository)
232
+ platform.prepare_for_deploy(
233
+ services: { 'local' => %w[test_policy_1] },
234
+ secrets: {},
235
+ local_environment: false,
236
+ why_run: false
237
+ )
238
+ expect(platform.actions_to_deploy_on('local', 'test_policy_1', use_why_run: false)).to eq [
239
+ {
240
+ bash: "cd #{repository}/dist/prod/test_policy_1 && sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client --local-mode --json-attributes nodes/local.json"
241
+ }
242
+ ]
243
+ end
244
+ end
245
+
246
+ end
247
+
248
+ context 'with 2 platforms' do
249
+
250
+ it 'deploys a service on a node belonging to another platform' do
251
+ with_serverless_chef_platforms({ 'p1' => '1_node', 'p2' => 'several_nodes' }) do |repositories|
252
+ platform_p1, repository_p1 = repositories.find { |platform, _repository| platform.name == 'p1' }
253
+ mock_package(repository_p1)
254
+ platform_p1.prepare_for_deploy(
255
+ services: { 'node2' => %w[test_policy_1] },
256
+ secrets: {},
257
+ local_environment: false,
258
+ why_run: false
259
+ )
260
+ expect(platform_p1.actions_to_deploy_on('node2', 'test_policy_1', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository_p1, policy: 'test_policy_1', node: 'node2')
261
+ end
262
+ end
263
+
264
+ end
265
+
266
+ end
267
+
268
+ end