hybrid_platforms_conductor 32.4.2 → 32.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (23) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hybrid_platforms_conductor/deployer.rb +9 -8
  3. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +1 -1
  4. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +1 -1
  5. data/lib/hybrid_platforms_conductor/hpc_plugins/test/deploy_freshness.rb +1 -1
  6. data/lib/hybrid_platforms_conductor/hpc_plugins/test/file_system.rb +1 -1
  7. data/lib/hybrid_platforms_conductor/hpc_plugins/test/hostname.rb +1 -1
  8. data/lib/hybrid_platforms_conductor/hpc_plugins/test/ip.rb +1 -1
  9. data/lib/hybrid_platforms_conductor/hpc_plugins/test/local_users.rb +1 -1
  10. data/lib/hybrid_platforms_conductor/hpc_plugins/test/mounts.rb +1 -1
  11. data/lib/hybrid_platforms_conductor/hpc_plugins/test/orphan_files.rb +1 -1
  12. data/lib/hybrid_platforms_conductor/hpc_plugins/test/spectre.rb +6 -7
  13. data/lib/hybrid_platforms_conductor/hpc_plugins/test/vulnerabilities.rb +7 -6
  14. data/lib/hybrid_platforms_conductor/nodes_handler.rb +37 -0
  15. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  16. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +15 -1
  17. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb +28 -0
  18. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/config_spec.rb +71 -0
  19. data/spec/hybrid_platforms_conductor_test/helpers/connector_ssh_helpers.rb +10 -2
  20. data/spec/hybrid_platforms_conductor_test/helpers/deployer_helpers.rb +14 -14
  21. data/spec/hybrid_platforms_conductor_test/helpers/deployer_test_helpers.rb +70 -11
  22. data/spec/hybrid_platforms_conductor_test/helpers/provisioner_proxmox_helpers.rb +2 -2
  23. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 544df1af20b12202d76519a9ebb2a7ea824e676fca1d04af0b546baa759d97ae
4
- data.tar.gz: 19aa74c8d6f634d1b8618ba5b701c2b4dfb4457db8f69b2db84a8f08563bc891
3
+ metadata.gz: 834a3af157221b88e6a150738b146f90fdf832c43fe5e8471619879c47a22d5b
4
+ data.tar.gz: c4f54b879fbfba923fda2a8aee1b299cb846ed9478ca9bd81535f220ec622f69
5
5
  SHA512:
6
- metadata.gz: c7aeb4324286b216d36b0b3f205af58dd3a92d1655d74d05275de1c911cf0137198dda7e3c23d226e0b0a5c0b127eeef4e79a22bc1f585d4058cb2f31abfc09f
7
- data.tar.gz: 84493300be870ee61c7f154b92eee7b27cbcbcd8af7c7fe4cbeed0f853c982e00587aa6294230552a2526bd57e76716a7b8d157097ce33c254d6f2206a9c3fa9
6
+ metadata.gz: 42ae65da627c812b096c0e9f9b4bb8c9ac4dde3185e1f6cf8d1405acbab960d5c5c88050c25e3d45906acb6054c73fd7ec29b2e5751b1ec38734f83a33f34bef
7
+ data.tar.gz: 41e641381b34d9d0841770974c4401612bfc3a4d11a5ec2fe85969f40ab1bfce0952cb4bbf5b7d2fce5420d9090a4962e278b9fb84d4251e0f13ee84db405e6c
@@ -480,6 +480,7 @@ module HybridPlatformsConductor
480
480
  outputs = @actions_executor.execute_actions(
481
481
  Hash[services.map do |node, node_services|
482
482
  image_id = @nodes_handler.get_image_of(node)
483
+ sudo = (ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} ")
483
484
  # Install My_company corporate certificates if present
484
485
  certificate_actions =
485
486
  if @local_environment && ENV['hpc_certificates']
@@ -489,20 +490,20 @@ module HybridPlatformsConductor
489
490
  when 'debian_9', 'debian_10'
490
491
  [
491
492
  {
492
- remote_bash: "#{ssh_user == 'root' ? '' : 'sudo '}apt update && #{ssh_user == 'root' ? '' : 'sudo '}apt install -y ca-certificates"
493
+ remote_bash: "#{sudo}apt update && #{sudo}apt install -y ca-certificates"
493
494
  },
494
495
  {
495
496
  scp: {
496
497
  ENV['hpc_certificates'] => '/usr/local/share/ca-certificates',
497
498
  :sudo => ssh_user != 'root'
498
499
  },
499
- remote_bash: "#{ssh_user == 'root' ? '' : 'sudo '}update-ca-certificates"
500
+ remote_bash: "#{sudo}update-ca-certificates"
500
501
  }
501
502
  ]
502
503
  when 'centos_7'
503
504
  [
504
505
  {
505
- remote_bash: "#{ssh_user == 'root' ? '' : 'sudo '}yum install -y ca-certificates"
506
+ remote_bash: "#{sudo}yum install -y ca-certificates"
506
507
  },
507
508
  {
508
509
  scp: Hash[Dir.glob("#{ENV['hpc_certificates']}/*.crt").map do |cert_file|
@@ -512,8 +513,8 @@ module HybridPlatformsConductor
512
513
  ]
513
514
  end].merge(sudo: ssh_user != 'root'),
514
515
  remote_bash: [
515
- "#{ssh_user == 'root' ? '' : 'sudo '}update-ca-trust enable",
516
- "#{ssh_user == 'root' ? '' : 'sudo '}update-ca-trust extract"
516
+ "#{sudo}update-ca-trust enable",
517
+ "#{sudo}update-ca-trust extract"
517
518
  ]
518
519
  }
519
520
  ]
@@ -532,7 +533,7 @@ module HybridPlatformsConductor
532
533
  # Install the mutex lock and acquire it
533
534
  {
534
535
  scp: { "#{__dir__}/mutex_dir" => '.' },
535
- remote_bash: "while ! #{ssh_user == 'root' ? '' : 'sudo '}./mutex_dir lock /tmp/hybrid_platforms_conductor_deploy_lock \"$(ps -o ppid= -p $$)\"; do echo -e 'Another deployment is running on #{node}. Waiting for it to finish to continue...' ; sleep 5 ; done"
536
+ remote_bash: "while ! #{sudo}./mutex_dir lock /tmp/hybrid_platforms_conductor_deploy_lock \"$(ps -o ppid= -p $$)\"; do echo -e 'Another deployment is running on #{node}. Waiting for it to finish to continue...' ; sleep 5 ; done"
536
537
  }
537
538
  ] +
538
539
  certificate_actions +
@@ -548,7 +549,7 @@ module HybridPlatformsConductor
548
549
  Hash[services.keys.map do |node|
549
550
  [
550
551
  node,
551
- { remote_bash: "#{ssh_user == 'root' ? '' : 'sudo '}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock" }
552
+ { remote_bash: "#{ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock" }
552
553
  ]
553
554
  end],
554
555
  timeout: 10,
@@ -595,7 +596,7 @@ module HybridPlatformsConductor
595
596
  [
596
597
  node,
597
598
  {
598
- remote_bash: "#{ssh_user == 'root' ? '' : 'sudo '}mkdir -p /var/log/deployments",
599
+ remote_bash: "#{ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} "}mkdir -p /var/log/deployments",
599
600
  scp: {
600
601
  log_file => '/var/log/deployments',
601
602
  :sudo => ssh_user != 'root',
@@ -272,7 +272,7 @@ module HybridPlatformsConductor
272
272
  #{File.basename(from)} | \
273
273
  #{ssh_exec} \
274
274
  #{ssh_url} \
275
- \"#{sudo ? 'sudo ' : ''}tar \
275
+ \"#{sudo ? "#{@nodes_handler.sudo_on(@node)} " : ''}tar \
276
276
  --extract \
277
277
  --gunzip \
278
278
  --file - \
@@ -404,7 +404,7 @@ module HybridPlatformsConductor
404
404
  {
405
405
  proxmox_test_info[:sync_node] => {
406
406
  remote_bash: {
407
- commands: "#{@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : 'sudo -E '}./proxmox/#{cmd}",
407
+ commands: "#{@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(proxmox_test_info[:sync_node])} -E "}./proxmox/#{cmd}",
408
408
  env: {
409
409
  'hpc_user_for_proxmox' => user,
410
410
  'hpc_password_for_proxmox' => password,
@@ -15,7 +15,7 @@ module HybridPlatformsConductor
15
15
  def test_on_node
16
16
  now = Time.now
17
17
  {
18
- 'sudo ls -t /var/log/deployments' => proc do |stdout|
18
+ "#{@nodes_handler.sudo_on(@node)} ls -t /var/log/deployments" => proc do |stdout|
19
19
  if stdout.empty?
20
20
  error 'Node has never been deployed using deploy (/var/log/deployments is empty)'
21
21
  elsif stdout.first =~ /No such file or directory/
@@ -17,7 +17,7 @@ module HybridPlatformsConductor
17
17
  Hash[
18
18
  @config.aggregate_files_rules(@nodes_handler, @node).map do |path, rule_info|
19
19
  [
20
- "if sudo /bin/bash -c '[[ -d \"#{path}\" ]]' ; then echo 1 ; else echo 0 ; fi",
20
+ "if #{@nodes_handler.sudo_on(@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
@@ -10,7 +10,7 @@ module HybridPlatformsConductor
10
10
  # Check my_test_plugin.rb.sample documentation for signature details.
11
11
  def test_on_node
12
12
  {
13
- 'sudo hostname -s' => proc do |stdout|
13
+ "#{@nodes_handler.sudo_on(@node)} hostname -s" => proc do |stdout|
14
14
  assert_equal stdout.first, @node, "Expected hostname to be #{@node}, but got #{stdout.first} instead."
15
15
  end
16
16
  }
@@ -10,7 +10,7 @@ module HybridPlatformsConductor
10
10
  # Check my_test_plugin.rb.sample documentation for signature details.
11
11
  def test_on_node
12
12
  {
13
- 'sudo hostname -I' => proc do |stdout|
13
+ "#{@nodes_handler.sudo_on(@node)} hostname -I" => proc do |stdout|
14
14
  if stdout.first.nil?
15
15
  error 'No IP returned by "hostname -I"'
16
16
  else
@@ -57,7 +57,7 @@ module HybridPlatformsConductor
57
57
  # Check my_test_plugin.rb.sample documentation for signature details.
58
58
  def test_on_node
59
59
  {
60
- "sudo cat /etc/passwd" => proc do |stdout|
60
+ "#{@nodes_handler.sudo_on(@node)} cat /etc/passwd" => proc do |stdout|
61
61
  passwd_users = stdout.map { |passwd_line| passwd_line.split(':').first }
62
62
  missing_users = @nodes_handler.
63
63
  select_confs_for_node(@node, @config.users_that_should_be_present).
@@ -61,7 +61,7 @@ module HybridPlatformsConductor
61
61
  # Check my_test_plugin.rb.sample documentation for signature details.
62
62
  def test_on_node
63
63
  {
64
- 'sudo mount' => proc do |stdout|
64
+ "#{@nodes_handler.sudo_on(@node)} mount" => proc do |stdout|
65
65
  mounts_info = stdout.map do |line|
66
66
  fields = line.split
67
67
  {
@@ -50,7 +50,7 @@ module HybridPlatformsConductor
50
50
  # Check my_test_plugin.rb.sample documentation for signature details.
51
51
  def test_on_node
52
52
  {
53
- "sudo /usr/bin/find / \\( #{@nodes_handler.
53
+ "#{@nodes_handler.sudo_on(@node)} /usr/bin/find / \\( #{@nodes_handler.
54
54
  select_confs_for_node(@node, @config.ignored_orphan_files_paths).
55
55
  inject(DIRECTORIES_TO_ALWAYS_IGNORE) { |merged_paths, paths_to_ignore_info| merged_paths + paths_to_ignore_info[:ignored_paths] }.
56
56
  uniq.
@@ -13,16 +13,15 @@ module HybridPlatformsConductor
13
13
  'CVE-2017-5754' => 'Meltdown'
14
14
  }
15
15
 
16
- SPECTRE_CMD = <<~EOS
17
- sudo /bin/bash <<'EOAction'
18
- #{File.read("#{__dir__}/spectre-meltdown-checker.sh")}
19
- EOAction
20
- EOS
21
-
22
16
  # Check my_test_plugin.rb.sample documentation for signature details.
23
17
  def test_on_node
18
+ spectre_cmd = <<~EOS
19
+ #{@nodes_handler.sudo_on(@node)} /bin/bash <<'EOAction'
20
+ #{File.read("#{__dir__}/spectre-meltdown-checker.sh")}
21
+ EOAction
22
+ EOS
24
23
  {
25
- SPECTRE_CMD => {
24
+ spectre_cmd => {
26
25
  validator: proc do |stdout|
27
26
  VULNERABILITIES_TO_CHECK.each do |id, name|
28
27
  id_regexp = /#{Regexp.escape(id)}/
@@ -54,6 +54,7 @@ module HybridPlatformsConductor
54
54
  current_url
55
55
  end
56
56
  )
57
+ sudo = @nodes_handler.sudo_on(@node)
57
58
  Hash[urls.map do |url|
58
59
  # 1. Get the OVAL file on the node to be tested (uncompress it if needed)
59
60
  # 2. Make sure oscap is installed
@@ -74,9 +75,9 @@ module HybridPlatformsConductor
74
75
  #{
75
76
  case image
76
77
  when :centos_7
77
- "sudo yum install -y wget openscap-scanner #{packages_to_install.join(' ')}"
78
+ "#{sudo} yum install -y wget openscap-scanner #{packages_to_install.join(' ')}"
78
79
  when :debian_9
79
- "sudo apt install -y wget libopenscap8 #{packages_to_install.join(' ')}"
80
+ "#{sudo} apt install -y wget libopenscap8 #{packages_to_install.join(' ')}"
80
81
  when :debian_10
81
82
  # On Debian 10 we have to compile it from sources, as the packaged official version has core dumps.
82
83
  # cf https://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg1688223.html
@@ -86,13 +87,13 @@ module HybridPlatformsConductor
86
87
  rm -rf openscap
87
88
  git clone --recurse-submodules https://github.com/OpenSCAP/openscap.git
88
89
  cd openscap
89
- sudo apt install -y cmake libdbus-1-dev libdbus-glib-1-dev libcurl4-openssl-dev libgcrypt20-dev libselinux1-dev libxslt1-dev libgconf2-dev libacl1-dev libblkid-dev libcap-dev libxml2-dev libldap2-dev libpcre3-dev python-dev swig libxml-parser-perl libxml-xpath-perl libperl-dev libbz2-dev librpm-dev g++ libapt-pkg-dev libyaml-dev
90
+ #{sudo} apt install -y cmake libdbus-1-dev libdbus-glib-1-dev libcurl4-openssl-dev libgcrypt20-dev libselinux1-dev libxslt1-dev libgconf2-dev libacl1-dev libblkid-dev libcap-dev libxml2-dev libldap2-dev libpcre3-dev python-dev swig libxml-parser-perl libxml-xpath-perl libperl-dev libbz2-dev librpm-dev g++ libapt-pkg-dev libyaml-dev
90
91
  cd build
91
92
  cmake ../
92
93
  make
93
- sudo make install
94
+ #{sudo} make install
94
95
  fi
95
- sudo apt install -y wget #{packages_to_install.join(' ')}
96
+ #{sudo} apt install -y wget #{packages_to_install.join(' ')}
96
97
  EOS2
97
98
  else
98
99
  raise "Non supported image: #{image}. Please adapt this test's code."
@@ -103,7 +104,7 @@ module HybridPlatformsConductor
103
104
  cd hpc_vulnerabilities_test
104
105
  wget -N #{url}
105
106
  #{uncompress_cmds.join("\n")}
106
- sudo oscap oval eval --skip-valid --results "#{local_oval_file}.results.xml" "#{local_oval_file}"
107
+ #{sudo} oscap oval eval --skip-valid --results "#{local_oval_file}.results.xml" "#{local_oval_file}"
107
108
  echo "===== RESULTS ====="
108
109
  cat "#{local_oval_file}.results.xml"
109
110
  cd ..
@@ -18,9 +18,20 @@ module HybridPlatformsConductor
18
18
  # Array< Hash<Symbol, Object> >
19
19
  attr_reader :cmdb_masters
20
20
 
21
+ # List of sudo methods. Each info has the following properties:
22
+ # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
23
+ # * *sudo_proc* (Proc): Code giving the sudo line for a given user
24
+ # Parameters::
25
+ # * *user* (String): User for which we want sudo
26
+ # Result::
27
+ # * String: Corresponding sudo string
28
+ # Array< Hash<Symbol, Object> >
29
+ attr_reader :sudo_procs
30
+
21
31
  # Mixin initializer
22
32
  def init_nodes_handler_config
23
33
  @cmdb_masters = []
34
+ @sudo_procs = []
24
35
  end
25
36
 
26
37
  # Set CMDB masters
@@ -34,6 +45,17 @@ module HybridPlatformsConductor
34
45
  }
35
46
  end
36
47
 
48
+ # Set a sudo proc
49
+ #
50
+ # Parameters::
51
+ # * *sudo_proc* (Proc): The sudo proc (see #sudo_procs doc to know the signature)
52
+ def sudo_for(&sudo_proc)
53
+ @sudo_procs << {
54
+ nodes_selectors_stack: current_nodes_selectors_stack,
55
+ sudo_proc: sudo_proc
56
+ }
57
+ end
58
+
37
59
  end
38
60
 
39
61
  Config.extend_config_dsl_with ConfigDSLExtension, :init_nodes_handler_config
@@ -568,6 +590,21 @@ module HybridPlatformsConductor
568
590
  nodes_selector_stack.inject(known_nodes) { |selected_nodes, nodes_selector| selected_nodes & select_nodes(nodes_selector) }
569
591
  end
570
592
 
593
+ # Get the sudo command for a given user on a given node
594
+ #
595
+ # Parameters::
596
+ # * *node* (String): Node on which we need sudo
597
+ # * *user* (String): User for which we need sudo [default = 'root']
598
+ # Result::
599
+ # * String: The corresponding sudo string
600
+ def sudo_on(node, user = 'root')
601
+ sudo = nil
602
+ select_confs_for_node(node, @config.sudo_procs).each do |sudo_proc_info|
603
+ sudo = sudo_proc_info[:sudo_proc].call(user)
604
+ end
605
+ sudo.nil? ? "sudo -u #{user}" : sudo
606
+ end
607
+
571
608
  private
572
609
 
573
610
  # Get the CMDB master for a given property.
@@ -1,5 +1,5 @@
1
1
  module HybridPlatformsConductor
2
2
 
3
- VERSION = '32.4.2'
3
+ VERSION = '32.5.0'
4
4
 
5
5
  end
@@ -92,7 +92,7 @@ describe HybridPlatformsConductor::ActionsExecutor do
92
92
  with_test_platform_for_remote_testing(
93
93
  expected_cmds: [
94
94
  [
95
- /cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+test_user@hpc\.node\s+"sudo tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
95
+ /cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+test_user@hpc\.node\s+"sudo -u root tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
96
96
  proc { [0, '', ''] }
97
97
  ]
98
98
  ]
@@ -101,6 +101,20 @@ describe HybridPlatformsConductor::ActionsExecutor do
101
101
  end
102
102
  end
103
103
 
104
+ it 'copies files remotely with a different sudo' do
105
+ with_test_platform_for_remote_testing(
106
+ expected_cmds: [
107
+ [
108
+ /cd \/path\/to && tar\s+--create\s+--gzip\s+--file -\s+src.file \| \/.+\/ssh\s+test_user@hpc\.node\s+"other_sudo --user root tar\s+--extract\s+--gunzip\s+--file -\s+--directory \/remote_path\/to\/dst.dir\s+--owner root\s+"/,
109
+ proc { [0, '', ''] }
110
+ ]
111
+ ],
112
+ additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
113
+ ) do
114
+ test_connector.remote_copy('/path/to/src.file', '/remote_path/to/dst.dir', sudo: true)
115
+ end
116
+ end
117
+
104
118
  it 'copies files remotely with a different owner' do
105
119
  with_test_platform_for_remote_testing(
106
120
  expected_cmds: [
@@ -124,4 +124,32 @@ describe HybridPlatformsConductor::NodesHandler do
124
124
  end
125
125
  end
126
126
 
127
+ it 'computes the correct sudo for different nodes' do
128
+ with_test_platform(
129
+ {
130
+ nodes: {
131
+ 'node1' => {},
132
+ 'node2' => {},
133
+ 'node3' => {}
134
+ }
135
+ },
136
+ false,
137
+ '
138
+ for_nodes(%w[node1 node2]) do
139
+ sudo_for { |user| "alt_sudo1 -p #{user}" }
140
+ end
141
+ for_nodes(\'node2\') do
142
+ sudo_for { |user| "alt_sudo2 -q #{user}" }
143
+ end
144
+ '
145
+ ) do
146
+ expect(test_nodes_handler.sudo_on('node1')).to eq 'alt_sudo1 -p root'
147
+ expect(test_nodes_handler.sudo_on('node1', 'test_user')).to eq 'alt_sudo1 -p test_user'
148
+ expect(test_nodes_handler.sudo_on('node2')).to eq 'alt_sudo2 -q root'
149
+ expect(test_nodes_handler.sudo_on('node2', 'test_user')).to eq 'alt_sudo2 -q test_user'
150
+ expect(test_nodes_handler.sudo_on('node3')).to eq 'sudo -u root'
151
+ expect(test_nodes_handler.sudo_on('node3', 'test_user')).to eq 'sudo -u test_user'
152
+ end
153
+ end
154
+
127
155
  end
@@ -0,0 +1,71 @@
1
+ describe HybridPlatformsConductor::NodesHandler do
2
+
3
+ context 'checking config DSL' do
4
+
5
+ it 'adds helpers for master cmdbs' do
6
+ with_test_platform(
7
+ {
8
+ nodes: {
9
+ 'node1' => {},
10
+ 'node2' => {},
11
+ 'node3' => {}
12
+ }
13
+ },
14
+ false,
15
+ '
16
+ master_cmdbs(
17
+ test_cmdb: :property1,
18
+ test_cmdb2: :property2
19
+ )
20
+ for_nodes(\'node2\') do
21
+ master_cmdbs(test_cmdb: :property3)
22
+ end
23
+ '
24
+ ) do
25
+ register_test_cmdb(%i[test_cmdb test_cmdb2])
26
+ expect(test_config.cmdb_masters).to eq [
27
+ {
28
+ nodes_selectors_stack: [],
29
+ cmdb_masters: {
30
+ test_cmdb: [:property1],
31
+ test_cmdb2: [:property2]
32
+ }
33
+ },
34
+ {
35
+ nodes_selectors_stack: ['node2'],
36
+ cmdb_masters: {
37
+ test_cmdb: [:property3]
38
+ }
39
+ }
40
+ ]
41
+ end
42
+ end
43
+
44
+ it 'adds helpers for configurable sudo' do
45
+ with_test_platform(
46
+ {
47
+ nodes: {
48
+ 'node1' => {},
49
+ 'node2' => {},
50
+ 'node3' => {}
51
+ }
52
+ },
53
+ false,
54
+ '
55
+ sudo_for { |user| "alt_sudo1 -p #{user}" }
56
+ for_nodes(\'node2\') do
57
+ sudo_for { |user| "alt_sudo2 -q #{user}" }
58
+ end
59
+ '
60
+ ) do
61
+ expect(test_config.sudo_procs.size).to eq 2
62
+ expect(test_config.sudo_procs[0][:nodes_selectors_stack]). to eq []
63
+ expect(test_config.sudo_procs[0][:sudo_proc].call('test_user')). to eq 'alt_sudo1 -p test_user'
64
+ expect(test_config.sudo_procs[1][:nodes_selectors_stack]). to eq ['node2']
65
+ expect(test_config.sudo_procs[1][:sudo_proc].call('test_user')). to eq 'alt_sudo2 -q test_user'
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -94,9 +94,17 @@ module HybridPlatformsConductorTest
94
94
  # * *expected_stderr* (String): Expected stderr after client code execution [default: '']
95
95
  # * *timeout* (Integer or nil): Timeout to prepare the connector for [default: nil]
96
96
  # * *password* (String or nil): Password to set for the node, or nil for none [default: nil]
97
+ # * *additional_config* (String): Additional config [default: '']
97
98
  # * Proc: Client code to execute testing
98
- def with_test_platform_for_remote_testing(expected_cmds: [], expected_stdout: '', expected_stderr: '', timeout: nil, password: nil)
99
- with_test_platform(nodes: { 'node' => { meta: { host_ip: '192.168.42.42' } } }) do
99
+ def with_test_platform_for_remote_testing(
100
+ expected_cmds: [],
101
+ expected_stdout: '',
102
+ expected_stderr: '',
103
+ timeout: nil,
104
+ password: nil,
105
+ additional_config: ''
106
+ )
107
+ with_test_platform({ nodes: { 'node' => { meta: { host_ip: '192.168.42.42' } } } }, false, additional_config) do
100
108
  with_cmd_runner_mocked(
101
109
  [
102
110
  ['which env', proc { [0, "/usr/bin/env\n", ''] }],
@@ -9,12 +9,12 @@ module HybridPlatformsConductorTest
9
9
  # Parameters::
10
10
  # * *action* (Hash<Symbol,Object>): The action to check
11
11
  # * *node* (String): The concerned node
12
- # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
13
- def expect_action_to_lock_node(action, node, sudo: true)
12
+ # * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
13
+ def expect_action_to_lock_node(action, node, sudo: 'sudo -u root')
14
14
  expect(action[:scp].size).to eq 1
15
15
  expect(action[:scp].first[0]).to match /^.+\/mutex_dir$/
16
16
  expect(action[:scp].first[1]).to eq '.'
17
- expect(action[:remote_bash]).to eq "while ! #{sudo ? 'sudo ' : ''}./mutex_dir lock /tmp/hybrid_platforms_conductor_deploy_lock \"$(ps -o ppid= -p $$)\"; do echo -e 'Another deployment is running on #{node}. Waiting for it to finish to continue...' ; sleep 5 ; done"
17
+ expect(action[:remote_bash]).to eq "while ! #{sudo ? "#{sudo} " : ''}./mutex_dir lock /tmp/hybrid_platforms_conductor_deploy_lock \"$(ps -o ppid= -p $$)\"; do echo -e 'Another deployment is running on #{node}. Waiting for it to finish to continue...' ; sleep 5 ; done"
18
18
  end
19
19
 
20
20
  # Expect a given action to be releasing the mutex on a given node
@@ -22,9 +22,9 @@ module HybridPlatformsConductorTest
22
22
  # Parameters::
23
23
  # * *action* (Hash<Symbol,Object>): The action to check
24
24
  # * *node* (String): The concerned node
25
- # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
26
- def expect_action_to_unlock_node(action, node, sudo: true)
27
- expect(action).to eq(remote_bash: "#{sudo ? 'sudo ' : ''}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock")
25
+ # * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
26
+ def expect_action_to_unlock_node(action, node, sudo: 'sudo -u root')
27
+ expect(action).to eq(remote_bash: "#{sudo ? "#{sudo} " : ''}./mutex_dir unlock /tmp/hybrid_platforms_conductor_deploy_lock")
28
28
  end
29
29
 
30
30
  # Expect a given set of actions to be a deployment
@@ -33,12 +33,12 @@ module HybridPlatformsConductorTest
33
33
  # * *actions* (Object): Actions
34
34
  # * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
35
35
  # * *check* (Boolean): Is the deploy only a check? [default: false]
36
- # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
36
+ # * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
37
37
  # * *expected_actions* (Array<Object>): Additional expected actions [default: []]
38
38
  # * *mocked_result* (Hash<String, [Object, String, String]>): Expected result of the actions, per node, or nil for success [default: nil]
39
39
  # Result::
40
40
  # * Hash<String, [Integer or Symbol, String, String] >: Expected result of those expected actions
41
- def expect_actions_to_deploy_on(actions, nodes, check: false, sudo: true, expected_actions: [], mocked_result: nil)
41
+ def expect_actions_to_deploy_on(actions, nodes, check: false, sudo: 'sudo -u root', expected_actions: [], mocked_result: nil)
42
42
  nodes = [nodes] if nodes.is_a?(String)
43
43
  mocked_result = Hash[nodes.map { |node| [node, [0, "#{check ? 'Check' : 'Deploy'} successful", '']] }] if mocked_result.nil?
44
44
  expect(actions.size).to eq nodes.size
@@ -57,8 +57,8 @@ module HybridPlatformsConductorTest
57
57
  # Parameters::
58
58
  # * *actions* (Object): Actions
59
59
  # * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
60
- # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
61
- def expect_actions_to_unlock(actions, nodes, sudo: true)
60
+ # * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
61
+ def expect_actions_to_unlock(actions, nodes, sudo: 'sudo -u root')
62
62
  nodes = [nodes] if nodes.is_a?(String)
63
63
  expect(actions.size).to eq nodes.size
64
64
  nodes.each do |node|
@@ -73,17 +73,17 @@ module HybridPlatformsConductorTest
73
73
  # Parameters::
74
74
  # * *actions* (Object): Actions
75
75
  # * *nodes* (String or Array<String>): Node (or list of nodes) that should be checked
76
- # * *sudo* (Boolean): Is sudo supposed to be used? [default: true]
77
- def expect_actions_to_upload_logs(actions, nodes, sudo: true)
76
+ # * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
77
+ def expect_actions_to_upload_logs(actions, nodes, sudo: 'sudo -u root')
78
78
  nodes = [nodes] if nodes.is_a?(String)
79
79
  expect(actions.size).to eq nodes.size
80
80
  nodes.each do |node|
81
81
  expect(actions.key?(node)).to eq true
82
- expect(actions[node][:remote_bash]).to eq "#{sudo ? 'sudo ' : ''}mkdir -p /var/log/deployments"
82
+ expect(actions[node][:remote_bash]).to eq "#{sudo ? "#{sudo} " : ''}mkdir -p /var/log/deployments"
83
83
  expect(actions[node][:scp].first[1]).to eq '/var/log/deployments'
84
84
  expect(actions[node][:scp][:group]).to eq 'root'
85
85
  expect(actions[node][:scp][:owner]).to eq 'root'
86
- expect(actions[node][:scp][:sudo]).to eq sudo
86
+ expect(actions[node][:scp][:sudo]).to eq (!sudo.nil?)
87
87
  end
88
88
  Hash[nodes.map { |node| [node, [0, 'Logs uploaded', '']] }]
89
89
  end
@@ -20,7 +20,7 @@ module HybridPlatformsConductorTest
20
20
  #
21
21
  # Parameters::
22
22
  # * *services* (Hash<String, Array<String> >): Expected nodes that should be deployed, with their corresponding services [default: { 'node' => %w[service] }]
23
- # * *sudo* (Boolean): Do we expect sudo to be used in commands? [default: true]
23
+ # * *sudo* (String or nil): sudo supposed to be used, or nil if none [default: 'sudo -u root']
24
24
  # * *check_mode* (Boolean): Are we testing in check mode? [default: @check_mode]
25
25
  # * *mocked_deploy_result* (Hash or nil): Mocked result of the deployment actions, or nil to use the helper's default [default: nil]
26
26
  # * *additional_expected_actions* (Array): Additional expected actions [default: []]
@@ -28,7 +28,7 @@ module HybridPlatformsConductorTest
28
28
  # * *expect_actions_timeout* (Integer or nil): Expected timeout in actions, or nil for none [default: nil]
29
29
  def expected_actions_for_deploy_on(
30
30
  services: { 'node' => %w[service] },
31
- sudo: true,
31
+ sudo: 'sudo -u root',
32
32
  check_mode: @check_mode,
33
33
  mocked_deploy_result: nil,
34
34
  additional_expected_actions: [],
@@ -82,7 +82,7 @@ module HybridPlatformsConductorTest
82
82
  # * *expect_prepare_for_deploy* (Boolean): Should we expect calls to prepare for deploy? [default: true]
83
83
  # * *expect_connections_to_nodes* (Boolean): Should we expect connections to nodes? [default: true]
84
84
  # * *expect_default_actions* (Boolean): Should we expect default actions? [default: true]
85
- # * *expect_sudo* (Boolean): Do we expect sudo to be used in commands? [default: true]
85
+ # * *expect_sudo* (String or nil): Expected sudo command, or nil if none [default: 'sudo -u root']
86
86
  # * *expect_secrets* (Hash): Secrets to be expected during deployment [default: {}]
87
87
  # * *expect_local_environment* (Boolean): Expected local environment flag [default: false]
88
88
  # * *expect_additional_actions* (Array): Additional expected actions [default: []]
@@ -99,7 +99,7 @@ module HybridPlatformsConductorTest
99
99
  expect_prepare_for_deploy: true,
100
100
  expect_connections_to_nodes: true,
101
101
  expect_default_actions: true,
102
- expect_sudo: true,
102
+ expect_sudo: 'sudo -u root',
103
103
  expect_secrets: {},
104
104
  expect_local_environment: false,
105
105
  expect_additional_actions: [],
@@ -201,12 +201,21 @@ module HybridPlatformsConductorTest
201
201
  end
202
202
 
203
203
  it 'deploys on 1 node using root' do
204
- with_platform_to_deploy(expect_sudo: false) do
204
+ with_platform_to_deploy(expect_sudo: nil) do
205
205
  test_actions_executor.connector(:ssh).ssh_user = 'root'
206
206
  expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
207
207
  end
208
208
  end
209
209
 
210
+ it 'deploys on 1 node using an alternate sudo' do
211
+ with_platform_to_deploy(
212
+ expect_sudo: 'other_sudo --user root',
213
+ additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
214
+ ) do
215
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
216
+ end
217
+ end
218
+
210
219
  it 'deploys on 1 node using 1 secret' do
211
220
  with_platform_to_deploy(expect_secrets: { 'secret1' => 'password1' }) do
212
221
  test_deployer.secrets = [{ 'secret1' => 'password1' }]
@@ -227,9 +236,9 @@ module HybridPlatformsConductorTest
227
236
  nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
228
237
  expect_local_environment: true,
229
238
  expect_additional_actions: [
230
- { remote_bash: 'sudo apt update && sudo apt install -y ca-certificates' },
239
+ { remote_bash: 'sudo -u root apt update && sudo -u root apt install -y ca-certificates' },
231
240
  {
232
- remote_bash: 'sudo update-ca-certificates',
241
+ remote_bash: 'sudo -u root update-ca-certificates',
233
242
  scp: {
234
243
  certs_dir => '/usr/local/share/ca-certificates',
235
244
  :sudo => true
@@ -244,6 +253,31 @@ module HybridPlatformsConductorTest
244
253
  end
245
254
  end
246
255
 
256
+ it 'deploys on 1 node in local environment with certificates to install using hpc_certificates on Debian and an alternate sudo' do
257
+ with_certs_dir do |certs_dir|
258
+ with_platform_to_deploy(
259
+ nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
260
+ expect_sudo: 'other_sudo --user root',
261
+ expect_local_environment: true,
262
+ expect_additional_actions: [
263
+ { remote_bash: 'other_sudo --user root apt update && other_sudo --user root apt install -y ca-certificates' },
264
+ {
265
+ remote_bash: 'other_sudo --user root update-ca-certificates',
266
+ scp: {
267
+ certs_dir => '/usr/local/share/ca-certificates',
268
+ :sudo => true
269
+ }
270
+ }
271
+ ],
272
+ additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
273
+ ) do
274
+ ENV['hpc_certificates'] = certs_dir
275
+ test_deployer.local_environment = true
276
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
277
+ end
278
+ end
279
+ end
280
+
247
281
  it 'deploys on 1 node with certificates to install using hpc_certificates on Debian but ignores them in non-local environment' do
248
282
  with_certs_dir do |certs_dir|
249
283
  with_platform_to_deploy(nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } }) do
@@ -257,7 +291,7 @@ module HybridPlatformsConductorTest
257
291
  with_certs_dir do |certs_dir|
258
292
  with_platform_to_deploy(
259
293
  nodes_info: { nodes: { 'node' => { meta: { image: 'debian_9' }, services: %w[service] } } },
260
- expect_sudo: false,
294
+ expect_sudo: nil,
261
295
  expect_local_environment: true,
262
296
  expect_additional_actions: [
263
297
  { remote_bash: 'apt update && apt install -y ca-certificates' },
@@ -284,9 +318,9 @@ module HybridPlatformsConductorTest
284
318
  nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
285
319
  expect_local_environment: true,
286
320
  expect_additional_actions: [
287
- { remote_bash: 'sudo yum install -y ca-certificates' },
321
+ { remote_bash: 'sudo -u root yum install -y ca-certificates' },
288
322
  {
289
- remote_bash: ['sudo update-ca-trust enable', 'sudo update-ca-trust extract'],
323
+ remote_bash: ['sudo -u root update-ca-trust enable', 'sudo -u root update-ca-trust extract'],
290
324
  scp: {
291
325
  "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
292
326
  :sudo => true
@@ -301,11 +335,36 @@ module HybridPlatformsConductorTest
301
335
  end
302
336
  end
303
337
 
338
+ it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS and an alternate sudo' do
339
+ with_certs_dir do |certs_dir|
340
+ with_platform_to_deploy(
341
+ nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
342
+ expect_sudo: 'other_sudo --user root',
343
+ expect_local_environment: true,
344
+ expect_additional_actions: [
345
+ { remote_bash: 'other_sudo --user root yum install -y ca-certificates' },
346
+ {
347
+ remote_bash: ['other_sudo --user root update-ca-trust enable', 'other_sudo --user root update-ca-trust extract'],
348
+ scp: {
349
+ "#{certs_dir}/test_cert.crt" => '/etc/pki/ca-trust/source/anchors',
350
+ :sudo => true
351
+ }
352
+ }
353
+ ],
354
+ additional_config: 'sudo_for { |user| "other_sudo --user #{user}" }'
355
+ ) do
356
+ ENV['hpc_certificates'] = certs_dir
357
+ test_deployer.local_environment = true
358
+ expect(test_deployer.deploy_on('node')).to eq('node' => expected_deploy_result)
359
+ end
360
+ end
361
+ end
362
+
304
363
  it 'deploys on 1 node with certificates to install using hpc_certificates on CentOS using root' do
305
364
  with_certs_dir do |certs_dir|
306
365
  with_platform_to_deploy(
307
366
  nodes_info: { nodes: { 'node' => { meta: { image: 'centos_7' }, services: %w[service] } } },
308
- expect_sudo: false,
367
+ expect_sudo: nil,
309
368
  expect_local_environment: true,
310
369
  expect_additional_actions: [
311
370
  { remote_bash: 'yum install -y ca-certificates' },
@@ -330,7 +330,7 @@ module HybridPlatformsConductorTest
330
330
  expect(actions).to eq({
331
331
  'node' => {
332
332
  remote_bash: {
333
- commands: "#{expected_sudo ? 'sudo -E ' : ''}./proxmox/reserve_proxmox_container --create ./proxmox/create/create_#{expected_file_id}.json --config ./proxmox/config/config_#{expected_file_id}.json",
333
+ commands: "#{expected_sudo ? 'sudo -u root -E ' : ''}./proxmox/reserve_proxmox_container --create ./proxmox/create/create_#{expected_file_id}.json --config ./proxmox/config/config_#{expected_file_id}.json",
334
334
  env: {
335
335
  'hpc_user_for_proxmox' => proxmox_user,
336
336
  'hpc_password_for_proxmox' => proxmox_password,
@@ -382,7 +382,7 @@ module HybridPlatformsConductorTest
382
382
  expect(actions).to eq({
383
383
  'node' => {
384
384
  remote_bash: {
385
- commands: "#{expected_sudo ? 'sudo -E ' : ''}./proxmox/reserve_proxmox_container --destroy ./proxmox/destroy/destroy_#{expected_file_id}.json --config ./proxmox/config/config_#{expected_file_id}.json",
385
+ commands: "#{expected_sudo ? 'sudo -u root -E ' : ''}./proxmox/reserve_proxmox_container --destroy ./proxmox/destroy/destroy_#{expected_file_id}.json --config ./proxmox/config/config_#{expected_file_id}.json",
386
386
  env: {
387
387
  'hpc_user_for_proxmox' => proxmox_user,
388
388
  'hpc_password_for_proxmox' => proxmox_password,
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: 32.4.2
4
+ version: 32.5.0
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-03-05 00:00:00.000000000 Z
11
+ date: 2021-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: range_operators
@@ -463,6 +463,7 @@ files:
463
463
  - spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs/platform_handlers_spec.rb
464
464
  - spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb
465
465
  - spec/hybrid_platforms_conductor_test/api/nodes_handler/common_spec.rb
466
+ - spec/hybrid_platforms_conductor_test/api/nodes_handler/config_spec.rb
466
467
  - spec/hybrid_platforms_conductor_test/api/nodes_handler/git_diff_impacts_spec.rb
467
468
  - spec/hybrid_platforms_conductor_test/api/nodes_handler/nodes_selectors_spec.rb
468
469
  - spec/hybrid_platforms_conductor_test/api/nodes_handler/platform_handlers_plugins_api_spec.rb