hybrid_platforms_conductor 33.1.1 → 33.2.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8698bc386b9a607d4dda6b8a21ee754860b8027a26f851be1887ec8bbe3aaa96
4
- data.tar.gz: ddb3c31da1f23113755fcfc07d97785b0ddc03611922568401043405e50014e8
3
+ metadata.gz: bd578efdc520f51dc9752ace39626e73dbdda736fd4376ee5e9ce55ed34a0a4d
4
+ data.tar.gz: c44c935905b7a62a4a0f3ea037b0f1e4ed8fa07bdad4802e38143fe1a448bfd1
5
5
  SHA512:
6
- metadata.gz: 8076f914cd5675de3b990e78191569ba96c368c840644183c5a52f75feaa67f2b93172465595f8d6619c921c694ea16fb05eed18cc559b560f8dae7c5584fdf0
7
- data.tar.gz: 42b83e310c9f03473e50c4b9694f3320126ebcbe30a4777845eecda87da4ccad78ffb7bcd99f4fb6b2e8b6f98f131052ae667389961602bb525e7e888fb71243
6
+ metadata.gz: f0070cf6736acaa5b9a1e36279bab3b9f6530c26ea341feec4fb4775d022e1c67e2694df832a3ab340b765e10bf510969febe82e4b34fa564e9aab82eea71314
7
+ data.tar.gz: d5cc0229b32b7f75d1c7604e304e6986b0b7ab121676dfd62121d954c48e3ba93f827dabfbb8320c9f945339c334263ff9404c8c60e1be5a0b03e4b390cc044f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,64 @@
1
+ # [v33.2.4](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.2.3...v33.2.4) (2021-06-23 15:14:20)
2
+
3
+ ## Global changes
4
+ ### Patches
5
+
6
+ * [[Hotfix(platform_handler_serverless_chef)] Forward environment in sudo commands](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/fd3b58875665c29dd071b5af2055eab0c45c0974)
7
+ * [[Hotfix] Fixed unbundled environment not cleaned + Moved deployer config DSL in deployer.rb](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/2bce6dbc31d98b27f196ed646eb9aa669b0f9a86)
8
+
9
+ ## Changes for platform_handler_serverless_chef
10
+ ### Patches
11
+
12
+ * [[Hotfix(platform_handler_serverless_chef)] Forward environment in sudo commands](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/fd3b58875665c29dd071b5af2055eab0c45c0974)
13
+
14
+ # [v33.2.3](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.2.2...v33.2.3) (2021-06-23 13:45:56)
15
+
16
+ ## Global changes
17
+ ### Patches
18
+
19
+ * [[Hotfix(provisioner_proxmox)] Add missing require in synchronization script](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/7a6c71595789c9180e1d95323fc5cf5051f2e2cd)
20
+
21
+ ## Changes for provisioner_proxmox
22
+ ### Patches
23
+
24
+ * [[Hotfix(provisioner_proxmox)] Add missing require in synchronization script](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/7a6c71595789c9180e1d95323fc5cf5051f2e2cd)
25
+
26
+ # [v33.2.2](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.2.1...v33.2.2) (2021-06-21 12:41:35)
27
+
28
+ ## Global changes
29
+ ### Patches
30
+
31
+ * [[Hotfix(cmd_runner)] Retain dynamically set environment while executing commands](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/d709d5d2871e43196cc1f5f9eaf5b2155b34ed4e)
32
+
33
+ ## Changes for cmd_runner
34
+ ### Patches
35
+
36
+ * [[Hotfix(cmd_runner)] Retain dynamically set environment while executing commands](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/d709d5d2871e43196cc1f5f9eaf5b2155b34ed4e)
37
+
38
+ # [v33.2.1](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.2.0...v33.2.1) (2021-06-21 10:23:51)
39
+
40
+ ## Global changes
41
+ ### Patches
42
+
43
+ * [[Hotfix(platform_handler_serverless_chef)] Corrected dry-run mode not working](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/4800a0f4255c1999eed33651c1e66c445acd17bb)
44
+
45
+ ## Changes for platform_handler_serverless_chef
46
+ ### Patches
47
+
48
+ * [[Hotfix(platform_handler_serverless_chef)] Corrected dry-run mode not working](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/4800a0f4255c1999eed33651c1e66c445acd17bb)
49
+
50
+ # [v33.2.0](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.1.1...v33.2.0) (2021-06-18 23:22:21)
51
+
52
+ ## Global changes
53
+ ### Patches
54
+
55
+ * [[Feature(platform_handler_serverless_chef)] [#70] Install dependency gems from cookbook metadata before calling chef-client](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/6dfe7aa053db63489f3d0a236433304606051ecd)
56
+
57
+ ## Changes for platform_handler_serverless_chef
58
+ ### Features
59
+
60
+ * [[Feature(platform_handler_serverless_chef)] [#70] Install dependency gems from cookbook metadata before calling chef-client](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/6dfe7aa053db63489f3d0a236433304606051ecd)
61
+
1
62
  # [v33.1.1](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.1.0...v33.1.1) (2021-06-18 13:19:39)
2
63
 
3
64
  ### Patches
@@ -130,7 +130,7 @@ module HybridPlatformsConductor
130
130
  (log_to_stdout ? [@logger_stderr] : []) +
131
131
  (file_output.nil? ? [] : [file_output])
132
132
  ) do
133
- Bundler.with_unbundled_env do
133
+ Bundler.without_bundled_env do
134
134
  cmd_result = TTY::Command.new(
135
135
  printer: :null,
136
136
  pty: true,
@@ -47,12 +47,6 @@ module HybridPlatformsConductor
47
47
  # Array<Hash,Symbol,Object>
48
48
  attr_reader :expected_failures
49
49
 
50
- # List of retriable errors. Each info has the following properties:
51
- # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by those errors
52
- # * *errors_on_stdout* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stdout
53
- # * *errors_on_stderr* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stderr
54
- attr_reader :retriable_errors
55
-
56
50
  # List of deployment schedules. Each info has the following properties:
57
51
  # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule
58
52
  # * *schedule* (IceCube::Schedule): The deployment schedule
@@ -81,11 +75,6 @@ module HybridPlatformsConductor
81
75
  # * *reason* (String): Reason for this expected failure
82
76
  # Array<Hash,Symbol,Object>
83
77
  @expected_failures = []
84
- # List of retriable errors. Each info has the following properties:
85
- # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by those errors
86
- # * *errors_on_stdout* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stdout
87
- # * *errors_on_stderr* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stderr
88
- @retriable_errors = []
89
78
  # List of deployment schedules. Each info has the following properties:
90
79
  # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule
91
80
  # * *schedule* (IceCube::Schedule): The deployment schedule
@@ -162,30 +151,6 @@ module HybridPlatformsConductor
162
151
  end
163
152
  expose :expect_tests_to_fail
164
153
 
165
- # Mark some errors on stdout to be retriable during a deploy
166
- #
167
- # Parameters::
168
- # * *errors* (String, Regexp or Array<String or Regexp>): Single (or list of) errors matching pattern (either as exact string match or using a regexp).
169
- def retry_deploy_for_errors_on_stdout(errors)
170
- @retriable_errors << {
171
- errors_on_stdout: errors.is_a?(Array) ? errors : [errors],
172
- nodes_selectors_stack: current_nodes_selectors_stack
173
- }
174
- end
175
- expose :retry_deploy_for_errors_on_stdout
176
-
177
- # Mark some errors on stderr to be retriable during a deploy
178
- #
179
- # Parameters::
180
- # * *errors* (String, Regexp or Array<String or Regexp>): Single (or list of) errors matching pattern (either as exact string match or using a regexp).
181
- def retry_deploy_for_errors_on_stderr(errors)
182
- @retriable_errors << {
183
- errors_on_stderr: errors.is_a?(Array) ? errors : [errors],
184
- nodes_selectors_stack: current_nodes_selectors_stack
185
- }
186
- end
187
- expose :retry_deploy_for_errors_on_stderr
188
-
189
154
  # Set a deployment schedule
190
155
  #
191
156
  # Parameters::
@@ -0,0 +1,54 @@
1
+ # Add a way to clean the current env from Bundler variables
2
+ module Bundler
3
+
4
+ class << self
5
+
6
+ # Run block with all bundler-related variables removed from the current environment
7
+ def without_bundled_env(&block)
8
+ with_env(current_unbundled_env, &block)
9
+ end
10
+
11
+ # @return [Hash] Environment with all bundler-related variables removed
12
+ def current_unbundled_env
13
+ env = ENV.clone.to_hash
14
+ %w[
15
+ PATH
16
+ RUBYLIB
17
+ RUBYOPT
18
+ ].each do |env_name|
19
+ if original_env.key?(env_name)
20
+ env[env_name] = original_env[env_name]
21
+ else
22
+ env.delete(env_name)
23
+ end
24
+ end
25
+
26
+ env['MANPATH'] = env['BUNDLER_ORIG_MANPATH'] if env.key?('BUNDLER_ORIG_MANPATH')
27
+
28
+ env.delete_if do |k, _|
29
+ %w[
30
+ GEM_
31
+ BUNDLE_
32
+ BUNDLER_
33
+ ].any? { |prefix| k.start_with?(prefix) }
34
+ end
35
+
36
+ if env.key?('RUBYOPT')
37
+ rubyopt = env['RUBYOPT'].split
38
+ rubyopt.delete("-r#{File.expand_path('bundler/setup', __dir__)}")
39
+ rubyopt.delete('-rbundler/setup')
40
+ env['RUBYOPT'] = rubyopt.join(' ')
41
+ end
42
+
43
+ if env.key?('RUBYLIB')
44
+ rubylib = env['RUBYLIB'].split(File::PATH_SEPARATOR)
45
+ rubylib.delete(File.expand_path(__dir__))
46
+ env['RUBYLIB'] = rubylib.join(File::PATH_SEPARATOR)
47
+ end
48
+
49
+ env
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -18,6 +18,12 @@ module HybridPlatformsConductor
18
18
  # Extend the Config DSL
19
19
  module ConfigDSLExtension
20
20
 
21
+ # List of retriable errors. Each info has the following properties:
22
+ # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by those errors
23
+ # * *errors_on_stdout* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stdout
24
+ # * *errors_on_stderr* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stderr
25
+ attr_reader :retriable_errors
26
+
21
27
  # List of log plugins. Each info has the following properties:
22
28
  # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
23
29
  # * *log_plugins* (Array<Symbol>): List of log plugins to be used to store deployment logs.
@@ -36,6 +42,11 @@ module HybridPlatformsConductor
36
42
  # Mixin initializer
37
43
  def init_deployer_config
38
44
  @packaging_timeout_secs = 60
45
+ # List of retriable errors. Each info has the following properties:
46
+ # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by those errors
47
+ # * *errors_on_stdout* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stdout
48
+ # * *errors_on_stderr* (Array<String or Regexp>): List of errors match (as exact string match or using a regexp) to check against stderr
49
+ @retriable_errors = []
39
50
  @deployment_logs = []
40
51
  @secrets_readers = []
41
52
  end
@@ -48,6 +59,28 @@ module HybridPlatformsConductor
48
59
  @packaging_timeout_secs = packaging_timeout_secs
49
60
  end
50
61
 
62
+ # Mark some errors on stdout to be retriable during a deploy
63
+ #
64
+ # Parameters::
65
+ # * *errors* (String, Regexp or Array<String or Regexp>): Single (or list of) errors matching pattern (either as exact string match or using a regexp).
66
+ def retry_deploy_for_errors_on_stdout(errors)
67
+ @retriable_errors << {
68
+ errors_on_stdout: errors.is_a?(Array) ? errors : [errors],
69
+ nodes_selectors_stack: current_nodes_selectors_stack
70
+ }
71
+ end
72
+
73
+ # Mark some errors on stderr to be retriable during a deploy
74
+ #
75
+ # Parameters::
76
+ # * *errors* (String, Regexp or Array<String or Regexp>): Single (or list of) errors matching pattern (either as exact string match or using a regexp).
77
+ def retry_deploy_for_errors_on_stderr(errors)
78
+ @retriable_errors << {
79
+ errors_on_stderr: errors.is_a?(Array) ? errors : [errors],
80
+ nodes_selectors_stack: current_nodes_selectors_stack
81
+ }
82
+ end
83
+
51
84
  # Set the deployment log plugins to be used
52
85
  #
53
86
  # Parameters::
@@ -1,4 +1,6 @@
1
1
  require 'English'
2
+ require 'bundler'
3
+ require 'hybrid_platforms_conductor/core_extensions/bundler/without_bundled_env'
2
4
  require 'optparse'
3
5
  require 'logger'
4
6
  require 'hybrid_platforms_conductor/config'
@@ -179,6 +179,13 @@ module HybridPlatformsConductor
179
179
  /opt/chef-workstation/bin/chef export #{policy_file} #{package_dir} --chef-license accept#{extra_cp_data_bags}"
180
180
  next if @cmd_runner.dry_run
181
181
 
182
+ # Write the list of gems to be installed for this package
183
+ File.write(
184
+ "#{@repository_path}/#{package_dir}/gems.json",
185
+ Dir.glob("#{@repository_path}/#{package_dir}/cookbook_artifacts/*/metadata.json").map do |metadata|
186
+ JSON.parse(File.read(metadata))['gems']
187
+ end.flatten(1).to_json
188
+ )
182
189
  # Create secrets file
183
190
  secrets_file = "#{@repository_path}/#{package_dir}/data_bags/hpc_secrets/hpc_secrets.json"
184
191
  FileUtils.mkdir_p(File.dirname(secrets_file))
@@ -220,10 +227,13 @@ module HybridPlatformsConductor
220
227
  # * Array< Hash<Symbol,Object> >: List of actions to be done
221
228
  def actions_to_deploy_on(node, service, use_why_run: true)
222
229
  package_dir = "#{@repository_path}/dist/#{@local_env ? 'local' : 'prod'}/#{service}"
230
+ gems_to_install = []
223
231
  # Generate the nodes attributes file
224
232
  unless @cmd_runner.dry_run
225
233
  FileUtils.mkdir_p "#{package_dir}/nodes"
226
234
  File.write("#{package_dir}/nodes/#{node}.json", (known_nodes.include?(node) ? metadata_for(node) : {}).merge(@nodes_handler.metadata_of(node)).to_json)
235
+ # Get the gems to be installed
236
+ gems_to_install = JSON.parse(File.read("#{package_dir}/gems.json"))
227
237
  end
228
238
  client_options = [
229
239
  '--local-mode',
@@ -233,7 +243,19 @@ module HybridPlatformsConductor
233
243
  client_options << '--why-run' if use_why_run
234
244
  if @nodes_handler.get_use_local_chef_of(node)
235
245
  # Just run the chef-client directly from the packaged repository
236
- [{ bash: "cd #{package_dir} && #{@cmd_runner.root? ? '' : 'sudo '}SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client #{client_options.join(' ')}" }]
246
+ sudo_prefix = @cmd_runner.root? ? '' : 'sudo '
247
+ [
248
+ {
249
+ bash: [
250
+ 'set -e',
251
+ "cd #{package_dir}"
252
+ ] +
253
+ gems_to_install.map { |(gem_name, gem_version)| "#{sudo_prefix}SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef gem install #{gem_name} --version \"#{gem_version}\"" } +
254
+ [
255
+ "#{sudo_prefix}SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client #{client_options.join(' ')}"
256
+ ]
257
+ }
258
+ ]
237
259
  else
238
260
  # Upload the package and run it from the node
239
261
  package_name = File.basename(package_dir)
@@ -241,7 +263,7 @@ module HybridPlatformsConductor
241
263
  raise "Missing file #{chef_versions_file} specifying the Chef Infra Client version to be deployed" unless File.exist?(chef_versions_file)
242
264
 
243
265
  required_chef_client_version = YAML.load_file(chef_versions_file)['client']
244
- sudo = (@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} ")
266
+ sudo = (@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} -E ")
245
267
  [
246
268
  {
247
269
  # Install dependencies
@@ -261,10 +283,14 @@ module HybridPlatformsConductor
261
283
  scp: { package_dir => './hpc_deploy' },
262
284
  remote_bash: [
263
285
  'set -e',
264
- "cd ./hpc_deploy/#{package_name}",
265
- "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/bin/chef-client #{client_options.join(' ')}",
266
- 'cd ..'
267
- ] + (log_debug? ? [] : ["#{sudo}rm -rf ./hpc_deploy/#{package_name}"])
286
+ "cd ./hpc_deploy/#{package_name}"
287
+ ] +
288
+ gems_to_install.map { |(gem_name, gem_version)| "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/embedded/bin/gem install #{gem_name} --version \"#{gem_version}\"" } +
289
+ [
290
+ "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/bin/chef-client #{client_options.join(' ')}",
291
+ 'cd ..'
292
+ ] +
293
+ (log_debug? ? [] : ["#{sudo}rm -rf ./hpc_deploy/#{package_name}"])
268
294
  }
269
295
  ]
270
296
  end
@@ -34,6 +34,7 @@
34
34
  # * *hpc_password_for_proxmox*: Password to be used to query Proxmox API
35
35
  # * *hpc_realm_for_proxmox*: Realm used to connect to the Proxmox API [default = 'pam']
36
36
 
37
+ require 'English'
37
38
  require 'json'
38
39
 
39
40
  reserved_resource = nil
@@ -1,5 +1,5 @@
1
1
  module HybridPlatformsConductor
2
2
 
3
- VERSION = '33.1.1'
3
+ VERSION = '33.2.4'
4
4
 
5
5
  end
@@ -47,7 +47,21 @@ describe HybridPlatformsConductor::CmdRunner do
47
47
 
48
48
  it 'runs a command in an un-bundled environment' do
49
49
  with_repository do
50
- expect(test_cmd_runner.run_cmd('echo "${BUNDLE_GEMFILE}"')).to eq [0, "\n", '']
50
+ %w[
51
+ BUNDLE_GEMFILE
52
+ GEM_HOME
53
+ RUBYOPT
54
+ ].each do |var_to_check|
55
+ expect(test_cmd_runner.run_cmd("echo \"${#{var_to_check}}\"")).to eq [0, "\n", '']
56
+ end
57
+ end
58
+ end
59
+
60
+ it 'keeps dynamically set environment' do
61
+ with_repository do
62
+ value = ('a'..'z').to_a.sample(8).join
63
+ ENV['hpc_test_new_variable'] = value
64
+ expect(test_cmd_runner.run_cmd('echo "${hpc_test_new_variable}"')).to eq [0, "#{value}\n", '']
51
65
  end
52
66
  end
53
67
 
@@ -155,40 +155,6 @@ describe HybridPlatformsConductor::Config do
155
155
  end
156
156
  end
157
157
 
158
- it 'returns the retriable errors correctly' do
159
- with_platforms '
160
- retry_deploy_for_errors_on_stdout \'Retry stdout global\'
161
- retry_deploy_for_errors_on_stderr [
162
- \'Retry stderr global\',
163
- /.+Retry stderr regexp global/
164
- ]
165
- for_nodes(%w[node1 node2 node3]) do
166
- retry_deploy_for_errors_on_stdout \'Retry stdout nodes\'
167
- retry_deploy_for_errors_on_stderr \'Retry stderr nodes\'
168
- end
169
- ' do
170
- sort_proc = proc { |retriable_error_info| ((retriable_error_info[:errors_on_stdout] || []) + (retriable_error_info[:errors_on_stderr] || [])).first.to_s }
171
- expect(test_config.retriable_errors.sort_by(&sort_proc)).to eq [
172
- {
173
- nodes_selectors_stack: [],
174
- errors_on_stdout: ['Retry stdout global']
175
- },
176
- {
177
- nodes_selectors_stack: [],
178
- errors_on_stderr: ['Retry stderr global', /.+Retry stderr regexp global/]
179
- },
180
- {
181
- nodes_selectors_stack: [%w[node1 node2 node3]],
182
- errors_on_stdout: ['Retry stdout nodes']
183
- },
184
- {
185
- nodes_selectors_stack: [%w[node1 node2 node3]],
186
- errors_on_stderr: ['Retry stderr nodes']
187
- }
188
- ].sort_by(&sort_proc)
189
- end
190
- end
191
-
192
158
  it 'returns the deployment schedules correctly' do
193
159
  with_platforms '
194
160
  deployment_schedule(IceCube::Schedule.new(Time.parse(\'2020-05-01 11:22:33 UTC\')))
@@ -8,6 +8,40 @@ describe HybridPlatformsConductor::Deployer do
8
8
  end
9
9
  end
10
10
 
11
+ it 'returns the retriable errors correctly' do
12
+ with_platforms '
13
+ retry_deploy_for_errors_on_stdout \'Retry stdout global\'
14
+ retry_deploy_for_errors_on_stderr [
15
+ \'Retry stderr global\',
16
+ /.+Retry stderr regexp global/
17
+ ]
18
+ for_nodes(%w[node1 node2 node3]) do
19
+ retry_deploy_for_errors_on_stdout \'Retry stdout nodes\'
20
+ retry_deploy_for_errors_on_stderr \'Retry stderr nodes\'
21
+ end
22
+ ' do
23
+ sort_proc = proc { |retriable_error_info| ((retriable_error_info[:errors_on_stdout] || []) + (retriable_error_info[:errors_on_stderr] || [])).first.to_s }
24
+ expect(test_config.retriable_errors.sort_by(&sort_proc)).to eq [
25
+ {
26
+ nodes_selectors_stack: [],
27
+ errors_on_stdout: ['Retry stdout global']
28
+ },
29
+ {
30
+ nodes_selectors_stack: [],
31
+ errors_on_stderr: ['Retry stderr global', /.+Retry stderr regexp global/]
32
+ },
33
+ {
34
+ nodes_selectors_stack: [%w[node1 node2 node3]],
35
+ errors_on_stdout: ['Retry stdout nodes']
36
+ },
37
+ {
38
+ nodes_selectors_stack: [%w[node1 node2 node3]],
39
+ errors_on_stderr: ['Retry stderr nodes']
40
+ }
41
+ ].sort_by(&sort_proc)
42
+ end
43
+ end
44
+
11
45
  it 'declares log plugins to be used' do
12
46
  with_platforms(
13
47
  <<~EO_CONFIG
@@ -12,6 +12,7 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
12
12
  # * *export* (Boolean): Are we expecting the chef export stage? [default: true]
13
13
  # * *data_bags* (Boolean): Do we expect data bags copy? [default: false]
14
14
  # * *env* (String): Expected environment being packaged [default: 'prod']
15
+ # * *cookbook_metadata* (Hash<String, Hash>): JSON metadata to generate for packaged cookbooks [default: {}]
15
16
  # * *block* (Proc): Code called with mock in place
16
17
  def with_packaging_mocked(
17
18
  repository,
@@ -21,6 +22,7 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
21
22
  export: true,
22
23
  data_bags: false,
23
24
  env: 'prod',
25
+ cookbook_metadata: {},
24
26
  &block
25
27
  )
26
28
  with_cmd_runner_mocked(
@@ -49,8 +51,14 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
49
51
  [
50
52
  %r{^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)} --chef-license accept#{data_bags ? " && cp -ar data_bags/ dist/#{Regexp.escape(env)}/#{Regexp.escape(policy)}/" : ''}$},
51
53
  proc do
52
- FileUtils.mkdir_p "#{repository}/dist/#{env}/#{policy}"
53
- FileUtils.cp_r("#{repository}/data_bags", "#{repository}/dist/#{env}/#{policy}/") if data_bags
54
+ package_dir = "#{repository}/dist/#{env}/#{policy}"
55
+ FileUtils.mkdir_p package_dir
56
+ FileUtils.cp_r("#{repository}/data_bags", "#{package_dir}/") if data_bags
57
+ cookbook_metadata.each do |cookbook, metadata|
58
+ metadata_file = "#{package_dir}/cookbook_artifacts/#{cookbook}/metadata.json"
59
+ FileUtils.mkdir_p File.dirname(metadata_file)
60
+ File.write(metadata_file, metadata.to_json)
61
+ end
54
62
  [0, 'Chef export done', '']
55
63
  end
56
64
  ]
@@ -80,6 +88,9 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
80
88
  with_serverless_chef_platforms('1_node') do |platform, repository|
81
89
  with_packaging_mocked(repository) do
82
90
  platform.package(services: { 'node' => %w[test_policy] }, secrets: {}, local_environment: false)
91
+ gems_file = "#{repository}/dist/prod/test_policy/gems.json"
92
+ expect(File.exist?(gems_file)).to eq true
93
+ expect(JSON.parse(File.read(gems_file))).to eq []
83
94
  end
84
95
  end
85
96
  end
@@ -212,6 +223,41 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
212
223
 
213
224
  end
214
225
 
226
+ context 'with a platform having several cookbooks' do
227
+
228
+ it 'generates the gems info to be installed' do
229
+ with_serverless_chef_platforms('several_cookbooks') do |platform, repository|
230
+ with_packaging_mocked(
231
+ repository,
232
+ policy: 'test_policy_1',
233
+ cookbook_metadata: {
234
+ 'test_cookbook_1' => {
235
+ gems: [
236
+ ['my_gem_1', '0.0.1'],
237
+ ['my_gem_2', '0.0.2']
238
+ ]
239
+ },
240
+ 'dependency_cookbook' => {
241
+ gems: [
242
+ ['my_gem_3', '~> 1.3']
243
+ ]
244
+ }
245
+ }
246
+ ) do
247
+ platform.package(services: { 'node1' => %w[test_policy_1] }, secrets: {}, local_environment: false)
248
+ gems_file = "#{repository}/dist/prod/test_policy_1/gems.json"
249
+ expect(File.exist?(gems_file)).to eq true
250
+ expect(JSON.parse(File.read(gems_file)).sort).to eq [
251
+ ['my_gem_1', '0.0.1'],
252
+ ['my_gem_2', '0.0.2'],
253
+ ['my_gem_3', '~> 1.3']
254
+ ].sort
255
+ end
256
+ end
257
+ end
258
+
259
+ end
260
+
215
261
  context 'with a platform having data bags' do
216
262
 
217
263
  it 'packages data bags' do
@@ -6,9 +6,18 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
6
6
  #
7
7
  # Parameters::
8
8
  # * *repository* (String): The repository we package
9
+ # * *env* (String): The environment for which this repository is packaged [default: 'prod']
9
10
  # * *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}"
11
+ # * *gems* (Array<String, String>): The [<name>, <version>] gems info to be installed as generated by the packaging [default: []]
12
+ def mock_package(
13
+ repository,
14
+ env: 'prod',
15
+ service: 'test_policy',
16
+ gems: []
17
+ )
18
+ package_dir = "#{repository}/dist/#{env}/#{service}"
19
+ FileUtils.mkdir_p package_dir
20
+ File.write("#{package_dir}/gems.json", gems.to_json)
12
21
  end
13
22
 
14
23
  # Get expected actions to deploy a service on a given node
@@ -20,15 +29,17 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
20
29
  # * *env* (String): Environment expected to be packaged [default: 'prod']
21
30
  # * *policy* (String): Expected policy to be packaged [default: 'test_policy']
22
31
  # * *node* (String): Expected node to be deployed [default: 'node']
32
+ # * *gems_install_cmds* (Array<String>): Expected gem install commands [default: []]
23
33
  # Result::
24
34
  # * Array: Expected actions
25
35
  def expected_actions_to_deploy_chef(
26
36
  repository,
27
37
  check_mode: false,
28
- sudo: 'sudo -u root ',
38
+ sudo: 'sudo -u root -E ',
29
39
  env: 'prod',
30
40
  policy: 'test_policy',
31
- node: 'node'
41
+ node: 'node',
42
+ gems_install_cmds: []
32
43
  )
33
44
  [
34
45
  {
@@ -48,11 +59,14 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
48
59
  scp: { "#{repository}/dist/#{env}/#{policy}" => './hpc_deploy' },
49
60
  remote_bash: [
50
61
  'set -e',
51
- "cd ./hpc_deploy/#{policy}",
52
- "#{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' : ''}",
53
- 'cd ..',
54
- "#{sudo}rm -rf ./hpc_deploy/#{policy}"
55
- ]
62
+ "cd ./hpc_deploy/#{policy}"
63
+ ] +
64
+ gems_install_cmds.map { |gem_install_cmd| "#{sudo}SSL_CERT_DIR=/etc/ssl/certs /opt/chef/embedded/bin/#{gem_install_cmd}" } +
65
+ [
66
+ "#{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' : ''}",
67
+ 'cd ..',
68
+ "#{sudo}rm -rf ./hpc_deploy/#{policy}"
69
+ ]
56
70
  }
57
71
  ]
58
72
  end
@@ -109,6 +123,33 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
109
123
  end
110
124
  end
111
125
 
126
+ it 'returns actions to deploy on this node with gems to be installed' do
127
+ with_serverless_chef_platforms('1_node') do |platform, repository|
128
+ mock_package(
129
+ repository,
130
+ gems: [
131
+ ['my_gem_1', '0.0.1'],
132
+ ['my_gem_2', '0.0.2'],
133
+ ['my_gem_3', '~> 1.3']
134
+ ]
135
+ )
136
+ platform.prepare_for_deploy(
137
+ services: { 'node' => %w[test_policy] },
138
+ secrets: {},
139
+ local_environment: false,
140
+ why_run: false
141
+ )
142
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(
143
+ repository,
144
+ gems_install_cmds: [
145
+ 'gem install my_gem_1 --version "0.0.1"',
146
+ 'gem install my_gem_2 --version "0.0.2"',
147
+ 'gem install my_gem_3 --version "~> 1.3"'
148
+ ]
149
+ )
150
+ end
151
+ end
152
+
112
153
  it 'returns actions to deploy on this node with node attributes setup from metadata' do
113
154
  with_serverless_chef_platforms('1_node') do |platform, repository|
114
155
  test_nodes_handler.override_metadata_of 'node', :new_metadata, 'new_value'
@@ -161,7 +202,7 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
161
202
 
162
203
  it 'returns actions to deploy on this node using local mode' do
163
204
  with_serverless_chef_platforms('1_node') do |platform, repository|
164
- mock_package(repository)
205
+ mock_package(repository, env: 'local')
165
206
  platform.prepare_for_deploy(
166
207
  services: { 'node' => %w[test_policy] },
167
208
  secrets: {},
@@ -174,7 +215,7 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
174
215
 
175
216
  it 'returns actions to deploy on this node in why-run mode and local mode' do
176
217
  with_serverless_chef_platforms('1_node') do |platform, repository|
177
- mock_package(repository)
218
+ mock_package(repository, env: 'local')
178
219
  platform.prepare_for_deploy(
179
220
  services: { 'node' => %w[test_policy] },
180
221
  secrets: {},
@@ -219,7 +260,7 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
219
260
 
220
261
  it 'deploys services declared on 1 node on another node if asked' do
221
262
  with_serverless_chef_platforms('several_nodes') do |platform, repository|
222
- mock_package(repository)
263
+ mock_package(repository, service: 'test_policy_1')
223
264
  platform.prepare_for_deploy(
224
265
  services: { 'node2' => %w[test_policy_1] },
225
266
  secrets: {},
@@ -230,9 +271,38 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
230
271
  end
231
272
  end
232
273
 
233
- it 'deploys local nodes' do
274
+ it 'deploys using the local chef workstation when use_local_chef is set' do
234
275
  with_serverless_chef_platforms('several_nodes') do |platform, repository|
235
- mock_package(repository)
276
+ mock_package(repository, service: 'test_policy_1')
277
+ platform.prepare_for_deploy(
278
+ services: { 'local' => %w[test_policy_1] },
279
+ secrets: {},
280
+ local_environment: false,
281
+ why_run: false
282
+ )
283
+ expect(platform.actions_to_deploy_on('local', 'test_policy_1', use_why_run: false)).to eq [
284
+ {
285
+ bash: [
286
+ 'set -e',
287
+ "cd #{repository}/dist/prod/test_policy_1",
288
+ 'sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client --local-mode --chef-license accept --json-attributes nodes/local.json'
289
+ ]
290
+ }
291
+ ]
292
+ end
293
+ end
294
+
295
+ it 'deploys using the local chef workstation with gems to be installed when use_local_chef is set' do
296
+ with_serverless_chef_platforms('several_nodes') do |platform, repository|
297
+ mock_package(
298
+ repository,
299
+ service: 'test_policy_1',
300
+ gems: [
301
+ ['my_gem_1', '0.0.1'],
302
+ ['my_gem_2', '0.0.2'],
303
+ ['my_gem_3', '~> 1.3']
304
+ ]
305
+ )
236
306
  platform.prepare_for_deploy(
237
307
  services: { 'local' => %w[test_policy_1] },
238
308
  secrets: {},
@@ -241,7 +311,14 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
241
311
  )
242
312
  expect(platform.actions_to_deploy_on('local', 'test_policy_1', use_why_run: false)).to eq [
243
313
  {
244
- bash: "cd #{repository}/dist/prod/test_policy_1 && sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client --local-mode --chef-license accept --json-attributes nodes/local.json"
314
+ bash: [
315
+ 'set -e',
316
+ "cd #{repository}/dist/prod/test_policy_1",
317
+ 'sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef gem install my_gem_1 --version "0.0.1"',
318
+ 'sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef gem install my_gem_2 --version "0.0.2"',
319
+ 'sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef gem install my_gem_3 --version "~> 1.3"',
320
+ 'sudo SSL_CERT_DIR=/etc/ssl/certs /opt/chef-workstation/bin/chef-client --local-mode --chef-license accept --json-attributes nodes/local.json'
321
+ ]
245
322
  }
246
323
  ]
247
324
  end
@@ -254,7 +331,7 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
254
331
  it 'deploys a service on a node belonging to another platform' do
255
332
  with_serverless_chef_platforms({ 'p1' => '1_node', 'p2' => 'several_nodes' }) do |repositories|
256
333
  platform_1, repository_1 = repositories.find { |platform, _repository| platform.name == 'p1' }
257
- mock_package(repository_1)
334
+ mock_package(repository_1, service: 'test_policy_1')
258
335
  platform_1.prepare_for_deploy(
259
336
  services: { 'node2' => %w[test_policy_1] },
260
337
  secrets: {},
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hybrid_platforms_conductor
3
3
  version: !ruby/object:Gem::Version
4
- version: 33.1.1
4
+ version: 33.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muriel Salvan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-18 00:00:00.000000000 Z
11
+ date: 2021-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: range_operators
@@ -695,6 +695,7 @@ files:
695
695
  - lib/hybrid_platforms_conductor/config.rb
696
696
  - lib/hybrid_platforms_conductor/confluence.rb
697
697
  - lib/hybrid_platforms_conductor/connector.rb
698
+ - lib/hybrid_platforms_conductor/core_extensions/bundler/without_bundled_env.rb
698
699
  - lib/hybrid_platforms_conductor/core_extensions/cleanroom/fix_kwargs.rb
699
700
  - lib/hybrid_platforms_conductor/core_extensions/symbol/zero.rb
700
701
  - lib/hybrid_platforms_conductor/credentials.rb