hybrid_platforms_conductor 33.5.0 → 33.5.1

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.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/lib/hybrid_platforms_conductor/actions_executor.rb +29 -1
  4. data/lib/hybrid_platforms_conductor/connector.rb +4 -1
  5. data/lib/hybrid_platforms_conductor/deployer.rb +5 -7
  6. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +2 -2
  7. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +4 -3
  8. data/lib/hybrid_platforms_conductor/hpc_plugins/log/remote_fs.rb +5 -6
  9. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +1 -1
  10. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +1 -1
  11. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
  12. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -2
  13. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -2
  14. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -2
  15. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -2
  16. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -2
  17. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +1 -1
  18. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +1 -2
  19. data/lib/hybrid_platforms_conductor/test.rb +21 -7
  20. data/lib/hybrid_platforms_conductor/tests_runner.rb +7 -6
  21. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  22. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +78 -0
  23. data/spec/hybrid_platforms_conductor_test/api/actions_executor/helpers_spec.rb +195 -0
  24. data/spec/hybrid_platforms_conductor_test/api/deployer/log_plugins/remote_fs_spec.rb +215 -0
  25. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +38 -0
  26. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/chef_versions.yml +3 -0
  27. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/nodes/node.json +15 -0
  28. data/spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/policyfiles/test_policy.rb +3 -0
  29. data/spec/hybrid_platforms_conductor_test/shared_examples/deployer.rb +134 -0
  30. metadata +5 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: daf46892dd3b5a79ff0e54f16d6881b80519e8fe926e9952ad7faafd1706c31e
4
- data.tar.gz: 84f9ee06afb8141f140a8754d0961217ceb14b3f8d2d1d2577792be420d42aa2
3
+ metadata.gz: a1e882e48d05f919ad5818c9251e045f941d78a9eacc16824f3fd49e787d91b5
4
+ data.tar.gz: b685a6a1ca1f6f40714da2443ad7de95d78e90489f15a4b8499e153f4d84945a
5
5
  SHA512:
6
- metadata.gz: 7b1355694d9c7dbc5b2d2f9f6555972c25033d11bd07b14dfc728c94b2965ac1a852c91cb6ed4f20a26bc41cceb12f437a8b599177331cbf544e38ebc387cd4a
7
- data.tar.gz: 8636507ef5724bd9f0b3ffbb1f08c3efd1a48d39fe7161a4421350b4a03a9afff279b5522175418742ba87f7daca4dcdb4382e10f3283c39f9816eceba04bdc3
6
+ metadata.gz: f9386d953b2e652fd453656a21a935470099ba3f935a82229829d5777408e93149833883d7acd277da6cf2f08ba5ca49c8c62d43d3207b34113c347299335e5f
7
+ data.tar.gz: 9066d78f77fed46560b1884bade1074055da61547bd196c2a6479cf9412ba30f9d7518f91e05244307b703ebd241a620985e59f93a7911cd353543af26ae3699
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # [v33.5.1](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.5.0...v33.5.1) (2021-07-07 12:01:32)
2
+
3
+ ### Patches
4
+
5
+ * [[Bugfix] [#87] Make sure local nodes and root accounts are taken into account when getting sudo prefixes](https://github.com/sweet-delights/hybrid-platforms-conductor/commit/cb626f1c99a6f1a95c9c884c03bf3fd71045259c)
6
+
1
7
  # [v33.5.0](https://github.com/sweet-delights/hybrid-platforms-conductor/compare/v33.4.0...v33.5.0) (2021-07-07 11:03:01)
2
8
 
3
9
  ### Features
@@ -53,7 +53,8 @@ module HybridPlatformsConductor
53
53
  logger_stderr: @logger_stderr,
54
54
  config: @config,
55
55
  cmd_runner: @cmd_runner,
56
- nodes_handler: @nodes_handler
56
+ nodes_handler: @nodes_handler,
57
+ actions_executor: self
57
58
  )
58
59
  end
59
60
  )
@@ -246,6 +247,33 @@ module HybridPlatformsConductor
246
247
  @connector_plugins[connector_name]
247
248
  end
248
249
 
250
+ # Is the access to a given node privileged?
251
+ # Take into account if remote actions are executed on a local node, and configurable sudos.
252
+ #
253
+ # Parameters::
254
+ # * *node* (String): Node on which we want privileged access
255
+ # Result::
256
+ # * Boolean: Is the access privileged?
257
+ def privileged_access?(node)
258
+ (@nodes_handler.get_local_node_of(node) ? @cmd_runner.whoami : connector(:ssh).ssh_user) == 'root'
259
+ end
260
+
261
+ # Get the sudo prefix to get privileged access.
262
+ # Take into account if remote actions are executed on a local node, and configurable sudos.
263
+ #
264
+ # Parameters::
265
+ # * *node* (String): Node on which we want privileged access
266
+ # * *forward_env* (Boolean): Do we need to forward environment in case of sudo? [default: false]
267
+ # Result::
268
+ # * String: Sudo prefix to be used (can be empty if root is being used)
269
+ def sudo_prefix(node, forward_env: false)
270
+ if privileged_access?(node)
271
+ ''
272
+ else
273
+ "#{@nodes_handler.sudo_on(node)} #{forward_env ? '-E ' : ''}"
274
+ end
275
+ end
276
+
249
277
  private
250
278
 
251
279
  # Execute a list of actions for a node, and return exit codes, stdout and stderr of those actions.
@@ -14,16 +14,19 @@ module HybridPlatformsConductor
14
14
  # * *config* (Config): Config to be used. [default: Config.new]
15
15
  # * *cmd_runner* (CmdRunner): Command executor to be used. [default: CmdRunner.new]
16
16
  # * *nodes_handler* (NodesHandler): NodesHandler to be used. [default: NodesHandler.new]
17
+ # * *actions_executor* (ActionsExecutor): ActionsExecutor to be used. [default: ActionsExecutor.new]
17
18
  def initialize(
18
19
  logger: Logger.new($stdout),
19
20
  logger_stderr: Logger.new($stderr),
20
21
  config: Config.new,
21
22
  cmd_runner: CmdRunner.new,
22
- nodes_handler: NodesHandler.new
23
+ nodes_handler: NodesHandler.new,
24
+ actions_executor: ActionsExecutor.new
23
25
  )
24
26
  super(logger: logger, logger_stderr: logger_stderr, config: config)
25
27
  @cmd_runner = cmd_runner
26
28
  @nodes_handler = nodes_handler
29
+ @actions_executor = actions_executor
27
30
  # If the connector has an initializer, use it
28
31
  init if respond_to?(:init)
29
32
  end
@@ -544,15 +544,13 @@ module HybridPlatformsConductor
544
544
  # Result::
545
545
  # * Hash<String, [Integer or Symbol, String, String]>: Exit status code (or Symbol in case of error or dry run), standard output and error for each node.
546
546
  def deploy(services)
547
- # Get the ssh user directly from the connector
548
- ssh_user = @actions_executor.connector(:ssh).ssh_user
549
-
550
547
  # Deploy for real
551
548
  @nodes_handler.prefetch_metadata_of services.keys, :image
552
549
  outputs = @actions_executor.execute_actions(
553
550
  services.map do |node, node_services|
554
551
  image_id = @nodes_handler.get_image_of(node)
555
- sudo = (ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} ")
552
+ need_sudo = !@actions_executor.privileged_access?(node)
553
+ sudo = @actions_executor.sudo_prefix(node)
556
554
  # Install corporate certificates if present
557
555
  certificate_actions =
558
556
  if @local_environment && ENV['hpc_certificates']
@@ -568,7 +566,7 @@ module HybridPlatformsConductor
568
566
  {
569
567
  scp: {
570
568
  ENV['hpc_certificates'] => '/usr/local/share/ca-certificates',
571
- :sudo => ssh_user != 'root'
569
+ :sudo => need_sudo
572
570
  },
573
571
  remote_bash: "#{sudo}update-ca-certificates"
574
572
  }
@@ -584,7 +582,7 @@ module HybridPlatformsConductor
584
582
  cert_file,
585
583
  '/etc/pki/ca-trust/source/anchors'
586
584
  ]
587
- end.to_h.merge(sudo: ssh_user != 'root'),
585
+ end.to_h.merge(sudo: need_sudo),
588
586
  remote_bash: [
589
587
  "#{sudo}update-ca-trust enable",
590
588
  "#{sudo}update-ca-trust extract"
@@ -619,7 +617,7 @@ module HybridPlatformsConductor
619
617
  services.keys.map do |node|
620
618
  [
621
619
  node,
622
- { remote_bash: "#{ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock" }
620
+ { remote_bash: "#{@actions_executor.sudo_prefix(node)}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock" }
623
621
  ]
624
622
  end.to_h,
625
623
  timeout: 10,
@@ -77,8 +77,8 @@ module HybridPlatformsConductor
77
77
  def remote_copy(from, to, sudo: false, owner: nil, group: nil)
78
78
  # If the destination is a relative path, prepend the workspace dir to it.
79
79
  to = "#{workspace_for(@node)}/#{to}" unless to.start_with?('/')
80
- if sudo
81
- run_cmd "#{@nodes_handler.sudo_on(@node)} cp -r \"#{from}\" \"#{to}\""
80
+ if sudo && !@actions_executor.privileged_access?(@node)
81
+ run_cmd "#{@actions_executor.sudo_prefix(@node)}cp -r \"#{from}\" \"#{to}\""
82
82
  else
83
83
  FileUtils.cp_r from, to unless @cmd_runner.dry_run
84
84
  end
@@ -310,13 +310,14 @@ module HybridPlatformsConductor
310
310
  # * *owner* (String or nil): Owner to be used when copying the files, or nil for current one [default: nil]
311
311
  # * *group* (String or nil): Group to be used when copying the files, or nil for current one [default: nil]
312
312
  def remote_copy(from, to, sudo: false, owner: nil, group: nil)
313
+ need_sudo = sudo && !@actions_executor.privileged_access?(@node)
313
314
  if @nodes_handler.get_ssh_session_exec_of(@node) == false
314
315
  # We don't have ExecSession, so don't use ssh, but scp instead.
315
- if sudo
316
+ if need_sudo
316
317
  # We need to first copy the file in an accessible directory, and then sudo mv
317
318
  remote_bash('mkdir -p hpc_tmp_scp')
318
319
  run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:./hpc_tmp_scp"
319
- remote_bash("#{@nodes_handler.sudo_on(@node)} mv ./hpc_tmp_scp/#{File.basename(from)} #{to}")
320
+ remote_bash("#{@actions_executor.sudo_prefix(@node)}mv ./hpc_tmp_scp/#{File.basename(from)} #{to}")
320
321
  else
321
322
  run_cmd "scp -S #{ssh_exec} #{from} #{ssh_url}:#{to}"
322
323
  end
@@ -332,7 +333,7 @@ module HybridPlatformsConductor
332
333
  #{File.basename(from)} | \
333
334
  #{ssh_exec} \
334
335
  #{ssh_url} \
335
- \"#{sudo ? "#{@nodes_handler.sudo_on(@node)} " : ''}tar \
336
+ \"#{need_sudo ? @actions_executor.sudo_prefix(@node) : ''}tar \
336
337
  --extract \
337
338
  --gunzip \
338
339
  --file - \
@@ -29,10 +29,9 @@ module HybridPlatformsConductor
29
29
  # Result::
30
30
  # * Array< Hash<Symbol,Object> >: List of actions to be done
31
31
  def actions_to_save_logs(node, services, deployment_info, exit_status, stdout, stderr)
32
- # Create a log file to be scp with all relevant info
33
- ssh_user = @actions_executor.connector(:ssh).ssh_user
34
- sudo_prefix = ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "
35
- log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{ssh_user}"
32
+ # Create a log file to be scp-ed with all relevant info
33
+ sudo_prefix = @actions_executor.sudo_prefix(node)
34
+ log_file = "#{Dir.tmpdir}/hpc_deploy_logs/#{node}_#{Time.now.utc.strftime('%F_%H%M%S')}_#{@actions_executor.connector(:ssh).ssh_user}"
36
35
  [
37
36
  {
38
37
  ruby: proc do
@@ -56,7 +55,7 @@ module HybridPlatformsConductor
56
55
  {
57
56
  scp: {
58
57
  log_file => '/var/log/deployments',
59
- :sudo => ssh_user != 'root',
58
+ :sudo => !@actions_executor.privileged_access?(node),
60
59
  :owner => 'root',
61
60
  :group => 'root'
62
61
  }
@@ -85,7 +84,7 @@ module HybridPlatformsConductor
85
84
  # Result::
86
85
  # * Array< Hash<Symbol,Object> >: List of actions to be done
87
86
  def actions_to_read_logs(node)
88
- sudo_prefix = @actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "
87
+ sudo_prefix = @actions_executor.sudo_prefix(node)
89
88
  [
90
89
  { remote_bash: "#{sudo_prefix}cat /var/log/deployments/`#{sudo_prefix}ls -t /var/log/deployments/ | head -1`" }
91
90
  ]
@@ -263,7 +263,7 @@ module HybridPlatformsConductor
263
263
  raise "Missing file #{chef_versions_file} specifying the Chef Infra Client version to be deployed" unless File.exist?(chef_versions_file)
264
264
 
265
265
  required_chef_client_version = YAML.load_file(chef_versions_file)['client']
266
- sudo = (@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} -E ")
266
+ sudo = @actions_executor.sudo_prefix(node, forward_env: true)
267
267
  [
268
268
  {
269
269
  # Install dependencies
@@ -436,7 +436,7 @@ module HybridPlatformsConductor
436
436
  {
437
437
  proxmox_test_info[:sync_node] => {
438
438
  remote_bash: {
439
- commands: "#{@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(proxmox_test_info[:sync_node])} -E "}./proxmox/#{cmd}",
439
+ commands: "#{@actions_executor.sudo_prefix(proxmox_test_info[:sync_node], forward_env: true)}./proxmox/#{cmd}",
440
440
  env: {
441
441
  'hpc_user_for_proxmox' => user,
442
442
  'hpc_password_for_proxmox' => password,
@@ -17,7 +17,7 @@ module HybridPlatformsConductor
17
17
  # Flatten the paths rules so that we can spot inconsistencies in configuration
18
18
  @config.aggregate_files_rules(@nodes_handler, @node).map do |path, rule_info|
19
19
  [
20
- "if #{@nodes_handler.sudo_on(@node)} /bin/bash -c '[[ -d \"#{path}\" ]]' ; then echo 1 ; else echo 0 ; fi",
20
+ "if #{@actions_executor.sudo_prefix(@node)}/bin/bash -c '[[ -d \"#{path}\" ]]' ; then echo 1 ; else echo 0 ; fi",
21
21
  {
22
22
  validator: proc do |stdout, stderr|
23
23
  case stdout.last
@@ -12,8 +12,7 @@ module HybridPlatformsConductor
12
12
  # Check my_test_plugin.rb.sample documentation for signature details.
13
13
  def test_on_node
14
14
  {
15
- # TODO: Access the user correctly when the user notion will be moved out of the ssh connector
16
- "#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}hostname -s" => proc do |stdout|
15
+ "#{@actions_executor.sudo_prefix(@node)}hostname -s" => proc do |stdout|
17
16
  assert_equal stdout.first, @node, "Expected hostname to be #{@node}, but got #{stdout.first} instead."
18
17
  end
19
18
  }
@@ -12,8 +12,7 @@ module HybridPlatformsConductor
12
12
  # Check my_test_plugin.rb.sample documentation for signature details.
13
13
  def test_on_node
14
14
  {
15
- # TODO: Access the user correctly when the user notion will be moved out of the ssh connector
16
- "#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}hostname -I" => proc do |stdout|
15
+ "#{@actions_executor.sudo_prefix(@node)}hostname -I" => proc do |stdout|
17
16
  if stdout.first.nil?
18
17
  error 'No IP returned by "hostname -I"'
19
18
  else
@@ -59,8 +59,7 @@ module HybridPlatformsConductor
59
59
  # Check my_test_plugin.rb.sample documentation for signature details.
60
60
  def test_on_node
61
61
  {
62
- # TODO: Access the user correctly when the user notion will be moved out of the ssh connector
63
- "#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}cat /etc/passwd" => proc do |stdout|
62
+ "#{@actions_executor.sudo_prefix(@node)}cat /etc/passwd" => proc do |stdout|
64
63
  passwd_users = stdout.map { |passwd_line| passwd_line.split(':').first }
65
64
  missing_users = @nodes_handler.
66
65
  select_confs_for_node(@node, @config.users_that_should_be_present).
@@ -63,8 +63,7 @@ module HybridPlatformsConductor
63
63
  # Check my_test_plugin.rb.sample documentation for signature details.
64
64
  def test_on_node
65
65
  {
66
- # TODO: Access the user correctly when the user notion will be moved out of the ssh connector
67
- "#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}mount" => proc do |stdout|
66
+ "#{@actions_executor.sudo_prefix(@node)}mount" => proc do |stdout|
68
67
  mounts_info = stdout.map do |line|
69
68
  fields = line.split
70
69
  {
@@ -52,8 +52,7 @@ module HybridPlatformsConductor
52
52
  # Check my_test_plugin.rb.sample documentation for signature details.
53
53
  def test_on_node
54
54
  {
55
- # TODO: Access the user correctly when the user notion will be moved out of the ssh connector
56
- "#{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}/usr/bin/find / \\( #{
55
+ "#{@actions_executor.sudo_prefix(@node)}/usr/bin/find / \\( #{
57
56
  @nodes_handler.
58
57
  select_confs_for_node(@node, @config.ignored_orphan_files_paths).
59
58
  inject(DIRECTORIES_TO_ALWAYS_IGNORE) { |merged_paths, paths_to_ignore_info| merged_paths + paths_to_ignore_info[:ignored_paths] }.
@@ -18,7 +18,7 @@ module HybridPlatformsConductor
18
18
  # Check my_test_plugin.rb.sample documentation for signature details.
19
19
  def test_on_node
20
20
  spectre_cmd = <<~EO_BASH
21
- #{@deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "}/bin/bash <<'EOAction'
21
+ #{@actions_executor.sudo_prefix(@node)}/bin/bash <<'EOAction'
22
22
  #{File.read("#{__dir__}/spectre-meltdown-checker.sh")}
23
23
  EOAction
24
24
  EO_BASH
@@ -56,8 +56,7 @@ module HybridPlatformsConductor
56
56
  current_url
57
57
  end
58
58
  )
59
- # TODO: Access the user correctly when the user notion will be moved out of the ssh connector
60
- sudo = @deployer.instance_variable_get(:@actions_executor).connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(@node)} "
59
+ sudo = @actions_executor.sudo_prefix(@node)
61
60
  urls.map do |url|
62
61
  # 1. Get the OVAL file on the node to be tested (uncompress it if needed)
63
62
  # 2. Make sure oscap is installed
@@ -36,20 +36,34 @@ module HybridPlatformsConductor
36
36
  # Constructor
37
37
  #
38
38
  # Parameters::
39
- # * *logger* (Logger): Logger to be used
40
- # * *logger_stderr* (Logger): Logger to be used for stderr
41
- # * *config* (Config): Config to be used.
42
- # * *cmd_runner* (CmdRunner): CmdRunner that can be used by tests
43
- # * *nodes_handler* (NodesHandler): Nodes handler that can be used by tests
44
- # * *deployer* (Deployer): Deployer that can be used by tests
39
+ # * *logger* (Logger): Logger to be used [default: Logger.new($stdout)]
40
+ # * *logger_stderr* (Logger): Logger to be used for stderr [default: Logger.new($stderr)]
41
+ # * *config* (Config): Config to be used. [default: Config.new]
42
+ # * *cmd_runner* (CmdRunner): Command executor to be used. [default: CmdRunner.new]
43
+ # * *nodes_handler* (NodesHandler): Nodes handler to be used. [default: NodesHandler.new]
44
+ # * *actions_executor* (ActionsExecutor): Actions Executor to be used. [default: ActionsExecutor.new]
45
+ # * *deployer* (Deployer): Deployer that can be used by tests [default: Deployer.new]
45
46
  # * *name* (String): Name of the test being instantiated [default: 'unknown_test']
46
47
  # * *platform* (PlatformHandler): Platform handler for which the test is instantiated, or nil if global or node specific [default: nil]
47
48
  # * *node* (String): Node name for which the test is instantiated, or nil if global or platform specific [default: nil]
48
49
  # * *expected_failure* (String or nil): Expected failure, or nil if not expected to fail [default: nil]
49
- def initialize(logger, logger_stderr, config, cmd_runner, nodes_handler, deployer, name: 'unknown_test', platform: nil, node: nil, expected_failure: nil)
50
+ def initialize(
51
+ logger: Logger.new($stdout),
52
+ logger_stderr: Logger.new($stderr),
53
+ config: Config.new,
54
+ cmd_runner: CmdRunner.new,
55
+ nodes_handler: NodesHandler.new,
56
+ actions_executor: ActionsExecutor.new,
57
+ deployer: Deployer.new,
58
+ name: 'unknown_test',
59
+ platform: nil,
60
+ node: nil,
61
+ expected_failure: nil
62
+ )
50
63
  super(logger: logger, logger_stderr: logger_stderr, config: config)
51
64
  @cmd_runner = cmd_runner
52
65
  @nodes_handler = nodes_handler
66
+ @actions_executor = actions_executor
53
67
  @deployer = deployer
54
68
  @name = name
55
69
  @platform = platform
@@ -274,12 +274,13 @@ module HybridPlatformsConductor
274
274
  # * Test: Corresponding test
275
275
  def new_test(test_name, platform: nil, node: nil, ignore_expected_failure: false)
276
276
  (test_name.nil? ? Test : @tests_plugins[test_name]).new(
277
- @logger,
278
- @logger_stderr,
279
- @config,
280
- @cmd_runner,
281
- @nodes_handler,
282
- @deployer,
277
+ logger: @logger,
278
+ logger_stderr: @logger_stderr,
279
+ config: @config,
280
+ cmd_runner: @cmd_runner,
281
+ nodes_handler: @nodes_handler,
282
+ actions_executor: @actions_executor,
283
+ deployer: @deployer,
283
284
  name: test_name.nil? ? :global : test_name,
284
285
  platform: platform,
285
286
  node: node,
@@ -1,5 +1,5 @@
1
1
  module HybridPlatformsConductor
2
2
 
3
- VERSION = '33.5.0'
3
+ VERSION = '33.5.1'
4
4
 
5
5
  end
@@ -107,6 +107,10 @@ describe HybridPlatformsConductor::ActionsExecutor do
107
107
  it 'copies files remotely with sudo' do
108
108
  with_test_platform_for_remote_testing(
109
109
  expected_cmds: [
110
+ [
111
+ 'whoami',
112
+ proc { [0, 'test_user', ''] }
113
+ ],
110
114
  [
111
115
  'sudo -u root cp -r "/path/to/src.file" "/remote_path/to/dst.dir"',
112
116
  proc { [0, '', ''] }
@@ -117,9 +121,27 @@ describe HybridPlatformsConductor::ActionsExecutor do
117
121
  end
118
122
  end
119
123
 
124
+ it 'copies files remotely with sudo when being root' do
125
+ with_test_platform_for_remote_testing(
126
+ expected_cmds: [
127
+ [
128
+ 'whoami',
129
+ proc { [0, 'root', ''] }
130
+ ]
131
+ ]
132
+ ) do
133
+ expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/remote_path/to/dst.dir')
134
+ test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
135
+ end
136
+ end
137
+
120
138
  it 'copies files remotely with a different sudo' do
121
139
  with_test_platform_for_remote_testing(
122
140
  expected_cmds: [
141
+ [
142
+ 'whoami',
143
+ proc { [0, 'test_user', ''] }
144
+ ],
123
145
  [
124
146
  'other_sudo --user root cp -r "/path/to/src.file" "/remote_path/to/dst.dir"',
125
147
  proc { [0, '', ''] }
@@ -133,6 +155,23 @@ describe HybridPlatformsConductor::ActionsExecutor do
133
155
  end
134
156
  end
135
157
 
158
+ it 'copies files remotely with a different sudo when being root' do
159
+ with_test_platform_for_remote_testing(
160
+ expected_cmds: [
161
+ [
162
+ 'whoami',
163
+ proc { [0, 'root', ''] }
164
+ ]
165
+ ],
166
+ additional_config: <<~'EO_CONFIG'
167
+ sudo_for { |user| "other_sudo --user #{user}" }
168
+ EO_CONFIG
169
+ ) do
170
+ expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/remote_path/to/dst.dir')
171
+ test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
172
+ end
173
+ end
174
+
136
175
  it 'copies files remotely with timeout' do
137
176
  with_test_platform_for_remote_testing(
138
177
  timeout: 5
@@ -152,6 +191,10 @@ describe HybridPlatformsConductor::ActionsExecutor do
152
191
  it 'copies relative files remotely with sudo' do
153
192
  with_test_platform_for_remote_testing(
154
193
  expected_cmds: [
194
+ [
195
+ 'whoami',
196
+ proc { [0, 'test_user', ''] }
197
+ ],
155
198
  [
156
199
  'sudo -u root cp -r "/path/to/src.file" "/tmp/hpc_local_workspaces/node/to/dst.dir"',
157
200
  proc { [0, '', ''] }
@@ -162,9 +205,27 @@ describe HybridPlatformsConductor::ActionsExecutor do
162
205
  end
163
206
  end
164
207
 
208
+ it 'copies relative files remotely with sudo when being root' do
209
+ with_test_platform_for_remote_testing(
210
+ expected_cmds: [
211
+ [
212
+ 'whoami',
213
+ proc { [0, 'root', ''] }
214
+ ]
215
+ ]
216
+ ) do
217
+ expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/tmp/hpc_local_workspaces/node/to/dst.dir')
218
+ test_connector.remote_copy('/path/to/src.file', 'to/dst.dir', sudo: true)
219
+ end
220
+ end
221
+
165
222
  it 'copies relative files remotely with a different sudo' do
166
223
  with_test_platform_for_remote_testing(
167
224
  expected_cmds: [
225
+ [
226
+ 'whoami',
227
+ proc { [0, 'test_user', ''] }
228
+ ],
168
229
  [
169
230
  'other_sudo --user root cp -r "/path/to/src.file" "/tmp/hpc_local_workspaces/node/to/dst.dir"',
170
231
  proc { [0, '', ''] }
@@ -178,6 +239,23 @@ describe HybridPlatformsConductor::ActionsExecutor do
178
239
  end
179
240
  end
180
241
 
242
+ it 'copies relative files remotely with a different sudo when being root' do
243
+ with_test_platform_for_remote_testing(
244
+ expected_cmds: [
245
+ [
246
+ 'whoami',
247
+ proc { [0, 'root', ''] }
248
+ ]
249
+ ],
250
+ additional_config: <<~'EO_CONFIG'
251
+ sudo_for { |user| "other_sudo --user #{user}" }
252
+ EO_CONFIG
253
+ ) do
254
+ expect(FileUtils).to receive(:cp_r).with('/path/to/src.file', '/tmp/hpc_local_workspaces/node/to/dst.dir')
255
+ test_connector.remote_copy('/path/to/src.file', 'to/dst.dir', sudo: true)
256
+ end
257
+ end
258
+
181
259
  end
182
260
 
183
261
  end
@@ -0,0 +1,195 @@
1
+ describe HybridPlatformsConductor::ActionsExecutor do
2
+
3
+ context 'when checking helpers' do
4
+
5
+ it 'gives access to connectors' do
6
+ with_test_platform({}) do
7
+ expect(test_actions_executor.connector(:ssh)).not_to be_nil
8
+ end
9
+ end
10
+
11
+ it 'returns if a user has privileged access on a node' do
12
+ with_test_platform({ nodes: { 'node' => {} } }) do
13
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
14
+ expect(test_actions_executor.privileged_access?('node')).to eq false
15
+ end
16
+ end
17
+
18
+ it 'returns if a user has privileged access on a node when connecting with root' do
19
+ with_test_platform({ nodes: { 'node' => {} } }) do
20
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
21
+ expect(test_actions_executor.privileged_access?('node')).to eq true
22
+ end
23
+ end
24
+
25
+ it 'returns if a user has privileged access on a local node' do
26
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true } } } }) do
27
+ with_cmd_runner_mocked [
28
+ ['whoami', proc { [0, 'test_user', ''] }]
29
+ ] do
30
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
31
+ expect(test_actions_executor.privileged_access?('node')).to eq false
32
+ end
33
+ end
34
+ end
35
+
36
+ it 'returns if a user has privileged access on a local node when local user is root' do
37
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true } } } }) do
38
+ with_cmd_runner_mocked [
39
+ ['whoami', proc { [0, 'root', ''] }]
40
+ ] do
41
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
42
+ expect(test_actions_executor.privileged_access?('node')).to eq true
43
+ end
44
+ end
45
+ end
46
+
47
+ context 'with connection on a remote node' do
48
+
49
+ it 'returns the correct sudo prefix' do
50
+ with_test_platform({ nodes: { 'node' => {} } }) do
51
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
52
+ expect(test_actions_executor.sudo_prefix('node')).to eq 'sudo -u root '
53
+ end
54
+ end
55
+
56
+ it 'returns the correct sudo prefix with env forwarding' do
57
+ with_test_platform({ nodes: { 'node' => {} } }) do
58
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
59
+ expect(test_actions_executor.sudo_prefix('node', forward_env: true)).to eq 'sudo -u root -E '
60
+ end
61
+ end
62
+
63
+ it 'returns the correct sudo prefix when connecting as root' do
64
+ with_test_platform({ nodes: { 'node' => {} } }) do
65
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
66
+ expect(test_actions_executor.sudo_prefix('node')).to eq ''
67
+ end
68
+ end
69
+
70
+ it 'returns the correct sudo prefix with a different sudo' do
71
+ with_test_platform(
72
+ { nodes: { 'node' => {} } },
73
+ additional_config: <<~'EO_CONFIG'
74
+ sudo_for { |user| "other_sudo --user #{user}" }
75
+ EO_CONFIG
76
+ ) do
77
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
78
+ expect(test_actions_executor.sudo_prefix('node')).to eq 'other_sudo --user root '
79
+ end
80
+ end
81
+
82
+ it 'returns the correct sudo prefix with a different sudo and env forwarding' do
83
+ with_test_platform(
84
+ { nodes: { 'node' => {} } },
85
+ additional_config: <<~'EO_CONFIG'
86
+ sudo_for { |user| "other_sudo --user #{user}" }
87
+ EO_CONFIG
88
+ ) do
89
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
90
+ expect(test_actions_executor.sudo_prefix('node', forward_env: true)).to eq 'other_sudo --user root -E '
91
+ end
92
+ end
93
+
94
+ it 'returns the correct sudo prefix with a different sudo when connecting as root' do
95
+ with_test_platform(
96
+ { nodes: { 'node' => {} } },
97
+ additional_config: <<~'EO_CONFIG'
98
+ sudo_for { |user| "other_sudo --user #{user}" }
99
+ EO_CONFIG
100
+ ) do
101
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
102
+ expect(test_actions_executor.sudo_prefix('node')).to eq ''
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ context 'with connection on a local node' do
109
+
110
+ it 'returns the correct sudo prefix' do
111
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true } } } }) do
112
+ with_cmd_runner_mocked [
113
+ ['whoami', proc { [0, 'test_user', ''] }]
114
+ ] do
115
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
116
+ expect(test_actions_executor.sudo_prefix('node')).to eq 'sudo -u root '
117
+ end
118
+ end
119
+ end
120
+
121
+ it 'returns the correct sudo prefix with env forwarding' do
122
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true } } } }) do
123
+ with_cmd_runner_mocked [
124
+ ['whoami', proc { [0, 'test_user', ''] }]
125
+ ] do
126
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
127
+ expect(test_actions_executor.sudo_prefix('node', forward_env: true)).to eq 'sudo -u root -E '
128
+ end
129
+ end
130
+ end
131
+
132
+ it 'returns the correct sudo prefix when connecting as root' do
133
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true } } } }) do
134
+ with_cmd_runner_mocked [
135
+ ['whoami', proc { [0, 'root', ''] }]
136
+ ] do
137
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
138
+ expect(test_actions_executor.sudo_prefix('node')).to eq ''
139
+ end
140
+ end
141
+ end
142
+
143
+ it 'returns the correct sudo prefix with a different sudo' do
144
+ with_test_platform(
145
+ { nodes: { 'node' => { meta: { local_node: true } } } },
146
+ additional_config: <<~'EO_CONFIG'
147
+ sudo_for { |user| "other_sudo --user #{user}" }
148
+ EO_CONFIG
149
+ ) do
150
+ with_cmd_runner_mocked [
151
+ ['whoami', proc { [0, 'test_user', ''] }]
152
+ ] do
153
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
154
+ expect(test_actions_executor.sudo_prefix('node')).to eq 'other_sudo --user root '
155
+ end
156
+ end
157
+ end
158
+
159
+ it 'returns the correct sudo prefix with a different sudo and env forwarding' do
160
+ with_test_platform(
161
+ { nodes: { 'node' => { meta: { local_node: true } } } },
162
+ additional_config: <<~'EO_CONFIG'
163
+ sudo_for { |user| "other_sudo --user #{user}" }
164
+ EO_CONFIG
165
+ ) do
166
+ with_cmd_runner_mocked [
167
+ ['whoami', proc { [0, 'test_user', ''] }]
168
+ ] do
169
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
170
+ expect(test_actions_executor.sudo_prefix('node', forward_env: true)).to eq 'other_sudo --user root -E '
171
+ end
172
+ end
173
+ end
174
+
175
+ it 'returns the correct sudo prefix with a different sudo when connecting as root' do
176
+ with_test_platform(
177
+ { nodes: { 'node' => { meta: { local_node: true } } } },
178
+ additional_config: <<~'EO_CONFIG'
179
+ sudo_for { |user| "other_sudo --user #{user}" }
180
+ EO_CONFIG
181
+ ) do
182
+ with_cmd_runner_mocked [
183
+ ['whoami', proc { [0, 'root', ''] }]
184
+ ] do
185
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
186
+ expect(test_actions_executor.sudo_prefix('node')).to eq ''
187
+ end
188
+ end
189
+ end
190
+
191
+ end
192
+
193
+ end
194
+
195
+ end
@@ -129,6 +129,127 @@ describe HybridPlatformsConductor::Deployer do
129
129
  end
130
130
  end
131
131
 
132
+ it 'returns actions to save logs on a local node' do
133
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true }, services: %w[service1 service2] } } }, additional_config: 'send_logs_to :remote_fs') do
134
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
135
+ expect_services_handler_to_deploy('node' => %w[service1 service2])
136
+ expect_actions_executor_runs [
137
+ # First run, we expect the mutex to be setup, and the deployment actions to be run
138
+ proc do |actions_per_nodes|
139
+ expect_actions_to_deploy_on(
140
+ actions_per_nodes,
141
+ 'node',
142
+ mocked_result: { 'node' => [0, 'Deploy successful stdout', 'Deploy successful stderr'] }
143
+ )
144
+ end,
145
+ # Second run, we expect the mutex to be released
146
+ proc { |actions_per_nodes| expect_actions_to_unlock(actions_per_nodes, 'node') },
147
+ # Third run, we expect logs to be uploaded on the node
148
+ proc do |actions_per_nodes|
149
+ expect(actions_per_nodes['node'].size).to eq 3
150
+ expect(actions_per_nodes['node'][0].keys.sort).to eq %i[ruby remote_bash].sort
151
+ expect(actions_per_nodes['node'][0][:remote_bash]).to eq 'sudo -u root mkdir -p /var/log/deployments && sudo -u root chmod 600 /var/log/deployments'
152
+ expect(actions_per_nodes['node'][1].keys.sort).to eq %i[scp].sort
153
+ expect(actions_per_nodes['node'][1][:scp].delete(:sudo)).to eq true
154
+ expect(actions_per_nodes['node'][1][:scp].delete(:owner)).to eq 'root'
155
+ expect(actions_per_nodes['node'][1][:scp].delete(:group)).to eq 'root'
156
+ expect(actions_per_nodes['node'][1][:scp].size).to eq 1
157
+ tmp_log_file = actions_per_nodes['node'][1][:scp].first[0]
158
+ expect(actions_per_nodes['node'][1][:scp].first[1]).to eq '/var/log/deployments'
159
+ expect(actions_per_nodes['node'][2].keys.sort).to eq %i[ruby remote_bash].sort
160
+ expect(actions_per_nodes['node'][2][:remote_bash]).to eq "sudo -u root chmod 600 /var/log/deployments/#{File.basename(tmp_log_file)}"
161
+ # Call the Ruby codes to be tested
162
+ actions_per_nodes['node'][0][:ruby].call
163
+ expect(File.exist?(tmp_log_file)).to eq true
164
+ file_content_regexp = Regexp.new <<~EOREGEXP
165
+ repo_name_0: platform
166
+ commit_id_0: 123456
167
+ commit_message_0: Test commit for node: service1, service2
168
+ date: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}
169
+ user: test_user
170
+ debug: No
171
+ services: service1, service2
172
+ exit_status: 0
173
+ ===== STDOUT =====
174
+ Deploy successful stdout
175
+ ===== STDERR =====
176
+ Deploy successful stderr
177
+ EOREGEXP
178
+ expect(File.read(tmp_log_file)).to match file_content_regexp
179
+ actions_per_nodes['node'][2][:ruby].call
180
+ # Check temporary log file gets deleted for security reasons
181
+ expect(File.exist?(tmp_log_file)).to eq false
182
+ end
183
+ ]
184
+ with_cmd_runner_mocked [
185
+ ['whoami', proc { [0, 'test_user', ''] }]
186
+ ] do
187
+ expect(test_deployer.deploy_on('node')).to eq('node' => [0, 'Deploy successful stdout', 'Deploy successful stderr'])
188
+ end
189
+ end
190
+ end
191
+
192
+ it 'returns actions to save logs on a local node as root' do
193
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true }, services: %w[service1 service2] } } }, additional_config: 'send_logs_to :remote_fs') do
194
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
195
+ expect_services_handler_to_deploy('node' => %w[service1 service2])
196
+ expect_actions_executor_runs [
197
+ # First run, we expect the mutex to be setup, and the deployment actions to be run
198
+ proc do |actions_per_nodes|
199
+ expect_actions_to_deploy_on(
200
+ actions_per_nodes,
201
+ 'node',
202
+ sudo: nil,
203
+ mocked_result: { 'node' => [0, 'Deploy successful stdout', 'Deploy successful stderr'] }
204
+ )
205
+ end,
206
+ # Second run, we expect the mutex to be released
207
+ proc { |actions_per_nodes| expect_actions_to_unlock(actions_per_nodes, 'node', sudo: nil) },
208
+ # Third run, we expect logs to be uploaded on the node
209
+ proc do |actions_per_nodes|
210
+ expect(actions_per_nodes['node'].size).to eq 3
211
+ expect(actions_per_nodes['node'][0].keys.sort).to eq %i[ruby remote_bash].sort
212
+ expect(actions_per_nodes['node'][0][:remote_bash]).to eq 'mkdir -p /var/log/deployments && chmod 600 /var/log/deployments'
213
+ expect(actions_per_nodes['node'][1].keys.sort).to eq %i[scp].sort
214
+ expect(actions_per_nodes['node'][1][:scp].delete(:sudo)).to eq false
215
+ expect(actions_per_nodes['node'][1][:scp].delete(:owner)).to eq 'root'
216
+ expect(actions_per_nodes['node'][1][:scp].delete(:group)).to eq 'root'
217
+ expect(actions_per_nodes['node'][1][:scp].size).to eq 1
218
+ tmp_log_file = actions_per_nodes['node'][1][:scp].first[0]
219
+ expect(actions_per_nodes['node'][1][:scp].first[1]).to eq '/var/log/deployments'
220
+ expect(actions_per_nodes['node'][2].keys.sort).to eq %i[ruby remote_bash].sort
221
+ expect(actions_per_nodes['node'][2][:remote_bash]).to eq "chmod 600 /var/log/deployments/#{File.basename(tmp_log_file)}"
222
+ # Call the Ruby codes to be tested
223
+ actions_per_nodes['node'][0][:ruby].call
224
+ expect(File.exist?(tmp_log_file)).to eq true
225
+ file_content_regexp = Regexp.new <<~EOREGEXP
226
+ repo_name_0: platform
227
+ commit_id_0: 123456
228
+ commit_message_0: Test commit for node: service1, service2
229
+ date: \\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}
230
+ user: test_user
231
+ debug: No
232
+ services: service1, service2
233
+ exit_status: 0
234
+ ===== STDOUT =====
235
+ Deploy successful stdout
236
+ ===== STDERR =====
237
+ Deploy successful stderr
238
+ EOREGEXP
239
+ expect(File.read(tmp_log_file)).to match file_content_regexp
240
+ actions_per_nodes['node'][2][:ruby].call
241
+ # Check temporary log file gets deleted for security reasons
242
+ expect(File.exist?(tmp_log_file)).to eq false
243
+ end
244
+ ]
245
+ with_cmd_runner_mocked [
246
+ ['whoami', proc { [0, 'root', ''] }]
247
+ ] do
248
+ expect(test_deployer.deploy_on('node')).to eq('node' => [0, 'Deploy successful stdout', 'Deploy successful stderr'])
249
+ end
250
+ end
251
+ end
252
+
132
253
  it 'reads logs' do
133
254
  with_test_platform_for_remote_fs do
134
255
  expect_actions_executor_runs [
@@ -216,6 +337,100 @@ describe HybridPlatformsConductor::Deployer do
216
337
  end
217
338
  end
218
339
 
340
+ it 'reads logs on a local node' do
341
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true }, services: %w[service1 service2] } } }, additional_config: 'send_logs_to :remote_fs') do
342
+ expect_actions_executor_runs [
343
+ # Expect the actions to get log files
344
+ proc do |actions_per_nodes|
345
+ expect(actions_per_nodes).to eq('node' => [{ remote_bash: 'sudo -u root cat /var/log/deployments/`sudo -u root ls -t /var/log/deployments/ | head -1`' }])
346
+ { 'node' => [0, <<~EO_STDOUT, ''] }
347
+ repo_name_0: platform
348
+ commit_id_0: 123456
349
+ commit_message_0: Test commit for node: service1, service2
350
+ diff_files_0: file1, file2, file3
351
+ date: 2017-11-23 18:43:01
352
+ user: test_user
353
+ debug: Yes
354
+ services: service1, service2, service3
355
+ exit_status: 0
356
+ ===== STDOUT =====
357
+ Deploy successful stdout
358
+ ===== STDERR =====
359
+ Deploy successful stderr
360
+ EO_STDOUT
361
+ end
362
+ ]
363
+ with_cmd_runner_mocked [
364
+ ['whoami', proc { [0, 'test_user', ''] }]
365
+ ] do
366
+ expect(test_deployer.deployment_info_from('node')).to eq(
367
+ 'node' => {
368
+ deployment_info: {
369
+ repo_name_0: 'platform',
370
+ commit_id_0: '123456',
371
+ commit_message_0: 'Test commit for node: service1, service2',
372
+ diff_files_0: %w[file1 file2 file3],
373
+ date: Time.parse('2017-11-23 18:43:01 UTC'),
374
+ debug: true,
375
+ user: 'test_user'
376
+ },
377
+ exit_status: 0,
378
+ services: %w[service1 service2 service3],
379
+ stderr: 'Deploy successful stderr',
380
+ stdout: 'Deploy successful stdout'
381
+ }
382
+ )
383
+ end
384
+ end
385
+ end
386
+
387
+ it 'reads logs on a local node as root' do
388
+ with_test_platform({ nodes: { 'node' => { meta: { local_node: true }, services: %w[service1 service2] } } }, additional_config: 'send_logs_to :remote_fs') do
389
+ expect_actions_executor_runs [
390
+ # Expect the actions to get log files
391
+ proc do |actions_per_nodes|
392
+ expect(actions_per_nodes).to eq('node' => [{ remote_bash: 'cat /var/log/deployments/`ls -t /var/log/deployments/ | head -1`' }])
393
+ { 'node' => [0, <<~EO_STDOUT, ''] }
394
+ repo_name_0: platform
395
+ commit_id_0: 123456
396
+ commit_message_0: Test commit for node: service1, service2
397
+ diff_files_0: file1, file2, file3
398
+ date: 2017-11-23 18:43:01
399
+ user: test_user
400
+ debug: Yes
401
+ services: service1, service2, service3
402
+ exit_status: 0
403
+ ===== STDOUT =====
404
+ Deploy successful stdout
405
+ ===== STDERR =====
406
+ Deploy successful stderr
407
+ EO_STDOUT
408
+ end
409
+ ]
410
+ with_cmd_runner_mocked [
411
+ ['whoami', proc { [0, 'root', ''] }]
412
+ ] do
413
+ expect(test_deployer.deployment_info_from('node')).to eq(
414
+ 'node' => {
415
+ deployment_info: {
416
+ repo_name_0: 'platform',
417
+ commit_id_0: '123456',
418
+ commit_message_0: 'Test commit for node: service1, service2',
419
+ diff_files_0: %w[file1 file2 file3],
420
+ date: Time.parse('2017-11-23 18:43:01 UTC'),
421
+ debug: true,
422
+ user: 'test_user'
423
+ },
424
+ exit_status: 0,
425
+ services: %w[service1 service2 service3],
426
+ stderr: 'Deploy successful stderr',
427
+ stdout: 'Deploy successful stdout'
428
+ }
429
+ )
430
+ end
431
+ end
432
+ end
433
+
219
434
  end
220
435
 
221
436
  end
@@ -256,6 +256,44 @@ describe HybridPlatformsConductor::HpcPlugins::PlatformHandler::ServerlessChef d
256
256
 
257
257
  end
258
258
 
259
+ context 'with a platform having 1 local node' do
260
+
261
+ it 'returns actions to deploy on this node' do
262
+ with_serverless_chef_platforms('1_local_node') do |platform, repository|
263
+ mock_package(repository)
264
+ platform.prepare_for_deploy(
265
+ services: { 'node' => %w[test_policy] },
266
+ secrets: {},
267
+ local_environment: false,
268
+ why_run: false
269
+ )
270
+ with_cmd_runner_mocked [
271
+ ['whoami', proc { [0, 'test_user', ''] }]
272
+ ] do
273
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository)
274
+ end
275
+ end
276
+ end
277
+
278
+ it 'returns actions to deploy on this node as root' do
279
+ with_serverless_chef_platforms('1_local_node') do |platform, repository|
280
+ mock_package(repository)
281
+ platform.prepare_for_deploy(
282
+ services: { 'node' => %w[test_policy] },
283
+ secrets: {},
284
+ local_environment: false,
285
+ why_run: false
286
+ )
287
+ with_cmd_runner_mocked [
288
+ ['whoami', proc { [0, 'root', ''] }]
289
+ ] do
290
+ expect(platform.actions_to_deploy_on('node', 'test_policy', use_why_run: false)).to eq expected_actions_to_deploy_chef(repository, sudo: '')
291
+ end
292
+ end
293
+ end
294
+
295
+ end
296
+
259
297
  context 'with a platform having several nodes' do
260
298
 
261
299
  it 'deploys services declared on 1 node on another node if asked' do
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "node",
3
+ "normal": {
4
+ "description": "Single test node",
5
+ "image": "debian_9",
6
+ "private_ips": ["172.16.0.1"],
7
+ "local_node": true,
8
+ "property_1": {
9
+ "property_11": "value11"
10
+ },
11
+ "property_2": "value2"
12
+ },
13
+ "policy_name": "test_policy",
14
+ "policy_group": "test_group"
15
+ }
@@ -0,0 +1,3 @@
1
+ name File.basename(__FILE__, '.rb')
2
+ default_source :supermarket
3
+ run_list 'recipe[test_cookbook]'
@@ -46,6 +46,30 @@ shared_examples 'a deployer' do
46
46
  end
47
47
  end
48
48
 
49
+ it 'deploys on 1 local node' do
50
+ with_platform_to_deploy(nodes_info: { nodes: { 'node' => { meta: { local_node: true }, services: %w[service] } } }) do
51
+ # Make sure the ssh_user is ignored in this case
52
+ test_actions_executor.connector(:ssh).ssh_user = 'root'
53
+ with_cmd_runner_mocked [
54
+ ['whoami', proc { [0, 'test_user', ''] }]
55
+ ] do
56
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
57
+ end
58
+ end
59
+ end
60
+
61
+ it 'deploys on 1 local node as root' do
62
+ with_platform_to_deploy(nodes_info: { nodes: { 'node' => { meta: { local_node: true }, services: %w[service] } } }, expect_sudo: nil) do
63
+ # Make sure the ssh_user is ignored in this case
64
+ test_actions_executor.connector(:ssh).ssh_user = 'test_user'
65
+ with_cmd_runner_mocked [
66
+ ['whoami', proc { [0, 'root', ''] }]
67
+ ] do
68
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
69
+ end
70
+ end
71
+ end
72
+
49
73
  it 'deploys on 1 node using 1 secret' do
50
74
  with_platform_to_deploy(expect_secrets: { 'secret1' => 'password1' }) do
51
75
  test_deployer.override_secrets('secret1' => 'password1')
@@ -137,6 +161,61 @@ shared_examples 'a deployer' do
137
161
  end
138
162
  end
139
163
 
164
+ it 'deploys on 1 local node in local environment with certificates to install using hpc_certificates on Debian' do
165
+ with_certs_dir do |certs_dir|
166
+ with_platform_to_deploy(
167
+ nodes_info: { nodes: { 'node' => { meta: { local_node: true, image: 'debian_9' }, services: %w[service] } } },
168
+ expect_local_environment: true,
169
+ expect_additional_actions: [
170
+ { remote_bash: 'sudo -u root apt update && sudo -u root apt install -y ca-certificates' },
171
+ {
172
+ remote_bash: 'sudo -u root update-ca-certificates',
173
+ scp: {
174
+ certs_dir => '/usr/local/share/ca-certificates',
175
+ :sudo => true
176
+ }
177
+ }
178
+ ]
179
+ ) do
180
+ ENV['hpc_certificates'] = certs_dir
181
+ test_deployer.local_environment = true
182
+ with_cmd_runner_mocked [
183
+ ['whoami', proc { [0, 'test_user', ''] }]
184
+ ] do
185
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
186
+ end
187
+ end
188
+ end
189
+ end
190
+
191
+ it 'deploys on 1 local node in local environment with certificates to install using hpc_certificates on Debian as root' do
192
+ with_certs_dir do |certs_dir|
193
+ with_platform_to_deploy(
194
+ nodes_info: { nodes: { 'node' => { meta: { local_node: true, image: 'debian_9' }, services: %w[service] } } },
195
+ expect_sudo: nil,
196
+ expect_local_environment: true,
197
+ expect_additional_actions: [
198
+ { remote_bash: 'apt update && apt install -y ca-certificates' },
199
+ {
200
+ remote_bash: 'update-ca-certificates',
201
+ scp: {
202
+ certs_dir => '/usr/local/share/ca-certificates',
203
+ :sudo => false
204
+ }
205
+ }
206
+ ]
207
+ ) do
208
+ ENV['hpc_certificates'] = certs_dir
209
+ test_deployer.local_environment = true
210
+ with_cmd_runner_mocked [
211
+ ['whoami', proc { [0, 'root', ''] }]
212
+ ] do
213
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
214
+ end
215
+ end
216
+ end
217
+ end
218
+
140
219
  it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS' do
141
220
  with_certs_dir do |certs_dir|
142
221
  with_platform_to_deploy(
@@ -212,6 +291,61 @@ shared_examples 'a deployer' do
212
291
  end
213
292
  end
214
293
 
294
+ it 'deploys on 1 local node with certificates to install using hpc_certificates on CentOS' do
295
+ with_certs_dir do |certs_dir|
296
+ with_platform_to_deploy(
297
+ nodes_info: { nodes: { 'node' => { meta: { local_node: true, image: 'centos_7' }, services: %w[service] } } },
298
+ expect_local_environment: true,
299
+ expect_additional_actions: [
300
+ { remote_bash: 'sudo -u root yum install -y ca-certificates' },
301
+ {
302
+ remote_bash: ['sudo -u root update-ca-trust enable', 'sudo -u root update-ca-trust extract'],
303
+ scp: {
304
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
305
+ :sudo => true
306
+ }
307
+ }
308
+ ]
309
+ ) do
310
+ ENV['hpc_certificates'] = certs_dir
311
+ test_deployer.local_environment = true
312
+ with_cmd_runner_mocked [
313
+ ['whoami', proc { [0, 'test_user', ''] }]
314
+ ] do
315
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
316
+ end
317
+ end
318
+ end
319
+ end
320
+
321
+ it 'deploys on 1 local node with certificates to install using hpc_certificates on CentOS as root' do
322
+ with_certs_dir do |certs_dir|
323
+ with_platform_to_deploy(
324
+ nodes_info: { nodes: { 'node' => { meta: { local_node: true, image: 'centos_7' }, services: %w[service] } } },
325
+ expect_sudo: nil,
326
+ expect_local_environment: true,
327
+ expect_additional_actions: [
328
+ { remote_bash: 'yum install -y ca-certificates' },
329
+ {
330
+ remote_bash: ['update-ca-trust enable', 'update-ca-trust extract'],
331
+ scp: {
332
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
333
+ :sudo => false
334
+ }
335
+ }
336
+ ]
337
+ ) do
338
+ ENV['hpc_certificates'] = certs_dir
339
+ test_deployer.local_environment = true
340
+ with_cmd_runner_mocked [
341
+ ['whoami', proc { [0, 'root', ''] }]
342
+ ] do
343
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
344
+ end
345
+ end
346
+ end
347
+ end
348
+
215
349
  it 'deploys on several nodes' do
216
350
  with_platform_to_deploy(
217
351
  nodes_info: {
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hybrid_platforms_conductor
3
3
  version: !ruby/object:Gem::Version
4
- version: 33.5.0
4
+ version: 33.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Muriel Salvan
@@ -866,6 +866,7 @@ files:
866
866
  - spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/global_helpers_spec.rb
867
867
  - spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/node_helpers_spec.rb
868
868
  - spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb
869
+ - spec/hybrid_platforms_conductor_test/api/actions_executor/helpers_spec.rb
869
870
  - spec/hybrid_platforms_conductor_test/api/actions_executor/logging_spec.rb
870
871
  - spec/hybrid_platforms_conductor_test/api/actions_executor/parallel_spec.rb
871
872
  - spec/hybrid_platforms_conductor_test/api/actions_executor/timeout_spec.rb
@@ -982,6 +983,9 @@ files:
982
983
  - spec/hybrid_platforms_conductor_test/platform_handler_plugins/test_2.rb
983
984
  - spec/hybrid_platforms_conductor_test/report_plugin.rb
984
985
  - spec/hybrid_platforms_conductor_test/rubocop_spec.rb
986
+ - spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/chef_versions.yml
987
+ - spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/nodes/node.json
988
+ - spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_local_node/policyfiles/test_policy.rb
985
989
  - spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/chef_versions.yml
986
990
  - spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/nodes/node.json
987
991
  - spec/hybrid_platforms_conductor_test/serverless_chef_repositories/1_node/policyfiles/test_policy.rb