puppet 8.6.0 → 8.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -2
  3. data/Gemfile.lock +63 -53
  4. data/Rakefile +45 -22
  5. data/examples/hiera/README.md +68 -57
  6. data/examples/hiera/data/common.yaml +12 -0
  7. data/examples/hiera/data/dc1.yaml +6 -0
  8. data/examples/hiera/hiera.yaml +15 -0
  9. data/examples/hiera/modules/ntp/data/common.yaml +4 -0
  10. data/examples/hiera/modules/ntp/hiera.yaml +9 -0
  11. data/examples/hiera/modules/ntp/manifests/config.pp +16 -4
  12. data/examples/hiera/modules/ntp/templates/ntp.conf.epp +3 -0
  13. data/examples/hiera/modules/users/manifests/common.pp +7 -2
  14. data/examples/hiera/modules/users/manifests/dc1.pp +7 -2
  15. data/examples/hiera/site.pp +1 -1
  16. data/ext/project_data.yaml +0 -45
  17. data/ext/windows/service/daemon.rb +9 -2
  18. data/lib/puppet/application/doc.rb +1 -5
  19. data/lib/puppet/application/lookup.rb +2 -0
  20. data/lib/puppet/defaults.rb +5 -19
  21. data/lib/puppet/file_serving/http_metadata.rb +2 -0
  22. data/lib/puppet/functions/regsubst.rb +11 -14
  23. data/lib/puppet/indirector/catalog/compiler.rb +2 -35
  24. data/lib/puppet/module_tool/tar/gnu.rb +10 -8
  25. data/lib/puppet/node/server_facts.rb +43 -0
  26. data/lib/puppet/parser/functions/generate.rb +2 -1
  27. data/lib/puppet/pops/evaluator/deferred_resolver.rb +41 -6
  28. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +2 -1
  29. data/lib/puppet/pops/evaluator/runtime3_support.rb +0 -6
  30. data/lib/puppet/pops/loader/static_loader.rb +2 -2
  31. data/lib/puppet/pops/lookup/module_data_provider.rb +9 -9
  32. data/lib/puppet/provider/aix_object.rb +1 -1
  33. data/lib/puppet/provider/file/posix.rb +16 -2
  34. data/lib/puppet/provider/group/groupadd.rb +30 -9
  35. data/lib/puppet/provider/package/gem.rb +1 -0
  36. data/lib/puppet/provider/package/pkgutil.rb +6 -5
  37. data/lib/puppet/provider/package/puppet_gem.rb +4 -15
  38. data/lib/puppet/provider/package/xbps.rb +127 -0
  39. data/lib/puppet/type/exec.rb +8 -0
  40. data/lib/puppet/type/file/selcontext.rb +7 -6
  41. data/lib/puppet/type/file/target.rb +9 -11
  42. data/lib/puppet/util/command_line/trollop.rb +20 -2
  43. data/lib/puppet/util/execution.rb +1 -1
  44. data/lib/puppet/util/reference.rb +1 -30
  45. data/lib/puppet/util/rpm_compare.rb +1 -1
  46. data/lib/puppet/util/run_mode.rb +40 -0
  47. data/lib/puppet/util/selinux.rb +14 -4
  48. data/lib/puppet/util/windows/com.rb +2 -2
  49. data/lib/puppet/util/windows/daemon.rb +15 -32
  50. data/lib/puppet/version.rb +1 -1
  51. data/locales/puppet.pot +648 -648
  52. data/man/man5/puppet.conf.5 +2 -2
  53. data/man/man8/puppet-agent.8 +1 -1
  54. data/man/man8/puppet-apply.8 +1 -1
  55. data/man/man8/puppet-catalog.8 +1 -1
  56. data/man/man8/puppet-config.8 +1 -1
  57. data/man/man8/puppet-describe.8 +1 -1
  58. data/man/man8/puppet-device.8 +1 -1
  59. data/man/man8/puppet-doc.8 +1 -1
  60. data/man/man8/puppet-epp.8 +1 -1
  61. data/man/man8/puppet-facts.8 +1 -1
  62. data/man/man8/puppet-filebucket.8 +1 -1
  63. data/man/man8/puppet-generate.8 +1 -1
  64. data/man/man8/puppet-help.8 +1 -1
  65. data/man/man8/puppet-lookup.8 +1 -1
  66. data/man/man8/puppet-module.8 +1 -1
  67. data/man/man8/puppet-node.8 +1 -1
  68. data/man/man8/puppet-parser.8 +1 -1
  69. data/man/man8/puppet-plugin.8 +1 -1
  70. data/man/man8/puppet-report.8 +1 -1
  71. data/man/man8/puppet-resource.8 +1 -1
  72. data/man/man8/puppet-script.8 +1 -1
  73. data/man/man8/puppet-ssl.8 +1 -1
  74. data/man/man8/puppet.8 +2 -2
  75. metadata +56 -51
  76. data/examples/hiera/etc/hiera.yaml +0 -15
  77. data/examples/hiera/etc/hieradb/common.yaml +0 -3
  78. data/examples/hiera/etc/hieradb/dc1.yaml +0 -6
  79. data/examples/hiera/etc/hieradb/development.yaml +0 -2
  80. data/examples/hiera/etc/puppet.conf +0 -3
  81. data/examples/hiera/modules/data/manifests/common.pp +0 -4
  82. data/examples/hiera/modules/ntp/manifests/data.pp +0 -4
  83. data/examples/hiera/modules/ntp/templates/ntp.conf.erb +0 -3
  84. data/examples/hiera/modules/users/manifests/development.pp +0 -4
  85. data/tasks/benchmark.rake +0 -180
  86. data/tasks/cfpropertylist.rake +0 -15
  87. data/tasks/ci.rake +0 -24
  88. data/tasks/generate_ast_model.rake +0 -90
  89. data/tasks/generate_cert_fixtures.rake +0 -199
  90. data/tasks/manpages.rake +0 -67
  91. data/tasks/memwalk.rake +0 -195
  92. data/tasks/parallel.rake +0 -410
  93. data/tasks/parser.rake +0 -22
  94. data/tasks/yard.rake +0 -59
@@ -1,4 +1,9 @@
1
- # notifies
1
+ # @summary Notify to demonstrate users::dc1 in catalog
2
+ #
3
+ # A Class that should be present in dc1 node(s) catalog
4
+ #
5
+ # @example
6
+ # include users::dc1
2
7
  class users::dc1 {
3
- notify{'Adding users::dc1': }
8
+ notify { 'Adding users::dc1': }
4
9
  }
@@ -1,3 +1,3 @@
1
1
  node default {
2
- hiera_include('classes')
2
+ include lookup('classes')
3
3
  }
@@ -1,53 +1,8 @@
1
1
  ---
2
2
  project: 'puppet'
3
- author: 'Puppet Labs'
4
- email: 'info@puppetlabs.com'
5
- homepage: 'https://github.com/puppetlabs/puppet'
6
- summary: 'Puppet, an automated configuration management tool'
7
- description: 'Puppet, an automated configuration management tool'
8
- version_file: 'lib/puppet/version.rb'
9
- # files and gem_files are space separated lists
10
- files: '[A-Z]* install.rb bin lib conf man examples ext tasks locales'
11
- # Make sure these gem requirements are in sync with the gemspec and Gemfile
12
- gem_files: '[A-Z]* install.rb bin lib conf man examples ext tasks locales'
13
- gem_test_files:
14
- gem_executables: 'puppet'
15
- gem_default_executables: 'puppet'
16
- gem_license: 'Apache-2.0'
17
- gem_forge_project: 'puppet'
18
- gem_required_ruby_version: '>= 3.1.0'
19
- gem_required_rubygems_version: '> 1.3.1'
20
- gem_runtime_dependencies:
21
- facter: ['>= 4.3.0', '< 5']
22
- semantic_puppet: '~> 1.0'
23
- fast_gettext: ['>= 2.1', '< 3']
24
- locale: '~> 2.1'
25
- multi_json: '~> 1.13'
26
- puppet-resource_api: '~>1.5'
27
- concurrent-ruby: "~> 1.0"
28
- deep_merge: '~> 1.0'
29
- scanf: '~> 1.0'
30
3
  gem_rdoc_options:
31
4
  - --title
32
5
  - "Puppet - Configuration Management"
33
6
  - --main
34
7
  - README.md
35
8
  - --line-numbers
36
- gem_platform_dependencies:
37
- universal-darwin:
38
- gem_runtime_dependencies:
39
- CFPropertyList: '~> 2.2'
40
- x86-mingw32:
41
- gem_runtime_dependencies:
42
- ffi: '1.15.5'
43
- minitar: '~> 0.9'
44
- x64-mingw32:
45
- gem_runtime_dependencies:
46
- ffi: '1.15.5'
47
- minitar: '~> 0.9'
48
- bundle_platforms:
49
- universal-darwin: all
50
- x86-mingw32: mingw
51
- x64-mingw32: x64_mingw
52
- pre_tasks:
53
- 'package:apple': 'cfpropertylist'
@@ -155,12 +155,19 @@ class WindowsDaemon < Puppet::Util::Windows::Daemon
155
155
  end
156
156
  end
157
157
 
158
+ # Parses runinterval.
159
+ #
160
+ # @param puppet_path [String] The file path for the Puppet executable.
161
+ # @return runinterval [Integer] How often to do a Puppet run, in seconds.
158
162
  def parse_runinterval(puppet_path)
159
163
  begin
160
- runinterval = %x(#{puppet_path} config --section agent --log_level notice print runinterval).to_i
161
- if runinterval == 0
164
+ runinterval = %x(#{puppet_path} config --section agent --log_level notice print runinterval).chomp
165
+ if runinterval == ''
162
166
  runinterval = 1800
163
167
  log_err("Failed to determine runinterval, defaulting to #{runinterval} seconds")
168
+ else
169
+ # Use Kernel#Integer because to_i will return 0 with non-numeric strings.
170
+ runinterval = Integer(runinterval)
164
171
  end
165
172
  rescue Exception => e
166
173
  log_exception(e)
@@ -173,11 +173,7 @@ class Puppet::Application::Doc < Puppet::Application
173
173
 
174
174
  text += Puppet::Util::Reference.footer unless with_contents # We've only got one reference
175
175
 
176
- if options[:mode] == :pdf
177
- Puppet::Util::Reference.pdf(text)
178
- else
179
- puts text
180
- end
176
+ puts text
181
177
 
182
178
  exit exit_code
183
179
  end
@@ -3,6 +3,7 @@
3
3
  require_relative '../../puppet/application'
4
4
  require_relative '../../puppet/pops'
5
5
  require_relative '../../puppet/node'
6
+ require_relative '../../puppet/node/server_facts'
6
7
  require_relative '../../puppet/parser/compiler'
7
8
 
8
9
  class Puppet::Application::Lookup < Puppet::Application
@@ -403,6 +404,7 @@ class Puppet::Application::Lookup < Puppet::Application
403
404
  end
404
405
  end
405
406
  node.environment = Puppet[:environment] if Puppet.settings.set_by_cli?(:environment)
407
+ node.add_server_facts(Puppet::Node::ServerFacts.load)
406
408
  Puppet[:code] = 'undef' unless options[:compile]
407
409
  compiler = Puppet::Parser::Compiler.new(node)
408
410
  if options[:node]
@@ -47,29 +47,15 @@ module Puppet
47
47
  end
48
48
 
49
49
  def self.default_basemodulepath
50
- if Puppet::Util::Platform.windows?
51
- path = ['$codedir/modules']
52
- installdir = ENV.fetch("FACTER_env_windows_installdir", nil)
53
- if installdir
54
- path << "#{installdir}/puppet/modules"
55
- end
56
- path.join(File::PATH_SEPARATOR)
57
- else
58
- '$codedir/modules:/opt/puppetlabs/puppet/modules'
50
+ path = ['$codedir/modules']
51
+ if (run_mode_dir = Puppet.run_mode.common_module_dir)
52
+ path << run_mode_dir
59
53
  end
54
+ path.join(File::PATH_SEPARATOR)
60
55
  end
61
56
 
62
57
  def self.default_vendormoduledir
63
- if Puppet::Util::Platform.windows?
64
- installdir = ENV.fetch("FACTER_env_windows_installdir", nil)
65
- if installdir
66
- "#{installdir}\\puppet\\vendor_modules"
67
- else
68
- nil
69
- end
70
- else
71
- '/opt/puppetlabs/puppet/vendor_modules'
72
- end
58
+ Puppet.run_mode.vendor_module_dir
73
59
  end
74
60
 
75
61
  ############################################################################################
@@ -51,6 +51,8 @@ class Puppet::FileServing::HttpMetadata < Puppet::FileServing::Metadata
51
51
  # Prefer the checksum_type from the indirector request options
52
52
  # but fall back to the alternative otherwise
53
53
  [@checksum_type, :sha256, :sha1, :md5, :mtime].each do |type|
54
+ next if type == :md5 && Puppet::Util::Platform.fips_enabled?
55
+
54
56
  @checksum_type = type
55
57
  @checksum = @checksums[type]
56
58
  break if @checksum
@@ -20,13 +20,10 @@ Puppet::Functions.create_function(:regsubst) do
20
20
  # - *M* Multiline regexps
21
21
  # - *G* Global replacement; all occurrences of the regexp in each target string will be replaced. Without this, only the first occurrence will be replaced.
22
22
  # @param encoding [Enum['N','E','S','U']]
23
- # Optional. How to handle multibyte characters when compiling the regexp (must not be used when pattern is a
24
- # precompiled regexp). A single-character string with the following values:
25
- # - *N* None
26
- # - *E* EUC
27
- # - *S* SJIS
28
- # - *U* UTF-8
23
+ # Deprecated and ignored parameter, only here for compatibility.
29
24
  # @return [Array[String], String] The result of the substitution. Result type is the same as for the target parameter.
25
+ # @deprecated
26
+ # This method has the optional encoding parameter, which is ignored.
30
27
  # @example Get the third octet from the node's IP address:
31
28
  # ```puppet
32
29
  # $i3 = regsubst($ipaddress,'^(\\d+)\\.(\\d+)\\.(\\d+)\\.(\\d+)$','\\3')
@@ -56,13 +53,6 @@ Puppet::Functions.create_function(:regsubst) do
56
53
  # - *I* Ignore case in regexps
57
54
  # - *M* Multiline regexps
58
55
  # - *G* Global replacement; all occurrences of the regexp in each target string will be replaced. Without this, only the first occurrence will be replaced.
59
- # @param encoding [Enum['N','E','S','U']]
60
- # Optional. How to handle multibyte characters when compiling the regexp (must not be used when pattern is a
61
- # precompiled regexp). A single-character string with the following values:
62
- # - *N* None
63
- # - *E* EUC
64
- # - *S* SJIS
65
- # - *U* UTF-8
66
56
  # @return [Array[String], String] The result of the substitution. Result type is the same as for the target parameter.
67
57
  # @example Put angle brackets around each octet in the node's IP address:
68
58
  # ```puppet
@@ -76,6 +66,13 @@ Puppet::Functions.create_function(:regsubst) do
76
66
  end
77
67
 
78
68
  def regsubst_string(target, pattern, replacement, flags = nil, encoding = nil)
69
+ if encoding
70
+ Puppet.warn_once(
71
+ 'deprecations', 'regsubst_function_encoding',
72
+ _("The regsubst() function's encoding argument has been ignored since Ruby 1.9 and will be removed in a future release")
73
+ )
74
+ end
75
+
79
76
  re_flags = 0
80
77
  operation = :sub
81
78
  unless flags.nil?
@@ -88,7 +85,7 @@ Puppet::Functions.create_function(:regsubst) do
88
85
  end
89
86
  end
90
87
  end
91
- inner_regsubst(target, Regexp.compile(pattern, re_flags, encoding), replacement, operation)
88
+ inner_regsubst(target, Regexp.compile(pattern, re_flags), replacement, operation)
92
89
  end
93
90
 
94
91
  def regsubst_regexp(target, pattern, replacement, flags = nil)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative '../../../puppet/environments'
4
4
  require_relative '../../../puppet/node'
5
+ require_relative '../../../puppet/node/server_facts'
5
6
  require_relative '../../../puppet/resource/catalog'
6
7
  require_relative '../../../puppet/indirector/code'
7
8
  require_relative '../../../puppet/util/profiler'
@@ -426,40 +427,6 @@ class Puppet::Resource::Catalog::Compiler < Puppet::Indirector::Code
426
427
  #
427
428
  # See also set_server_facts in Puppet::Server::Compiler in puppetserver.
428
429
  def set_server_facts
429
- @server_facts = {}
430
-
431
- # Add our server Puppet Enterprise version, if available.
432
- pe_version_file = '/opt/puppetlabs/server/pe_version'
433
- if File.readable?(pe_version_file) and !File.zero?(pe_version_file)
434
- @server_facts['pe_serverversion'] = File.read(pe_version_file).chomp
435
- end
436
-
437
- # Add our server version to the fact list
438
- @server_facts["serverversion"] = Puppet.version.to_s
439
-
440
- # And then add the server name and IP
441
- { "servername" => "networking.fqdn",
442
- "serverip" => "networking.ip",
443
- "serverip6" => "networking.ip6" }.each do |var, fact|
444
- value = Puppet.runtime[:facter].value(fact)
445
- unless value.nil?
446
- @server_facts[var] = value
447
- end
448
- end
449
-
450
- if @server_facts["servername"].nil?
451
- host = Puppet.runtime[:facter].value('networking.hostname')
452
- if host.nil?
453
- Puppet.warning _("Could not retrieve fact servername")
454
- elsif domain = Puppet.runtime[:facter].value('networking.domain') # rubocop:disable Lint/AssignmentInCondition
455
- @server_facts["servername"] = [host, domain].join(".")
456
- else
457
- @server_facts["servername"] = host
458
- end
459
- end
460
-
461
- if @server_facts["serverip"].nil? && @server_facts["serverip6"].nil?
462
- Puppet.warning _("Could not retrieve either serverip or serverip6 fact")
463
- end
430
+ @server_facts = Puppet::Node::ServerFacts.load
464
431
  end
465
432
  end
@@ -4,18 +4,20 @@ require 'shellwords'
4
4
 
5
5
  class Puppet::ModuleTool::Tar::Gnu
6
6
  def unpack(sourcefile, destdir, owner)
7
- sourcefile = File.expand_path(sourcefile)
7
+ safe_sourcefile = Shellwords.shellescape(File.expand_path(sourcefile))
8
8
  destdir = File.expand_path(destdir)
9
+ safe_destdir = Shellwords.shellescape(destdir)
9
10
 
10
- Dir.chdir(destdir) do
11
- Puppet::Util::Execution.execute("gzip -dc #{Shellwords.shellescape(sourcefile)} | tar xof -")
12
- Puppet::Util::Execution.execute("find . -type d -exec chmod 755 {} +")
13
- Puppet::Util::Execution.execute("find . -type f -exec chmod u+rw,g+r,a-st {} +")
14
- Puppet::Util::Execution.execute("chown -R #{owner} .")
15
- end
11
+ Puppet::Util::Execution.execute("gzip -dc #{safe_sourcefile} | tar --extract --no-same-owner --directory #{safe_destdir} --file -")
12
+ Puppet::Util::Execution.execute(['find', destdir, '-type', 'd', '-exec', 'chmod', '755', '{}', '+'])
13
+ Puppet::Util::Execution.execute(['find', destdir, '-type', 'f', '-exec', 'chmod', 'u+rw,g+r,a-st', '{}', '+'])
14
+ Puppet::Util::Execution.execute(['chown', '-R', owner, destdir])
16
15
  end
17
16
 
18
17
  def pack(sourcedir, destfile)
19
- Puppet::Util::Execution.execute("tar cf - #{sourcedir} | gzip -c > #{File.basename(destfile)}")
18
+ safe_sourcedir = Shellwords.shellescape(sourcedir)
19
+ safe_destfile = Shellwords.shellescape(File.basename(destfile))
20
+
21
+ Puppet::Util::Execution.execute("tar cf - #{safe_sourcedir} | gzip -c > #{safe_destfile}")
20
22
  end
21
23
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Puppet::Node::ServerFacts
4
+ def self.load
5
+ server_facts = {}
6
+
7
+ # Add our server Puppet Enterprise version, if available.
8
+ pe_version_file = '/opt/puppetlabs/server/pe_version'
9
+ if File.readable?(pe_version_file) and !File.zero?(pe_version_file)
10
+ server_facts['pe_serverversion'] = File.read(pe_version_file).chomp
11
+ end
12
+
13
+ # Add our server version to the fact list
14
+ server_facts["serverversion"] = Puppet.version.to_s
15
+
16
+ # And then add the server name and IP
17
+ { "servername" => "networking.fqdn",
18
+ "serverip" => "networking.ip",
19
+ "serverip6" => "networking.ip6" }.each do |var, fact|
20
+ value = Puppet.runtime[:facter].value(fact)
21
+ unless value.nil?
22
+ server_facts[var] = value
23
+ end
24
+ end
25
+
26
+ if server_facts["servername"].nil?
27
+ host = Puppet.runtime[:facter].value('networking.hostname')
28
+ if host.nil?
29
+ Puppet.warning _("Could not retrieve fact servername")
30
+ elsif domain = Puppet.runtime[:facter].value('networking.domain') # rubocop:disable Lint/AssignmentInCondition
31
+ server_facts["servername"] = [host, domain].join(".")
32
+ else
33
+ server_facts["servername"] = host
34
+ end
35
+ end
36
+
37
+ if server_facts["serverip"].nil? && server_facts["serverip6"].nil?
38
+ Puppet.warning _("Could not retrieve either serverip or serverip6 fact")
39
+ end
40
+
41
+ server_facts
42
+ end
43
+ end
@@ -31,7 +31,8 @@ Puppet::Parser::Functions.newfunction(:generate, :arity => -2, :type => :rvalue,
31
31
  end
32
32
 
33
33
  begin
34
- Dir.chdir(File.dirname(args[0])) { Puppet::Util::Execution.execute(args).to_str }
34
+ dir = File.dirname(args[0])
35
+ Puppet::Util::Execution.execute(args, failonfail: true, combine: true, cwd: dir).to_str
35
36
  rescue Puppet::ExecutionFailure => detail
36
37
  raise Puppet::ParseError, _("Failed to execute generator %{generator}: %{detail}") % { generator: args[0], detail: detail }, detail.backtrace
37
38
  end
@@ -89,17 +89,25 @@ class DeferredResolver
89
89
  overrides = {}
90
90
  r.parameters.each_pair do |k, v|
91
91
  resolved = resolve(v)
92
- # If the value is instance of Sensitive - assign the unwrapped value
93
- # and mark it as sensitive if not already marked
94
- #
95
92
  case resolved
96
93
  when Puppet::Pops::Types::PSensitiveType::Sensitive
94
+ # If the resolved value is instance of Sensitive - assign the unwrapped value
95
+ # and mark it as sensitive if not already marked
96
+ #
97
97
  resolved = resolved.unwrap
98
98
  mark_sensitive_parameters(r, k)
99
- # If the value is a DeferredValue and it has an argument of type PSensitiveType, mark it as sensitive
100
- # The DeferredValue.resolve method will unwrap it during catalog application
99
+
101
100
  when Puppet::Pops::Evaluator::DeferredValue
102
- if v.arguments.any? { |arg| arg.is_a?(Puppet::Pops::Types::PSensitiveType) }
101
+ # If the resolved value is a DeferredValue and it has an argument of type
102
+ # PSensitiveType, mark it as sensitive. Since DeferredValues can nest,
103
+ # we must walk all arguments, e.g. the DeferredValue may call the `epp`
104
+ # function, where one of its arguments is a DeferredValue to call the
105
+ # `vault:lookup` function.
106
+ #
107
+ # The DeferredValue.resolve method will unwrap the sensitive during
108
+ # catalog application
109
+ #
110
+ if contains_sensitive_args?(v)
103
111
  mark_sensitive_parameters(r, k)
104
112
  end
105
113
  end
@@ -109,6 +117,33 @@ class DeferredResolver
109
117
  end
110
118
  end
111
119
 
120
+ # Return true if x contains an argument that is an instance of PSensitiveType:
121
+ #
122
+ # Deferred('new', [Sensitive, 'password'])
123
+ #
124
+ # Or an instance of PSensitiveType::Sensitive:
125
+ #
126
+ # Deferred('join', [['a', Sensitive('b')], ':'])
127
+ #
128
+ # Since deferred values can nest, descend into Arrays and Hash keys and values,
129
+ # short-circuiting when the first occurrence is found.
130
+ #
131
+ def contains_sensitive_args?(x)
132
+ case x
133
+ when @deferred_class
134
+ contains_sensitive_args?(x.arguments)
135
+ when Array
136
+ x.any? { |v| contains_sensitive_args?(v) }
137
+ when Hash
138
+ x.any? { |k, v| contains_sensitive_args?(k) || contains_sensitive_args?(v) }
139
+ when Puppet::Pops::Types::PSensitiveType, Puppet::Pops::Types::PSensitiveType::Sensitive
140
+ true
141
+ else
142
+ false
143
+ end
144
+ end
145
+ private :contains_sensitive_args?
146
+
112
147
  def mark_sensitive_parameters(r, k)
113
148
  unless r.sensitive_parameters.include?(k.to_sym)
114
149
  r.sensitive_parameters = (r.sensitive_parameters + [k.to_sym]).freeze
@@ -76,7 +76,8 @@ module Runtime3ResourceSupport
76
76
  end
77
77
 
78
78
  def self.resource_to_ptype(resource)
79
- nil if resource.nil?
79
+ return nil if resource.nil?
80
+
80
81
  # inference returns the meta type since the 3x Resource is an alternate way to describe a type
81
82
  Puppet::Pops::Types::TypeCalculator.singleton().infer(resource).type
82
83
  end
@@ -443,12 +443,6 @@ module Runtime3Support
443
443
  resource.valid_parameter?(name)
444
444
  end
445
445
 
446
- def resource_to_ptype(resource)
447
- nil if resource.nil?
448
- # inference returns the meta type since the 3x Resource is an alternate way to describe a type
449
- type_calculator.infer(resource).type
450
- end
451
-
452
446
  # This is the same type of "truth" as used in the current Puppet DSL.
453
447
  #
454
448
  def is_true?(value, o)
@@ -46,9 +46,9 @@ class StaticLoader < Loader
46
46
 
47
47
  def discover(type, error_collector = nil, name_authority = Pcore::RUNTIME_NAME_AUTHORITY)
48
48
  # Static loader only contains runtime types
49
- return EMPTY_ARRAY unless type == :type && name_authority == name_authority = Pcore::RUNTIME_NAME_AUTHORITY
49
+ return EMPTY_ARRAY unless type == :type && name_authority == Pcore::RUNTIME_NAME_AUTHORITY
50
50
 
51
- typed_names = type == :type && name_authority == Pcore::RUNTIME_NAME_AUTHORITY ? @loaded.keys : EMPTY_ARRAY
51
+ typed_names = @loaded.keys
52
52
  block_given? ? typed_names.select { |tn| yield(tn) } : typed_names
53
53
  end
54
54
 
@@ -47,16 +47,16 @@ class ModuleDataProvider < ConfiguredDataProvider
47
47
  def validate_data_hash(data_hash)
48
48
  super
49
49
  module_prefix = "#{module_name}::"
50
- data_hash.each_key.reduce(data_hash) do |memo, k|
51
- next memo if k == LOOKUP_OPTIONS || k.start_with?(module_prefix)
52
-
53
- msg = "#{yield} must use keys qualified with the name of the module"
54
- memo = memo.clone if memo.equal?(data_hash)
55
- memo.delete(k)
56
- Puppet.warning("Module '#{module_name}': #{msg}")
57
- memo
50
+ data_hash_to_return = {}
51
+ data_hash.keys.each do |k|
52
+ if k == LOOKUP_OPTIONS || k.start_with?(module_prefix)
53
+ data_hash_to_return[k] = data_hash[k]
54
+ else
55
+ msg = "#{yield} must use keys qualified with the name of the module"
56
+ Puppet.warning("Module '#{module_name}': #{msg}; got #{k}")
57
+ end
58
58
  end
59
- data_hash
59
+ data_hash_to_return
60
60
  end
61
61
 
62
62
  protected
@@ -131,7 +131,7 @@ class Puppet::Provider::AixObject < Puppet::Provider
131
131
 
132
132
  # AIX will do the right validation to ensure numeric attributes
133
133
  # can't be set to non-numeric values, so no need for the extra clutter.
134
- info[:attribute_to_property] = lambda do |value|
134
+ info[:attribute_to_property] = lambda do |value| # rubocop:disable Style/SymbolProc
135
135
  value.to_i
136
136
  end
137
137
 
@@ -12,8 +12,22 @@ Puppet::Type.type(:file).provide :posix do
12
12
  require 'etc'
13
13
  require_relative '../../../puppet/util/selinux'
14
14
 
15
- def self.post_resource_eval
16
- Selinux.matchpathcon_fini if Puppet::Util::SELinux.selinux_support?
15
+ class << self
16
+ def selinux_handle
17
+ return nil unless Puppet::Util::SELinux.selinux_support?
18
+
19
+ # selabel_open takes 3 args: backend, options, and nopt. The backend param
20
+ # is a constant, SELABEL_CTX_FILE, which happens to be 0. Since options is
21
+ # nil, nopt can be 0 since nopt represents the # of options specified.
22
+ @selinux_handle ||= Selinux.selabel_open(Selinux::SELABEL_CTX_FILE, nil, 0)
23
+ end
24
+
25
+ def post_resource_eval
26
+ if @selinux_handle
27
+ Selinux.selabel_close(@selinux_handle)
28
+ @selinux_handle = nil
29
+ end
30
+ end
17
31
  end
18
32
 
19
33
  def uid2name(id)
@@ -17,11 +17,20 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
17
17
  value.is_a? Integer
18
18
  end
19
19
 
20
- optional_commands :localadd => "lgroupadd", :localdelete => "lgroupdel", :localmodify => "lgroupmod"
21
-
22
- has_feature :manages_local_users_and_groups, :manages_members if Puppet.features.libuser?
23
-
24
- options :members, :flag => '-M', :method => :mem
20
+ optional_commands :localadd => "lgroupadd", :localdelete => "lgroupdel", :localmodify => "lgroupmod", :purgemember => "usermod"
21
+
22
+ has_feature :manages_local_users_and_groups if Puppet.features.libuser?
23
+ has_feature :manages_members if Puppet.features.libuser? ||
24
+ (Puppet.runtime[:facter].value('os.name') == "Fedora" &&
25
+ Puppet.runtime[:facter].value('os.release.major').to_i >= 40)
26
+
27
+ # Libuser's modify command 'lgroupmod' requires '-M' flag for member additions.
28
+ # 'groupmod' command requires the '-aU' flags for it.
29
+ if Puppet.features.libuser?
30
+ options :members, :flag => '-M', :method => :mem
31
+ else
32
+ options :members, :flag => '-aU', :method => :mem
33
+ end
25
34
 
26
35
  def exists?
27
36
  return !!localgid if @resource.forcelocal?
@@ -63,7 +72,8 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
63
72
  end
64
73
 
65
74
  def addcmd
66
- if @resource.forcelocal?
75
+ # The localadd command (lgroupadd) must only be called when libuser is supported.
76
+ if Puppet.features.libuser? && @resource.forcelocal?
67
77
  cmd = [command(:localadd)]
68
78
  @custom_environment = Puppet::Util::Libuser.getenv
69
79
  else
@@ -91,7 +101,8 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
91
101
  end
92
102
 
93
103
  def modifycmd(param, value)
94
- if @resource.forcelocal? || @resource[:members]
104
+ # The localmodify command (lgroupmod) must only be called when libuser is supported.
105
+ if Puppet.features.libuser? && (@resource.forcelocal? || @resource[:members])
95
106
  cmd = [command(:localmodify)]
96
107
  @custom_environment = Puppet::Util::Libuser.getenv
97
108
  else
@@ -114,7 +125,8 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
114
125
  end
115
126
 
116
127
  def deletecmd
117
- if @resource.forcelocal?
128
+ # The localdelete command (lgroupdel) must only be called when libuser is supported.
129
+ if Puppet.features.libuser? && @resource.forcelocal?
118
130
  @custom_environment = Puppet::Util::Libuser.getenv
119
131
  [command(:localdelete), @resource[:name]]
120
132
  else
@@ -133,7 +145,16 @@ Puppet::Type.type(:group).provide :groupadd, :parent => Puppet::Provider::NameSe
133
145
  end
134
146
 
135
147
  def purge_members
136
- localmodify('-m', members_to_s(members), @resource.name)
148
+ # The groupadd provider doesn't have the ability currently to remove members from a group, libuser does.
149
+ # Use libuser's lgroupmod command to achieve purging members if libuser is supported.
150
+ # Otherwise use the 'usermod' command.
151
+ if Puppet.features.libuser?
152
+ localmodify('-m', members_to_s(members), @resource.name)
153
+ else
154
+ members.each do |member|
155
+ purgemember('-rG', @resource.name, member)
156
+ end
157
+ end
137
158
  end
138
159
 
139
160
  private
@@ -83,6 +83,7 @@ Puppet::Type.type(:package).provide :gem, :parent => Puppet::Provider::Package::
83
83
  custom_environment[:PATH] = windows_path_without_puppet_bin
84
84
  end
85
85
 
86
+ # This uses an unusual form of passing the command and args as [<cmd>, [<arg1>, <arg2>, ...]]
86
87
  execute(cmd, { :failonfail => true, :combine => true, :custom_environment => custom_environment })
87
88
  end
88
89
 
@@ -115,11 +115,12 @@ Puppet::Type.type(:package).provide :pkgutil, :parent => :sun, :source => :sun d
115
115
 
116
116
  # Identify common types of pkgutil noise as it downloads catalogs etc
117
117
  def self.noise?(line)
118
- true if line =~ /^#/
119
- true if line =~ /^Checking integrity / # use_gpg
120
- true if line =~ /^gpg: / # gpg verification
121
- true if line =~ /^=+> / # catalog fetch
122
- true if line =~ /\d+:\d+:\d+ URL:/ # wget without -q
118
+ return true if line =~ /^#/
119
+ return true if line =~ /^Checking integrity / # use_gpg
120
+ return true if line =~ /^gpg: / # gpg verification
121
+ return true if line =~ /^=+> / # catalog fetch
122
+ return true if line =~ /\d+:\d+:\d+ URL:/ # wget without -q
123
+
123
124
  false
124
125
  end
125
126