puppet 7.10.0 → 7.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -3
  3. data/Gemfile.lock +20 -15
  4. data/ext/project_data.yaml +1 -1
  5. data/lib/puppet/application/agent.rb +4 -0
  6. data/lib/puppet/application/apply.rb +20 -2
  7. data/lib/puppet/application/lookup.rb +72 -24
  8. data/lib/puppet/application/resource.rb +15 -13
  9. data/lib/puppet/concurrent/thread_local_singleton.rb +6 -3
  10. data/lib/puppet/configurer.rb +98 -29
  11. data/lib/puppet/confine/variable.rb +1 -1
  12. data/lib/puppet/defaults.rb +17 -3
  13. data/lib/puppet/facter_impl.rb +96 -0
  14. data/lib/puppet/file_serving/metadata.rb +3 -0
  15. data/lib/puppet/file_serving/mount/file.rb +4 -4
  16. data/lib/puppet/file_system/file_impl.rb +10 -8
  17. data/lib/puppet/file_system/jruby.rb +1 -1
  18. data/lib/puppet/file_system/path_pattern.rb +10 -15
  19. data/lib/puppet/file_system/uniquefile.rb +1 -1
  20. data/lib/puppet/file_system/windows.rb +4 -4
  21. data/lib/puppet/file_system.rb +3 -2
  22. data/lib/puppet/forge.rb +1 -1
  23. data/lib/puppet/functions/versioncmp.rb +6 -2
  24. data/lib/puppet/graph/simple_graph.rb +2 -1
  25. data/lib/puppet/http/client.rb +1 -1
  26. data/lib/puppet/http/redirector.rb +5 -0
  27. data/lib/puppet/indirector/catalog/compiler.rb +3 -3
  28. data/lib/puppet/indirector/facts/facter.rb +6 -6
  29. data/lib/puppet/indirector/indirection.rb +1 -1
  30. data/lib/puppet/module_tool/applications/uninstaller.rb +1 -1
  31. data/lib/puppet/module_tool/applications/upgrader.rb +1 -1
  32. data/lib/puppet/pal/pal_impl.rb +1 -1
  33. data/lib/puppet/parser/resource.rb +1 -1
  34. data/lib/puppet/parser/scope.rb +8 -7
  35. data/lib/puppet/parser/templatewrapper.rb +1 -0
  36. data/lib/puppet/pops/evaluator/closure.rb +7 -5
  37. data/lib/puppet/pops/evaluator/runtime3_resource_support.rb +1 -0
  38. data/lib/puppet/pops/lookup/lookup_adapter.rb +3 -2
  39. data/lib/puppet/pops/model/ast.rb +1 -0
  40. data/lib/puppet/pops/model/factory.rb +14 -13
  41. data/lib/puppet/pops/parser/code_merger.rb +4 -4
  42. data/lib/puppet/pops/parser/egrammar.ra +4 -2
  43. data/lib/puppet/pops/parser/eparser.rb +909 -894
  44. data/lib/puppet/pops/parser/lexer2.rb +69 -68
  45. data/lib/puppet/pops/parser/slurp_support.rb +1 -0
  46. data/lib/puppet/pops/serialization/to_data_converter.rb +6 -18
  47. data/lib/puppet/pops/serialization/to_stringified_converter.rb +1 -1
  48. data/lib/puppet/pops/types/type_formatter.rb +7 -6
  49. data/lib/puppet/pops/types/types.rb +1 -1
  50. data/lib/puppet/pops/validation/checker4_0.rb +7 -2
  51. data/lib/puppet/provider/aix_object.rb +1 -1
  52. data/lib/puppet/provider/group/groupadd.rb +5 -2
  53. data/lib/puppet/provider/package/pkg.rb +11 -1
  54. data/lib/puppet/provider/package/puppet_gem.rb +1 -1
  55. data/lib/puppet/provider/package/puppetserver_gem.rb +1 -1
  56. data/lib/puppet/provider/package/yum.rb +1 -1
  57. data/lib/puppet/provider/service/base.rb +1 -1
  58. data/lib/puppet/provider/service/init.rb +10 -9
  59. data/lib/puppet/provider/service/launchd.rb +1 -1
  60. data/lib/puppet/provider/service/redhat.rb +1 -1
  61. data/lib/puppet/provider/service/smf.rb +3 -3
  62. data/lib/puppet/provider/service/systemd.rb +1 -1
  63. data/lib/puppet/provider/service/upstart.rb +5 -5
  64. data/lib/puppet/provider/user/aix.rb +44 -1
  65. data/lib/puppet/provider/user/directoryservice.rb +1 -1
  66. data/lib/puppet/provider/user/useradd.rb +30 -7
  67. data/lib/puppet/provider.rb +1 -1
  68. data/lib/puppet/reference/providers.rb +2 -2
  69. data/lib/puppet/resource/catalog.rb +1 -1
  70. data/lib/puppet/resource/type_collection.rb +2 -1
  71. data/lib/puppet/resource.rb +38 -5
  72. data/lib/puppet/runtime.rb +11 -1
  73. data/lib/puppet/settings/file_setting.rb +3 -8
  74. data/lib/puppet/settings.rb +2 -2
  75. data/lib/puppet/ssl/verifier.rb +3 -1
  76. data/lib/puppet/test/test_helper.rb +4 -1
  77. data/lib/puppet/transaction/persistence.rb +22 -12
  78. data/lib/puppet/type/exec.rb +9 -1
  79. data/lib/puppet/type/file/data_sync.rb +1 -1
  80. data/lib/puppet/type/file/group.rb +8 -1
  81. data/lib/puppet/type/file/owner.rb +8 -1
  82. data/lib/puppet/type/group.rb +0 -1
  83. data/lib/puppet/type/resources.rb +1 -1
  84. data/lib/puppet/type/service.rb +8 -3
  85. data/lib/puppet/type/user.rb +40 -39
  86. data/lib/puppet/util/autoload.rb +1 -1
  87. data/lib/puppet/util/command_line.rb +1 -1
  88. data/lib/puppet/util/filetype.rb +2 -2
  89. data/lib/puppet/util/json.rb +20 -0
  90. data/lib/puppet/util/log.rb +8 -4
  91. data/lib/puppet/util/logging.rb +1 -25
  92. data/lib/puppet/util/monkey_patches.rb +26 -2
  93. data/lib/puppet/util/package.rb +25 -16
  94. data/lib/puppet/util/pidlock.rb +1 -1
  95. data/lib/puppet/util/rdoc/parser/puppet_parser_core.rb +1 -1
  96. data/lib/puppet/util/suidmanager.rb +1 -2
  97. data/lib/puppet/util/tagging.rb +1 -0
  98. data/lib/puppet/util/windows/service.rb +0 -5
  99. data/lib/puppet/util/windows/user.rb +0 -1
  100. data/lib/puppet/util/windows.rb +3 -0
  101. data/lib/puppet/util/yaml.rb +11 -0
  102. data/lib/puppet/util.rb +4 -3
  103. data/lib/puppet/version.rb +1 -1
  104. data/lib/puppet.rb +3 -6
  105. data/locales/puppet.pot +265 -239
  106. data/man/man5/puppet.conf.5 +18 -2
  107. data/man/man8/puppet-agent.8 +4 -1
  108. data/man/man8/puppet-apply.8 +1 -1
  109. data/man/man8/puppet-catalog.8 +1 -1
  110. data/man/man8/puppet-config.8 +1 -1
  111. data/man/man8/puppet-describe.8 +1 -1
  112. data/man/man8/puppet-device.8 +1 -1
  113. data/man/man8/puppet-doc.8 +1 -1
  114. data/man/man8/puppet-epp.8 +1 -1
  115. data/man/man8/puppet-facts.8 +1 -1
  116. data/man/man8/puppet-filebucket.8 +1 -1
  117. data/man/man8/puppet-generate.8 +1 -1
  118. data/man/man8/puppet-help.8 +1 -1
  119. data/man/man8/puppet-lookup.8 +9 -6
  120. data/man/man8/puppet-module.8 +1 -1
  121. data/man/man8/puppet-node.8 +1 -1
  122. data/man/man8/puppet-parser.8 +1 -1
  123. data/man/man8/puppet-plugin.8 +1 -1
  124. data/man/man8/puppet-report.8 +1 -1
  125. data/man/man8/puppet-resource.8 +1 -1
  126. data/man/man8/puppet-script.8 +1 -1
  127. data/man/man8/puppet-ssl.8 +1 -1
  128. data/man/man8/puppet.8 +2 -2
  129. data/spec/fixtures/integration/application/agent/cached_deferred_catalog.json +2 -1
  130. data/spec/fixtures/unit/forge/bacula.json +1 -1
  131. data/spec/integration/application/agent_spec.rb +44 -0
  132. data/spec/integration/application/lookup_spec.rb +29 -6
  133. data/spec/integration/configurer_spec.rb +1 -1
  134. data/spec/integration/indirector/facts/facter_spec.rb +3 -3
  135. data/spec/integration/parser/pcore_resource_spec.rb +20 -0
  136. data/spec/integration/transaction/report_spec.rb +1 -1
  137. data/spec/integration/type/file_spec.rb +2 -2
  138. data/spec/integration/type/package_spec.rb +6 -6
  139. data/spec/integration/util/rdoc/parser_spec.rb +1 -1
  140. data/spec/integration/util/windows/process_spec.rb +1 -9
  141. data/spec/shared_contexts/l10n.rb +5 -0
  142. data/spec/unit/application/apply_spec.rb +76 -56
  143. data/spec/unit/application/lookup_spec.rb +131 -10
  144. data/spec/unit/application/resource_spec.rb +29 -0
  145. data/spec/unit/concurrent/thread_local_singleton_spec.rb +39 -0
  146. data/spec/unit/configurer_spec.rb +113 -28
  147. data/spec/unit/facter_impl_spec.rb +31 -0
  148. data/spec/unit/file_bucket/dipper_spec.rb +2 -2
  149. data/spec/unit/file_system/uniquefile_spec.rb +7 -1
  150. data/spec/unit/file_system_spec.rb +41 -4
  151. data/spec/unit/forge/module_release_spec.rb +3 -3
  152. data/spec/unit/functions/lookup_spec.rb +64 -0
  153. data/spec/unit/functions/versioncmp_spec.rb +40 -4
  154. data/spec/unit/http/client_spec.rb +58 -1
  155. data/spec/unit/indirector/indirection_spec.rb +10 -3
  156. data/spec/unit/network/formats_spec.rb +6 -0
  157. data/spec/unit/pops/parser/parse_containers_spec.rb +2 -2
  158. data/spec/unit/pops/serialization/to_from_hr_spec.rb +0 -58
  159. data/spec/unit/pops/serialization/to_stringified_spec.rb +5 -0
  160. data/spec/unit/pops/types/type_calculator_spec.rb +6 -0
  161. data/spec/unit/pops/validator/validator_spec.rb +5 -0
  162. data/spec/unit/provider/package/gem_spec.rb +1 -1
  163. data/spec/unit/provider/package/pip2_spec.rb +1 -1
  164. data/spec/unit/provider/package/pip3_spec.rb +1 -1
  165. data/spec/unit/provider/package/pip_spec.rb +1 -1
  166. data/spec/unit/provider/package/pkg_spec.rb +15 -0
  167. data/spec/unit/provider/package/puppet_gem_spec.rb +1 -1
  168. data/spec/unit/provider/package/puppetserver_gem_spec.rb +1 -1
  169. data/spec/unit/provider/service/gentoo_spec.rb +6 -5
  170. data/spec/unit/provider/service/init_spec.rb +15 -9
  171. data/spec/unit/provider/service/openwrt_spec.rb +21 -29
  172. data/spec/unit/provider/service/redhat_spec.rb +3 -2
  173. data/spec/unit/provider/user/aix_spec.rb +100 -0
  174. data/spec/unit/provider/user/directoryservice_spec.rb +1 -1
  175. data/spec/unit/provider/user/useradd_spec.rb +40 -0
  176. data/spec/unit/provider_spec.rb +4 -4
  177. data/spec/unit/puppet_spec.rb +12 -4
  178. data/spec/unit/resource/catalog_spec.rb +14 -1
  179. data/spec/unit/resource_spec.rb +58 -2
  180. data/spec/unit/settings/file_setting_spec.rb +10 -7
  181. data/spec/unit/transaction/persistence_spec.rb +51 -0
  182. data/spec/unit/type/file/group_spec.rb +7 -0
  183. data/spec/unit/type/file/owner_spec.rb +7 -0
  184. data/spec/unit/type/service_spec.rb +27 -0
  185. data/spec/unit/type/user_spec.rb +0 -45
  186. data/spec/unit/type_spec.rb +2 -2
  187. data/spec/unit/util/autoload_spec.rb +25 -8
  188. data/spec/unit/util/json_spec.rb +126 -0
  189. data/spec/unit/util/logging_spec.rb +2 -0
  190. data/spec/unit/util/yaml_spec.rb +37 -13
  191. data/tasks/parallel.rake +3 -3
  192. metadata +17 -4
@@ -7,7 +7,10 @@ require_relative '../../../puppet/error'
7
7
  Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameService::ObjectAdd do
8
8
  desc "User management via `useradd` and its ilk. Note that you will need to
9
9
  install Ruby's shadow password library (often known as `ruby-libshadow`)
10
- if you wish to manage user passwords."
10
+ if you wish to manage user passwords.
11
+
12
+ To use the `forcelocal` parameter, you need to install the `libuser` package (providing
13
+ `/usr/sbin/lgroupadd` and `/usr/sbin/luseradd`)."
11
14
 
12
15
  commands :add => "useradd", :delete => "userdel", :modify => "usermod", :password => "chage", :chpasswd => "chpasswd"
13
16
 
@@ -21,13 +24,13 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
21
24
  options :expiry, :method => :sp_expire,
22
25
  :munge => proc { |value|
23
26
  if value == :absent
24
- if Facter.value(:operatingsystem)=='SLES' && Facter.value(:operatingsystemmajrelease) == "11"
27
+ if Puppet.runtime[:facter].value(:operatingsystem)=='SLES' && Puppet.runtime[:facter].value(:operatingsystemmajrelease) == "11"
25
28
  -1
26
29
  else
27
30
  ''
28
31
  end
29
32
  else
30
- case Facter.value(:operatingsystem)
33
+ case Puppet.runtime[:facter].value(:operatingsystem)
31
34
  when 'Solaris'
32
35
  # Solaris uses %m/%d/%Y for useradd/usermod
33
36
  expiry_year, expiry_month, expiry_day = value.split('-')
@@ -69,6 +72,16 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
69
72
  get(:comment)
70
73
  end
71
74
 
75
+ def shell
76
+ return localshell if @resource.forcelocal?
77
+ get(:shell)
78
+ end
79
+
80
+ def home
81
+ return localhome if @resource.forcelocal?
82
+ get(:home)
83
+ end
84
+
72
85
  def groups
73
86
  return localgroups if @resource.forcelocal?
74
87
  super
@@ -120,6 +133,16 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
120
133
  user[:gecos]
121
134
  end
122
135
 
136
+ def localshell
137
+ user = finduser(:account, resource[:name])
138
+ user[:shell]
139
+ end
140
+
141
+ def localhome
142
+ user = finduser(:account, resource[:name])
143
+ user[:directory]
144
+ end
145
+
123
146
  def localgroups
124
147
  @groups_of ||= {}
125
148
  group_file = '/etc/group'
@@ -193,7 +216,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
193
216
  end
194
217
 
195
218
  has_features :manages_homedir, :allows_duplicates, :manages_expiry
196
- has_features :system_users unless %w{HP-UX Solaris}.include? Facter.value(:operatingsystem)
219
+ has_features :system_users unless %w{HP-UX Solaris}.include? Puppet.runtime[:facter].value(:operatingsystem)
197
220
 
198
221
  has_features :manages_passwords, :manages_password_age if Puppet.features.libshadow?
199
222
  has_features :manages_shell
@@ -228,8 +251,8 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
228
251
  # libuser does not implement the -m flag
229
252
  cmd << "-m" unless @resource.forcelocal?
230
253
  else
231
- osfamily = Facter.value(:osfamily)
232
- osversion = Facter.value(:operatingsystemmajrelease).to_i
254
+ osfamily = Puppet.runtime[:facter].value(:osfamily)
255
+ osversion = Puppet.runtime[:facter].value(:operatingsystemmajrelease).to_i
233
256
  # SLES 11 uses pwdutils instead of shadow, which does not have -M
234
257
  # Solaris and OpenBSD use different useradd flavors
235
258
  unless osfamily =~ /Solaris|OpenBSD/ || osfamily == 'Suse' && osversion <= 11
@@ -327,7 +350,7 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
327
350
  cmd = [command(:delete)]
328
351
  end
329
352
  # Solaris `userdel -r` will fail if the homedir does not exist.
330
- if @resource.managehome? && (('Solaris' != Facter.value(:operatingsystem)) || Dir.exist?(Dir.home(@resource[:name])))
353
+ if @resource.managehome? && (('Solaris' != Puppet.runtime[:facter].value(:operatingsystem)) || Dir.exist?(Dir.home(@resource[:name])))
331
354
  cmd << '-r'
332
355
  end
333
356
  cmd << @resource[:name]
@@ -289,7 +289,7 @@ class Puppet::Provider
289
289
  # values. Given one or more Regexp instances, fact is compared via the basic
290
290
  # pattern-matching operator.
291
291
  def self.fact_match(fact, values)
292
- fact_val = Facter.value(fact).to_s.downcase
292
+ fact_val = Puppet.runtime[:facter].value(fact).to_s.downcase
293
293
  if fact_val.empty?
294
294
  return false
295
295
  else
@@ -15,7 +15,7 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
15
15
  # Throw some facts in there, so we know where the report is from.
16
16
  ["Ruby Version", "Puppet Version", "Operating System", "Operating System Release"].each do |label|
17
17
  name = label.gsub(/\s+/, '')
18
- value = Facter.value(name)
18
+ value = Puppet.runtime[:facter].value(name)
19
19
  ret << option(label, value)
20
20
  end
21
21
  ret << "\n"
@@ -61,7 +61,7 @@ providers = Puppet::Util::Reference.newreference :providers, :title => "Provider
61
61
  if Puppet.settings.valid?(name)
62
62
  details << _(" - Setting %{name} (currently %{value}) not in list %{facts}\n") % { name: name, value: Puppet.settings.value(name).inspect, facts: facts.join(", ") }
63
63
  else
64
- details << _(" - Fact %{name} (currently %{value}) not in list %{facts}\n") % { name: name, value: Facter.value(name).inspect, facts: facts.join(", ") }
64
+ details << _(" - Fact %{name} (currently %{value}) not in list %{facts}\n") % { name: name, value: Puppet.runtime[:facter].value(name).inspect, facts: facts.join(", ") }
65
65
  end
66
66
  end
67
67
  when :true
@@ -313,7 +313,7 @@ class Puppet::Resource::Catalog < Puppet::Graph::SimpleGraph
313
313
  super()
314
314
  @name = name
315
315
  @catalog_uuid = SecureRandom.uuid
316
- @catalog_format = 1
316
+ @catalog_format = 2
317
317
  @metadata = {}
318
318
  @recursive_metadata = {}
319
319
  @classes = []
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require_relative '../../puppet/parser/type_loader'
2
3
  require_relative '../../puppet/util/file_watcher'
3
4
  require_relative '../../puppet/util/warnings'
@@ -179,7 +180,7 @@ class Puppet::Resource::TypeCollection
179
180
 
180
181
  private
181
182
 
182
- COLON_COLON = "::".freeze
183
+ COLON_COLON = "::"
183
184
 
184
185
  # Resolve namespaces and find the given object. Autoload it if
185
186
  # necessary.
@@ -11,7 +11,7 @@ class Puppet::Resource
11
11
  include Puppet::Util::PsychSupport
12
12
 
13
13
  include Enumerable
14
- attr_accessor :file, :line, :catalog, :exported, :virtual, :strict
14
+ attr_accessor :file, :line, :catalog, :exported, :virtual, :strict, :kind
15
15
  attr_reader :type, :title, :parameters
16
16
 
17
17
  # @!attribute [rw] sensitive_parameters
@@ -29,10 +29,15 @@ class Puppet::Resource
29
29
  EMPTY_ARRAY = [].freeze
30
30
  EMPTY_HASH = {}.freeze
31
31
 
32
- ATTRIBUTES = [:file, :line, :exported].freeze
32
+ ATTRIBUTES = [:file, :line, :exported, :kind].freeze
33
33
  TYPE_CLASS = 'Class'.freeze
34
34
  TYPE_NODE = 'Node'.freeze
35
35
 
36
+ CLASS_STRING = 'class'.freeze
37
+ DEFINED_TYPE_STRING = 'defined_type'.freeze
38
+ COMPILABLE_TYPE_STRING = 'compilable_type'.freeze
39
+ UNKNOWN_TYPE_STRING = 'unknown'.freeze
40
+
36
41
  PCORE_TYPE_KEY = '__ptype'.freeze
37
42
  VALUE_KEY = 'value'.freeze
38
43
 
@@ -193,6 +198,18 @@ class Puppet::Resource
193
198
  resource_type.is_a?(Puppet::CompilableResourceType)
194
199
  end
195
200
 
201
+ def self.to_kind(resource_type)
202
+ if resource_type == CLASS_STRING
203
+ CLASS_STRING
204
+ elsif resource_type.is_a?(Puppet::Resource::Type) && resource_type.type == :definition
205
+ DEFINED_TYPE_STRING
206
+ elsif resource_type.is_a?(Puppet::CompilableResourceType)
207
+ COMPILABLE_TYPE_STRING
208
+ else
209
+ UNKNOWN_TYPE_STRING
210
+ end
211
+ end
212
+
196
213
  # Iterate over each param/value pair, as required for Enumerable.
197
214
  def each
198
215
  parameters.each { |p,v| yield p, v }
@@ -247,6 +264,7 @@ class Puppet::Resource
247
264
  src = type
248
265
  self.file = src.file
249
266
  self.line = src.line
267
+ self.kind = src.kind
250
268
  self.exported = src.exported
251
269
  self.virtual = src.virtual
252
270
  self.set_tags(src)
@@ -309,6 +327,7 @@ class Puppet::Resource
309
327
 
310
328
  rt = resource_type
311
329
 
330
+ self.kind = self.class.to_kind(rt) unless kind
312
331
  if strict? && rt.nil?
313
332
  if self.class?
314
333
  raise ArgumentError, _("Could not find declared class %{title}") % { title: title }
@@ -468,10 +487,24 @@ class Puppet::Resource
468
487
  ref
469
488
  end
470
489
 
471
- # Convert our resource to a RAL resource instance. Creates component
472
- # instances for resource types that don't exist.
490
+ # Convert our resource to a RAL resource instance. Creates component
491
+ # instances for resource types that are not of a compilable_type kind. In case
492
+ # the resource doesn’t exist and it’s compilable_type kind, raise an error.
493
+ # There are certain cases where a resource won't be in a catalog, such as
494
+ # when we create a resource directly by using Puppet::Resource.new(...), so we
495
+ # must check its kind before deciding whether the catalog format is of an older
496
+ # version or not.
473
497
  def to_ral
474
- typeklass = Puppet::Type.type(self.type) || Puppet::Type.type(:component)
498
+ if self.kind == COMPILABLE_TYPE_STRING
499
+ typeklass = Puppet::Type.type(self.type)
500
+ elsif self.catalog && self.catalog.catalog_format >= 2
501
+ typeklass = Puppet::Type.type(:component)
502
+ else
503
+ typeklass = Puppet::Type.type(self.type) || Puppet::Type.type(:component)
504
+ end
505
+
506
+ raise(Puppet::Error, "Resource type '#{self.type}' was not found") unless typeklass
507
+
475
508
  typeklass.new(self)
476
509
  end
477
510
 
@@ -1,4 +1,5 @@
1
1
  require_relative '../puppet/http'
2
+ require_relative '../puppet/facter_impl'
2
3
  require 'singleton'
3
4
 
4
5
  # Provides access to runtime implementations.
@@ -16,11 +17,20 @@ class Puppet::Runtime
16
17
  else
17
18
  Puppet::HTTP::ExternalClient.new(klass)
18
19
  end
19
- end
20
+ end,
21
+ facter: proc { Puppet::FacterImpl.new }
20
22
  }
21
23
  end
22
24
  private :initialize
23
25
 
26
+ # Loads all runtime implementations.
27
+ #
28
+ # @return Array[Symbol] the names of loaded implementations
29
+ # @api private
30
+ def load_services
31
+ @runtime_services.keys.each { |key| self[key] }
32
+ end
33
+
24
34
  # Get a runtime implementation.
25
35
  #
26
36
  # @param name [Symbol] the name of the implementation
@@ -53,7 +53,7 @@ class Puppet::Settings::FileSetting < Puppet::Settings::StringSetting
53
53
  end
54
54
  end
55
55
 
56
- attr_accessor :mode, :create
56
+ attr_accessor :mode
57
57
 
58
58
  def initialize(args)
59
59
  @group = Unspecified.new
@@ -61,11 +61,6 @@ class Puppet::Settings::FileSetting < Puppet::Settings::StringSetting
61
61
  super(args)
62
62
  end
63
63
 
64
- # Should we create files, rather than just directories?
65
- def create_files?
66
- create
67
- end
68
-
69
64
  # @param value [String] the group to use on the created file (can only be "root" or "service")
70
65
  # @api public
71
66
  def group=(value)
@@ -135,8 +130,8 @@ class Puppet::Settings::FileSetting < Puppet::Settings::StringSetting
135
130
  # Make sure the paths are fully qualified.
136
131
  path = File.expand_path(path)
137
132
 
138
- return nil unless type == :directory or create_files? or Puppet::FileSystem.exist?(path)
139
- return nil if path =~ /^\/dev/ or path =~ /^[A-Z]:\/dev/i
133
+ return nil unless type == :directory || Puppet::FileSystem.exist?(path)
134
+ return nil if path =~ /^\/dev/ || path =~ /^[A-Z]:\/dev/i
140
135
 
141
136
  resource = Puppet::Resource.new(:file, path)
142
137
 
@@ -79,11 +79,11 @@ class Puppet::Settings
79
79
  end
80
80
 
81
81
  def self.hostname_fact()
82
- Facter.value :hostname
82
+ Puppet.runtime[:facter].value :hostname
83
83
  end
84
84
 
85
85
  def self.domain_fact()
86
- Facter.value :domain
86
+ Puppet.runtime[:facter].value :domain
87
87
  end
88
88
 
89
89
  def self.default_config_file_name
@@ -117,7 +117,9 @@ class Puppet::SSL::Verifier
117
117
  return false
118
118
  end
119
119
 
120
- when OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH # new in ruby-openssl 2.2.0/ruby 3.0
120
+ # ruby-openssl#74ef8c0cc56b840b772240f2ee2b0fc0aafa2743 now sets the
121
+ # store_context error when the cert is mismatched
122
+ when OpenSSL::X509::V_ERR_HOSTNAME_MISMATCH
121
123
  @last_error = Puppet::SSL::CertMismatchError.new(peer_cert, @hostname)
122
124
  return false
123
125
 
@@ -142,7 +142,9 @@ module Puppet::Test
142
142
  },
143
143
  "Context for specs")
144
144
 
145
- Puppet.runtime.clear
145
+ # trigger `require 'facter'`
146
+ Puppet.runtime[:facter]
147
+
146
148
  Puppet::Parser::Functions.reset
147
149
  Puppet::Application.clear!
148
150
  Puppet::Util::Profiler.clear
@@ -166,6 +168,7 @@ module Puppet::Test
166
168
 
167
169
  Puppet::Util::Storage.clear
168
170
  Puppet::Util::ExecutionStub.reset
171
+ Puppet.runtime.clear
169
172
 
170
173
  Puppet.clear_deprecation_warnings
171
174
 
@@ -6,6 +6,26 @@ require_relative '../../puppet/util/yaml'
6
6
  # as calculating corrective_change).
7
7
  # @api private
8
8
  class Puppet::Transaction::Persistence
9
+
10
+ def self.allowed_classes
11
+ @allowed_classes ||= [
12
+ Symbol,
13
+ Time,
14
+ Regexp,
15
+ # URI is excluded, because it serializes all instance variables including the
16
+ # URI parser. Better to serialize the URL encoded representation.
17
+ SemanticPuppet::Version,
18
+ # SemanticPuppet::VersionRange has many nested classes and is unlikely to be
19
+ # used directly, so ignore it
20
+ Puppet::Pops::Time::Timestamp,
21
+ Puppet::Pops::Time::TimeData,
22
+ Puppet::Pops::Time::Timespan,
23
+ Puppet::Pops::Types::PBinaryType::Binary,
24
+ # Puppet::Pops::Types::PSensitiveType::Sensitive values are excluded from
25
+ # the persistence store, ignore it.
26
+ ].freeze
27
+ end
28
+
9
29
  def initialize
10
30
  @old_data = {}
11
31
  @new_data = {"resources" => {}}
@@ -62,7 +82,7 @@ class Puppet::Transaction::Persistence
62
82
  result = nil
63
83
  Puppet::Util.benchmark(:debug, _("Loaded transaction store file in %{seconds} seconds")) do
64
84
  begin
65
- result = Puppet::Util::Yaml.safe_load_file(filename, [Symbol, Time])
85
+ result = Puppet::Util::Yaml.safe_load_file(filename, self.class.allowed_classes)
66
86
  rescue Puppet::Util::Yaml::YamlLoadError => detail
67
87
  Puppet.log_exception(detail, _("Transaction store file %{filename} is corrupt (%{detail}); replacing") % { filename: filename, detail: detail })
68
88
 
@@ -87,17 +107,7 @@ class Puppet::Transaction::Persistence
87
107
 
88
108
  # Save data from internal class to persistence store on disk.
89
109
  def save
90
- converted_data = Puppet::Pops::Serialization::ToDataConverter.convert(
91
- @new_data, {
92
- symbol_as_string: false,
93
- local_reference: false,
94
- type_by_reference: true,
95
- force_symbol: true,
96
- silence_warnings: true,
97
- message_prefix: to_s
98
- }
99
- )
100
- Puppet::Util::Yaml.dump(converted_data, Puppet[:transactionstorefile])
110
+ Puppet::Util::Yaml.dump(@new_data, Puppet[:transactionstorefile])
101
111
  end
102
112
 
103
113
  # Use the catalog and run_mode to determine if persistence should be enabled or not
@@ -201,7 +201,15 @@ module Puppet
201
201
  any output is logged at the `err` log level.
202
202
 
203
203
  Multiple `exec` resources can use the same `command` value; Puppet
204
- only uses the resource title to ensure `exec`s are unique."
204
+ only uses the resource title to ensure `exec`s are unique.
205
+
206
+ On *nix platforms, the command can be specified as an array of
207
+ strings and Puppet will invoke it using the more secure method of
208
+ parameterized system calls. For example, rather than executing the
209
+ malicious injected code, this command will echo it out:
210
+
211
+ command => ['/bin/echo', 'hello world; rm -rf /']
212
+ "
205
213
 
206
214
  validate do |command|
207
215
  unless command.is_a?(String) || command.is_a?(Array)
@@ -79,7 +79,7 @@ module Puppet
79
79
  return :absent unless stat
80
80
  ftype = stat.ftype
81
81
  # Don't even try to manage the content on directories or links
82
- return nil if ["directory","link"].include?(ftype)
82
+ return nil if ['directory', 'link', 'fifo', 'socket'].include?(ftype)
83
83
 
84
84
  begin
85
85
  resource.parameter(:checksum).sum_file(resource[:path])
@@ -23,7 +23,14 @@ module Puppet
23
23
  # evaluate this property, because they might be added during the catalog
24
24
  # apply.
25
25
  @should.map! do |val|
26
- provider.name2gid(val) or raise "Could not find group #{val}"
26
+ gid = provider.name2gid(val)
27
+ if gid
28
+ gid
29
+ elsif provider.resource.noop?
30
+ return false
31
+ else
32
+ raise "Could not find group #{val}"
33
+ end
27
34
  end
28
35
 
29
36
  @should.include?(current)
@@ -18,7 +18,14 @@ module Puppet
18
18
  # evaluate this property, because they might be added during the catalog
19
19
  # apply.
20
20
  @should.map! do |val|
21
- provider.name2uid(val) or raise "Could not find user #{val}"
21
+ uid = provider.name2uid(val)
22
+ if uid
23
+ uid
24
+ elsif provider.resource.noop?
25
+ return false
26
+ else
27
+ raise "Could not find user #{val}"
28
+ end
22
29
  end
23
30
 
24
31
  return true if @should.include?(current)
@@ -1,5 +1,4 @@
1
1
  require 'etc'
2
- require 'facter'
3
2
  require_relative '../../puppet/property/keyvalue'
4
3
  require_relative '../../puppet/parameter/boolean'
5
4
 
@@ -175,7 +175,7 @@ Puppet::Type.newtype(:resources) do
175
175
  end
176
176
 
177
177
  # Otherwise, use a sensible default based on the OS family
178
- @system_users_max_uid ||= case Facter.value(:osfamily)
178
+ @system_users_max_uid ||= case Puppet.runtime[:facter].value(:osfamily)
179
179
  when 'OpenBSD', 'FreeBSD'
180
180
  999
181
181
  else
@@ -272,9 +272,14 @@ module Puppet
272
272
 
273
273
  newparam(:timeout, :required_features => :configurable_timeout) do
274
274
  desc "Specify an optional minimum timeout (in seconds) for puppet to wait when syncing service properties"
275
- defaultto { provider.class.respond_to?(:default_timeout) ? provider.default_timeout : 10 }
276
- validate do |value|
277
- if (not value.is_a? Integer) || value < 1
275
+ defaultto { provider.respond_to?(:default_timeout) ? provider.default_timeout : 10 }
276
+
277
+ munge do |value|
278
+ begin
279
+ value = value.to_i
280
+ raise if value < 1
281
+ value
282
+ rescue
278
283
  raise Puppet::Error.new(_("\"%{value}\" is not a positive integer: the timeout parameter must be specified as a positive integer") % { value: value })
279
284
  end
280
285
  end
@@ -1,5 +1,4 @@
1
1
  require 'etc'
2
- require 'facter'
3
2
  require_relative '../../puppet/parameter/boolean'
4
3
  require_relative '../../puppet/property/list'
5
4
  require_relative '../../puppet/property/ordered_list'
@@ -67,7 +66,6 @@ module Puppet
67
66
  newproperty(:ensure, :parent => Puppet::Property::Ensure) do
68
67
  newvalue(:present, :event => :user_created) do
69
68
  provider.create
70
- @resource.generate
71
69
  end
72
70
 
73
71
  newvalue(:absent, :event => :user_removed) do
@@ -696,7 +694,6 @@ module Puppet
696
694
 
697
695
  def generate
698
696
  if !self[:purge_ssh_keys].empty? && self[:purge_ssh_keys] != :false
699
- return [] if self[:ensure] == :present && !provider.exists?
700
697
  if Puppet::Type.type(:ssh_authorized_key).nil?
701
698
  warning _("Ssh_authorized_key type is not available. Cannot purge SSH keys.")
702
699
  else
@@ -745,6 +742,45 @@ module Puppet
745
742
  end
746
743
  raise ArgumentError, _("purge_ssh_keys must be true, false, or an array of file names, not %{value}") % { value: value.inspect }
747
744
  end
745
+
746
+ munge do |value|
747
+ # Resolve string, boolean and symbol forms of true and false to a
748
+ # single representation.
749
+ case value
750
+ when :false, false, "false"
751
+ []
752
+ when :true, true, "true"
753
+ home = homedir
754
+ home ? [ "#{home}/.ssh/authorized_keys" ] : []
755
+ else
756
+ # value can be a string or array - munge each value
757
+ [ value ].flatten.map do |entry|
758
+ authorized_keys_path(entry)
759
+ end.compact
760
+ end
761
+ end
762
+
763
+ private
764
+
765
+ def homedir
766
+ resource[:home] || Dir.home(resource[:name])
767
+ rescue ArgumentError
768
+ Puppet.debug("User '#{resource[:name]}' does not exist")
769
+ nil
770
+ end
771
+
772
+ def authorized_keys_path(entry)
773
+ return entry unless entry.match?(%r{^(?:~|%h)/})
774
+
775
+ # if user doesn't exist (yet), ignore nonexistent homedir
776
+ home = homedir
777
+ return nil unless home
778
+
779
+ # compiler freezes "value" so duplicate using a gsub, second mutating gsub! is then ok
780
+ entry = entry.gsub(%r{^~/}, "#{home}/")
781
+ entry.gsub!(%r{^%h/}, "#{home}/")
782
+ entry
783
+ end
748
784
  end
749
785
 
750
786
  newproperty(:loginclass, :required_features => :manages_loginclass) do
@@ -766,7 +802,7 @@ module Puppet
766
802
  # @see generate
767
803
  # @api private
768
804
  def find_unmanaged_keys
769
- munged_unmanaged_keys.
805
+ self[:purge_ssh_keys].
770
806
  select { |f| File.readable?(f) }.
771
807
  map { |f| unknown_keys_in_file(f) }.
772
808
  flatten.each do |res|
@@ -778,41 +814,6 @@ module Puppet
778
814
  end
779
815
  end
780
816
 
781
- def munged_unmanaged_keys
782
- value = self[:purge_ssh_keys]
783
-
784
- # Resolve string, boolean and symbol forms of true and false to a
785
- # single representation.
786
- test_sym = value.to_s.intern
787
- value = test_sym if [:true, :false].include? test_sym
788
-
789
- return [] if value == :false
790
-
791
- home = self[:home]
792
- begin
793
- home ||= provider.home
794
- rescue
795
- Puppet.debug("User '#{self[:name]}' does not exist")
796
- end
797
-
798
- if home.to_s.empty? || !Dir.exist?(home.to_s)
799
- if value == :true || [ value ].flatten.any? { |v| v.start_with?('~/', '%h/') }
800
- Puppet.debug("User '#{self[:name]}' has no home directory set to purge ssh keys from.")
801
- return []
802
- end
803
- end
804
-
805
- return [ "#{home}/.ssh/authorized_keys" ] if value == :true
806
-
807
- # value is an array - munge each value
808
- [ value ].flatten.map do |entry|
809
- # make sure frozen value is duplicated by using a gsub, second mutating gsub! is then ok
810
- entry = entry.gsub(/^~\//, "#{home}/")
811
- entry.gsub!(/^%h\//, "#{home}/")
812
- entry
813
- end
814
- end
815
-
816
817
  # Parse an ssh authorized keys file superficially, extract the comments
817
818
  # on the keys. These are considered names of possible ssh_authorized_keys
818
819
  # resources. Keys that are managed by the present catalog are ignored.
@@ -117,7 +117,7 @@ class Puppet::Util::Autoload
117
117
 
118
118
  # @api private
119
119
  def files_in_dir(dir, path)
120
- dir = Pathname.new(File.expand_path(dir))
120
+ dir = Pathname.new(Puppet::FileSystem.expand_path(dir))
121
121
  Dir.glob(File.join(dir, path, "*.rb")).collect do |file|
122
122
  Pathname.new(file).relative_path_from(dir).to_s
123
123
  end
@@ -135,7 +135,7 @@ module Puppet
135
135
 
136
136
  # Puppet requires Facter, which initializes its lookup paths. Reset Facter to
137
137
  # pickup the new $LOAD_PATH.
138
- Facter.reset
138
+ Puppet.runtime[:facter].reset
139
139
  end
140
140
  end
141
141
 
@@ -215,7 +215,7 @@ class Puppet::Util::FileType
215
215
  # Remove a specific @path's cron tab.
216
216
  def remove
217
217
  cmd = "#{cmdbase} -r"
218
- if %w{Darwin FreeBSD DragonFly}.include?(Facter.value("operatingsystem"))
218
+ if %w{Darwin FreeBSD DragonFly}.include?(Puppet.runtime[:facter].value("operatingsystem"))
219
219
  cmd = "/bin/echo yes | #{cmd}"
220
220
  end
221
221
 
@@ -244,7 +244,7 @@ class Puppet::Util::FileType
244
244
  # Only add the -u flag when the @path is different. Fedora apparently
245
245
  # does not think I should be allowed to set the @path to my own user name
246
246
  def cmdbase
247
- if @uid == Puppet::Util::SUIDManager.uid || Facter.value(:operatingsystem) == "HP-UX"
247
+ if @uid == Puppet::Util::SUIDManager.uid || Puppet.runtime[:facter].value(:operatingsystem) == "HP-UX"
248
248
  return "crontab"
249
249
  else
250
250
  return "crontab -u #{@path}"