puppet 4.3.1 → 4.3.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of puppet might be problematic. Click here for more details.

Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/ext/build_defaults.yaml +1 -1
  3. data/lib/hiera/scope.rb +1 -1
  4. data/lib/puppet/application/lookup.rb +41 -43
  5. data/lib/puppet/data_providers/lookup_adapter.rb +73 -26
  6. data/lib/puppet/functions/lookup.rb +126 -150
  7. data/lib/puppet/functions/match.rb +1 -0
  8. data/lib/puppet/indirector/hiera.rb +3 -1
  9. data/lib/puppet/indirector/indirection.rb +6 -2
  10. data/lib/puppet/indirector/json.rb +2 -2
  11. data/lib/puppet/module.rb +3 -2
  12. data/lib/puppet/node.rb +11 -2
  13. data/lib/puppet/parser/compiler.rb +1 -8
  14. data/lib/puppet/parser/functions/lookup.rb +128 -149
  15. data/lib/puppet/parser/functions/match.rb +1 -0
  16. data/lib/puppet/plugins/data_providers/data_provider.rb +3 -2
  17. data/lib/puppet/pops/adapters.rb +43 -0
  18. data/lib/puppet/pops/evaluator/access_operator.rb +3 -3
  19. data/lib/puppet/pops/evaluator/closure.rb +51 -51
  20. data/lib/puppet/pops/evaluator/collector_transformer.rb +16 -0
  21. data/lib/puppet/pops/evaluator/runtime3_support.rb +11 -2
  22. data/lib/puppet/pops/functions/function.rb +6 -2
  23. data/lib/puppet/pops/issues.rb +16 -0
  24. data/lib/puppet/pops/loader/puppet_function_instantiator.rb +3 -2
  25. data/lib/puppet/pops/lookup.rb +3 -0
  26. data/lib/puppet/pops/lookup/explainer.rb +73 -3
  27. data/lib/puppet/pops/lookup/invocation.rb +21 -19
  28. data/lib/puppet/pops/model/factory.rb +153 -155
  29. data/lib/puppet/pops/model/model.rb +9 -0
  30. data/lib/puppet/pops/model/model_label_provider.rb +1 -0
  31. data/lib/puppet/pops/parser/evaluating_parser.rb +3 -3
  32. data/lib/puppet/pops/parser/lexer2.rb +411 -393
  33. data/lib/puppet/pops/parser/slurp_support.rb +5 -1
  34. data/lib/puppet/pops/types/type_calculator.rb +2 -6
  35. data/lib/puppet/pops/types/types.rb +3 -9
  36. data/lib/puppet/pops/validation/checker4_0.rb +36 -12
  37. data/lib/puppet/provider/group/windows_adsi.rb +2 -2
  38. data/lib/puppet/provider/package/pip.rb +11 -1
  39. data/lib/puppet/provider/package/rpm.rb +0 -1
  40. data/lib/puppet/provider/package/yum.rb +1 -1
  41. data/lib/puppet/provider/service/debian.rb +5 -18
  42. data/lib/puppet/provider/service/init.rb +7 -0
  43. data/lib/puppet/provider/service/launchd.rb +6 -0
  44. data/lib/puppet/provider/service/systemd.rb +1 -1
  45. data/lib/puppet/provider/user/windows_adsi.rb +2 -2
  46. data/lib/puppet/provider/yumrepo/inifile.rb +6 -3
  47. data/lib/puppet/resource/type.rb +2 -1
  48. data/lib/puppet/transaction/additional_resource_generator.rb +17 -3
  49. data/lib/puppet/type/group.rb +6 -2
  50. data/lib/puppet/util/windows.rb +4 -0
  51. data/lib/puppet/util/windows/adsi.rb +61 -24
  52. data/lib/puppet/util/windows/principal.rb +181 -0
  53. data/lib/puppet/util/windows/registry.rb +21 -15
  54. data/lib/puppet/util/windows/sid.rb +42 -11
  55. data/lib/puppet/version.rb +1 -1
  56. data/spec/fixtures/unit/application/environments/production/data/common.yaml +4 -0
  57. data/spec/fixtures/unit/application/environments/production/manifests/site.pp +1 -0
  58. data/spec/fixtures/unit/application/environments/puppet_func_provider/environment.conf +1 -0
  59. data/spec/fixtures/unit/application/environments/puppet_func_provider/functions/data.pp +10 -0
  60. data/spec/fixtures/unit/application/environments/puppet_func_provider/manifests/site.pp +1 -0
  61. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/data/common.yaml +4 -0
  62. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/data/specific.yaml +4 -0
  63. data/spec/fixtures/unit/data_providers/environments/hiera_module_config/hiera.yaml +7 -0
  64. data/spec/fixtures/unit/data_providers/environments/hiera_modules/data/common.yaml +4 -0
  65. data/spec/fixtures/unit/data_providers/environments/hiera_modules/data/specific.yaml +4 -0
  66. data/spec/fixtures/unit/data_providers/environments/hiera_modules/environment.conf +2 -0
  67. data/spec/fixtures/unit/data_providers/environments/hiera_modules/hiera.yaml +7 -0
  68. data/spec/fixtures/unit/data_providers/environments/hiera_modules/manifests/site.pp +1 -0
  69. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/data/common.yaml +6 -0
  70. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/hiera.yaml +5 -0
  71. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/manifests/init.pp +2 -0
  72. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/one/metadata.json +9 -0
  73. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/data/common.yaml +4 -0
  74. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/hiera.yaml +5 -0
  75. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/manifests/init.pp +3 -0
  76. data/spec/fixtures/unit/data_providers/environments/hiera_modules/modules/two/metadata.json +9 -0
  77. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/functions/usee_puppet.pp +3 -0
  78. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{usee → modules/usee}/lib/puppet/functions/usee/callee.rb +0 -0
  79. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/lib/puppet/functions/usee/usee_ruby.rb +6 -0
  80. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee/manifests/init.pp +6 -0
  81. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/usee2/lib/puppet/functions/usee2/callee.rb +5 -0
  82. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_puppet.pp +5 -0
  83. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_puppet_init.pp +5 -0
  84. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/functions/puppet_calling_ruby.pp +5 -0
  85. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{user → modules/user}/lib/puppet/functions/user/caller.rb +0 -0
  86. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/caller2.rb +5 -0
  87. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_puppet.rb +5 -0
  88. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_puppet_init.rb +5 -0
  89. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/lib/puppet/functions/user/ruby_calling_ruby.rb +5 -0
  90. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/modules/user/manifests/init.pp +81 -0
  91. data/spec/fixtures/unit/pops/loaders/loaders/dependent_modules_with_metadata/{user → modules/user}/metadata.json +2 -1
  92. data/spec/integration/parser/collection_spec.rb +8 -0
  93. data/spec/integration/util/windows/principal_spec.rb +115 -0
  94. data/spec/{unit → integration}/util/windows/registry_spec.rb +91 -1
  95. data/spec/integration/util/windows/security_spec.rb +2 -2
  96. data/spec/unit/application/lookup_spec.rb +138 -28
  97. data/spec/unit/data_providers/hiera_data_provider_spec.rb +182 -5
  98. data/spec/unit/face/epp_face_spec.rb +2 -2
  99. data/spec/unit/functions/epp_spec.rb +6 -6
  100. data/spec/unit/functions/inline_epp_spec.rb +4 -4
  101. data/spec/unit/functions/lookup_spec.rb +30 -3
  102. data/spec/unit/functions4_spec.rb +1 -1
  103. data/spec/unit/hiera/scope_spec.rb +5 -2
  104. data/spec/unit/indirector/json_spec.rb +1 -1
  105. data/spec/unit/node_spec.rb +8 -0
  106. data/spec/unit/parser/compiler_spec.rb +0 -18
  107. data/spec/unit/pops/evaluator/access_ops_spec.rb +4 -4
  108. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +1 -1
  109. data/spec/unit/pops/loaders/loaders_spec.rb +84 -2
  110. data/spec/unit/pops/parser/lexer2_spec.rb +6 -0
  111. data/spec/unit/pops/parser/parser_rspec_helper.rb +5 -0
  112. data/spec/unit/pops/types/type_calculator_spec.rb +0 -17
  113. data/spec/unit/pops/validator/validator_spec.rb +87 -0
  114. data/spec/unit/provider/group/windows_adsi_spec.rb +8 -8
  115. data/spec/unit/provider/package/pip_spec.rb +41 -13
  116. data/spec/unit/provider/package/rpm_spec.rb +2 -25
  117. data/spec/unit/provider/package/yum_spec.rb +1 -1
  118. data/spec/unit/provider/service/debian_spec.rb +6 -24
  119. data/spec/unit/provider/service/init_spec.rb +11 -1
  120. data/spec/unit/provider/service/launchd_spec.rb +11 -0
  121. data/spec/unit/provider/service/systemd_spec.rb +18 -12
  122. data/spec/unit/provider/service/upstart_spec.rb +57 -0
  123. data/spec/unit/provider/user/windows_adsi_spec.rb +5 -5
  124. data/spec/unit/provider/yumrepo/inifile_spec.rb +16 -0
  125. data/spec/unit/resource_spec.rb +12 -2
  126. data/spec/unit/util/windows/adsi_spec.rb +44 -36
  127. data/spec/unit/util/windows/sid_spec.rb +47 -10
  128. metadata +77 -10
@@ -67,6 +67,10 @@ module Puppet::Pops::Parser::SlurpSupport
67
67
  def slurp(scanner, pattern, escapes, ignore_invalid_escapes)
68
68
  str = scanner.scan_until(pattern) || return
69
69
 
70
+ return str unless str.include?('\\')
71
+
72
+ return str.gsub!(/\\(\\|')/m, '\1') || str if escapes.equal?(SQ_ESCAPES)
73
+
70
74
  # Process unicode escapes first as they require getting 4 hex digits
71
75
  # If later a \u is found it is warned not to be a unicode escape
72
76
  if escapes.include?('u')
@@ -83,7 +87,7 @@ module Puppet::Pops::Parser::SlurpSupport
83
87
  when 'r' ; "\r"
84
88
  when 'n' ; "\n"
85
89
  when 't' ; "\t"
86
- when 's' ; " "
90
+ when 's' ; ' '
87
91
  when 'u'
88
92
  lex_warning(Puppet::Pops::Issues::ILLEGAL_UNICODE_ESCAPE)
89
93
  "\\u"
@@ -708,12 +708,8 @@ class Puppet::Pops::Types::TypeCalculator
708
708
  from = range.from
709
709
  to = range.to
710
710
  x = from.nil? ? 1 : from
711
- y = to.nil? ? Float::INFINITY : to
712
- if x < y
713
- [x, y]
714
- else
715
- [y, x]
716
- end
711
+ y = to.nil? ? TheInfinity : to
712
+ [x, y]
717
713
  end
718
714
 
719
715
  # @api private
@@ -423,15 +423,9 @@ module Puppet::Pops
423
423
  def initialize(from, to = Float::INFINITY)
424
424
  from = -Float::INFINITY if from.nil? || from == :default
425
425
  to = Float::INFINITY if to.nil? || to == :default
426
-
427
- # Always create in right order
428
- if from <= to
429
- @from = from
430
- @to = to
431
- else
432
- @to = from
433
- @from = to
434
- end
426
+ raise ArgumentError, "'from' must be less or equal to 'to'. Got (#{from}, #{to}" if from.is_a?(Numeric) && to.is_a?(Numeric) && from > to
427
+ @from = from
428
+ @to = to
435
429
  end
436
430
 
437
431
  # Returns the lower bound of the numeric range or `nil` if no lower bound is set.
@@ -213,11 +213,24 @@ class Puppet::Pops::Validation::Checker4_0
213
213
  rvalue(o.right_expr)
214
214
  end
215
215
 
216
+ def resource_without_title?(o)
217
+ if o.instance_of?(Puppet::Pops::Model::BlockExpression)
218
+ statements = o.statements
219
+ statements.length == 2 && statements[0].instance_of?(Puppet::Pops::Model::QualifiedName) && statements[1].instance_of?(Puppet::Pops::Model::LiteralHash)
220
+ else
221
+ false
222
+ end
223
+ end
224
+
216
225
  def check_BlockExpression(o)
217
- o.statements[0..-2].each do |statement|
218
- if idem(statement)
219
- acceptor.accept(Issues::IDEM_EXPRESSION_NOT_LAST, statement)
220
- break # only flag the first
226
+ if resource_without_title?(o)
227
+ acceptor.accept(Issues::RESOURCE_WITHOUT_TITLE, o, :name => o.statements[0].value)
228
+ else
229
+ o.statements[0..-2].each do |statement|
230
+ if idem(statement)
231
+ acceptor.accept(Issues::IDEM_EXPRESSION_NOT_LAST, statement)
232
+ break # only flag the first
233
+ end
221
234
  end
222
235
  end
223
236
  end
@@ -264,6 +277,7 @@ class Puppet::Pops::Validation::Checker4_0
264
277
  def check_EppExpression(o)
265
278
  if o.eContainer.is_a?(Puppet::Pops::Model::LambdaExpression)
266
279
  internal_check_no_capture(o.eContainer, o)
280
+ internal_check_parameter_name_uniqueness(o.eContainer)
267
281
  end
268
282
  end
269
283
 
@@ -352,16 +366,13 @@ class Puppet::Pops::Validation::Checker4_0
352
366
  end
353
367
 
354
368
  def check_FunctionDefinition(o)
355
- # TODO PUP-2080: more strict rule for top - can only be contained in Program (for now)
356
- # sticking functions in classes would create functions in the class name space
357
- # but not be special in any other way
358
- #
359
369
  check_NamedDefinition(o)
360
370
  end
361
371
 
362
372
  def check_HostClassDefinition(o)
363
373
  check_NamedDefinition(o)
364
374
  internal_check_no_capture(o)
375
+ internal_check_parameter_name_uniqueness(o)
365
376
  internal_check_reserved_params(o)
366
377
  internal_check_no_idem_last(o)
367
378
  end
@@ -369,13 +380,14 @@ class Puppet::Pops::Validation::Checker4_0
369
380
  def check_ResourceTypeDefinition(o)
370
381
  check_NamedDefinition(o)
371
382
  internal_check_no_capture(o)
383
+ internal_check_parameter_name_uniqueness(o)
372
384
  internal_check_reserved_params(o)
373
385
  internal_check_no_idem_last(o)
374
386
  end
375
387
 
376
388
  def internal_check_no_idem_last(o)
377
389
  if violator = ends_with_idem(o.body)
378
- acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o})
390
+ acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o}) unless resource_without_title?(violator)
379
391
  end
380
392
  end
381
393
 
@@ -409,6 +421,13 @@ class Puppet::Pops::Validation::Checker4_0
409
421
  end
410
422
  end
411
423
 
424
+ def internal_check_parameter_name_uniqueness(o)
425
+ unique = Set.new
426
+ o.parameters.each do |p|
427
+ acceptor.accept(Issues::DUPLICATE_PARAMETER, p, {:param_name => p.name}) unless unique.add?(p.name)
428
+ end
429
+ end
430
+
412
431
  def check_IfExpression(o)
413
432
  rvalue(o.test)
414
433
  end
@@ -433,7 +452,7 @@ class Puppet::Pops::Validation::Checker4_0
433
452
  hostname(o.host_matches, o)
434
453
  top(o.eContainer, o)
435
454
  if violator = ends_with_idem(o.body)
436
- acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o})
455
+ acceptor.accept(Issues::IDEM_NOT_ALLOWED_LAST, violator, {:container => o}) unless resource_without_title?(violator)
437
456
  end
438
457
  unless o.parent.nil?
439
458
  acceptor.accept(Issues::ILLEGAL_NODE_INHERITANCE, o.parent)
@@ -700,8 +719,13 @@ class Puppet::Pops::Validation::Checker4_0
700
719
  end
701
720
 
702
721
  def top_BlockExpression(o, definition)
703
- # ok, if this is a block representing the body of a class, or is top level
704
- top o.eContainer, definition
722
+ if definition.is_a?(Model::FunctionDefinition) && !o.eContainer.is_a?(Model::Program)
723
+ # not ok if the definition is a FunctionDefinition. It can never be nested in a block
724
+ acceptor.accept(Issues::NOT_ABSOLUTE_TOP_LEVEL, definition)
725
+ else
726
+ # ok, if this is a block representing the body of a class, or is top level
727
+ top o.eContainer, definition
728
+ end
705
729
  end
706
730
 
707
731
  def top_HostClassDefinition(o, definition)
@@ -28,7 +28,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
28
28
  specified_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should)
29
29
 
30
30
  if @resource[:auth_membership]
31
- current_users == specified_users
31
+ current_users.keys.to_a == specified_users.keys.to_a
32
32
  else
33
33
  (specified_users.keys.to_a & current_users.keys.to_a) == specified_users.keys.to_a
34
34
  end
@@ -48,7 +48,7 @@ Puppet::Type.type(:group).provide :windows_adsi do
48
48
  else
49
49
  account = sid.account
50
50
  end
51
- resource.debug("#{sid.domain}\\#{account} (#{sid.to_s})")
51
+ resource.debug("#{sid.domain}\\#{account} (#{sid.sid})")
52
52
  "#{sid.domain}\\#{account}"
53
53
  end
54
54
  return users.join(',')
@@ -3,6 +3,7 @@
3
3
 
4
4
  require 'puppet/provider/package'
5
5
  require 'xmlrpc/client'
6
+ require 'puppet/util/http_proxy'
6
7
 
7
8
  Puppet::Type.type(:package).provide :pip,
8
9
  :parent => ::Puppet::Provider::Package do
@@ -60,7 +61,16 @@ Puppet::Type.type(:package).provide :pip,
60
61
  # cache of PyPI's package list so this operation will always have to
61
62
  # ask the web service.
62
63
  def latest
63
- client = XMLRPC::Client.new2("http://pypi.python.org/pypi")
64
+ http_proxy_host = Puppet::Util::HttpProxy.http_proxy_host
65
+ http_proxy_port = Puppet::Util::HttpProxy.http_proxy_port
66
+ if http_proxy_host && http_proxy_port
67
+ proxy = "#{http_proxy_host}:#{http_proxy_port}"
68
+ else
69
+ # nil is acceptable
70
+ proxy = http_proxy_host
71
+ end
72
+
73
+ client = XMLRPC::Client.new2("http://pypi.python.org/pypi", proxy)
64
74
  client.http_header_extra = {"Content-Type" => "text/xml"}
65
75
  client.timeout = 10
66
76
  result = client.call("package_releases", @resource[:name])
@@ -281,7 +281,6 @@ Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Pr
281
281
  self::NEVRA_FIELDS.zip(match.captures) { |f, v| hash[f] = v }
282
282
  hash[:provider] = self.name
283
283
  hash[:ensure] = "#{hash[:version]}-#{hash[:release]}"
284
- hash[:ensure].prepend("#{hash[:epoch]}:") if hash[:epoch] != '0'
285
284
  else
286
285
  Puppet.debug("Failed to match rpm line #{line}")
287
286
  end
@@ -80,7 +80,7 @@ Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do
80
80
  elsif output.exitstatus == 0
81
81
  self.debug "#{command(:cmd)} check-update exited with 0; no package updates available."
82
82
  else
83
- self.warn "Could not check for updates, '#{command(:cmd)} check-update' exited with #{output.exitstatus}"
83
+ self.warning "Could not check for updates, '#{command(:cmd)} check-update' exited with #{output.exitstatus}"
84
84
  end
85
85
  updates
86
86
  end
@@ -15,6 +15,7 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do
15
15
  # http://projects.reductivelabs.com/issues/2538
16
16
  # is resolved.
17
17
  commands :invoke_rc => "/usr/sbin/invoke-rc.d"
18
+ commands :service => "/usr/sbin/service"
18
19
 
19
20
  defaultfor :operatingsystem => :cumuluslinux
20
21
  defaultfor :operatingsystem => :debian, :operatingsystemmajrelease => ['5','6','7']
@@ -65,23 +66,9 @@ Puppet::Type.type(:service).provide :debian, :parent => :init do
65
66
  end
66
67
 
67
68
  def statuscmd
68
- os = Facter.value(:operatingsystem).downcase
69
-
70
- if os == 'debian'
71
- majversion = Facter.value(:operatingsystemmajrelease).to_i
72
- else
73
- majversion = Facter.value(:operatingsystemmajrelease).split('.')[0].to_i
74
- end
75
-
76
-
77
- if ((os == 'debian' && majversion >= 8) || (os == 'ubuntu' && majversion >= 15))
78
- # SysVInit scripts will always return '0' for status when the service is masked,
79
- # even if the service is actually stopped. Use the SysVInit-Systemd compatibility
80
- # layer to determine the actual status. This is only necessary when the SysVInit
81
- # version of a service is queried. I.e, 'ntp' instead of 'ntp.service'.
82
- (@resource[:hasstatus] == :true) && ["systemctl", "is-active", @resource[:name]]
83
- else
84
- super
85
- end
69
+ # /usr/sbin/service provides an abstraction layer which is able to query services
70
+ # independent of the init system used.
71
+ # See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=775795
72
+ (@resource[:hasstatus] == :true) && [command(:service), @resource[:name], "status"]
86
73
  end
87
74
  end
@@ -49,6 +49,13 @@ Puppet::Type.type(:service).provide :init, :parent => :base do
49
49
  excludes += %w{wait-for-state portmap-wait}
50
50
  # these excludes were found with grep -r -L start /etc/init.d
51
51
  excludes += %w{rcS module-init-tools}
52
+ # Prevent puppet failing on unsafe scripts from Yocto Linux
53
+ if Facter.value(:osfamily) == "cisco-wrlinux"
54
+ excludes += %w{banner.sh bootmisc.sh checkroot.sh devpts.sh dmesg.sh
55
+ hostname.sh mountall.sh mountnfs.sh populate-volatile.sh
56
+ rmnologin.sh save-rtc.sh sendsigs sysfs.sh umountfs
57
+ umountnfs.sh}
58
+ end
52
59
  # Prevent puppet failing to get status of the new service introduced
53
60
  # by the fix for this (bug https://bugs.launchpad.net/ubuntu/+source/lightdm/+bug/982889)
54
61
  # due to puppet's inability to deal with upstart services with instances.
@@ -193,6 +193,12 @@ Puppet::Type.type(:service).provide :launchd, :parent => :base do
193
193
  # Read a plist, whether its format is XML or in Apple's "binary1"
194
194
  # format.
195
195
  def self.read_plist(path)
196
+ begin
197
+ return Plist::parse_xml(path)
198
+ rescue ArgumentError => detail
199
+ Puppet.debug("Error reading #{path}: #{detail}. Retrying with plutil.")
200
+ end
201
+
196
202
  begin
197
203
  Plist::parse_xml(plutil('-convert', 'xml1', '-o', '/dev/stdout', path))
198
204
  rescue Puppet::ExecutionFailure => detail
@@ -12,7 +12,7 @@ Puppet::Type.type(:service).provide :systemd, :parent => :base do
12
12
  defaultfor :osfamily => :redhat, :operatingsystem => :fedora
13
13
  defaultfor :osfamily => :suse
14
14
  defaultfor :operatingsystem => :debian, :operatingsystemmajrelease => "8"
15
- defaultfor :operatingsystem => :ubuntu, :operatingsystemmajrelease => "15.04"
15
+ defaultfor :operatingsystem => :ubuntu, :operatingsystemmajrelease => ["15.04","15.10"]
16
16
 
17
17
  def self.instances
18
18
  i = []
@@ -40,7 +40,7 @@ Puppet::Type.type(:user).provide :windows_adsi do
40
40
  specified_users = Puppet::Util::Windows::ADSI::Group.name_sid_hash(should)
41
41
 
42
42
  if @resource[:membership] == :inclusive
43
- current_users == specified_users
43
+ current_users.keys.to_a == specified_users.keys.to_a
44
44
  else
45
45
  (specified_users.keys.to_a & current_users.keys.to_a) == specified_users.keys.to_a
46
46
  end
@@ -55,7 +55,7 @@ Puppet::Type.type(:user).provide :windows_adsi do
55
55
  else
56
56
  account = sid.account
57
57
  end
58
- resource.debug("#{sid.domain}\\#{account} (#{sid.to_s})")
58
+ resource.debug("#{sid.domain}\\#{account} (#{sid.sid})")
59
59
  "#{sid.domain}\\#{account}"
60
60
  end
61
61
  return groups.join(',')
@@ -74,9 +74,12 @@ Puppet::Type.type(:yumrepo).provide(:inifile) do
74
74
  def self.reposdir(conf='/etc/yum.conf', dirs=['/etc/yum.repos.d', '/etc/yum/repos.d'])
75
75
  reposdir = find_conf_value('reposdir', conf)
76
76
  # Use directories in reposdir if they are set instead of default
77
- dirs = reposdir.split(",").map(&:strip) if reposdir
78
-
79
-
77
+ if reposdir
78
+ # Follow the code from the yum/config.py
79
+ dirs = reposdir.gsub!("\n", ' ')
80
+ dirs = reposdir.gsub!(',', ' ')
81
+ dirs = reposdir.split
82
+ end
80
83
  dirs.select! { |dir| Puppet::FileSystem.exist?(dir) }
81
84
  if dirs.empty?
82
85
  Puppet.debug('No yum directories were found on the local filesystem')
@@ -387,7 +387,8 @@ class Puppet::Resource::Type
387
387
  parameters = resource.parameters
388
388
  arguments.each do |param_name, _|
389
389
  name = param_name.to_sym
390
- next if parameters.include?(name)
390
+ param = parameters[name]
391
+ next unless param.nil? || param.value.nil?
391
392
  value = lookup_external_default_for(param_name, scope)
392
393
  resource[name] = value unless value.nil?
393
394
  end
@@ -138,10 +138,10 @@ class Puppet::Transaction::AdditionalResourceGenerator
138
138
  def add_generated_directed_dependency(parent, child, label=nil)
139
139
  if parent.depthfirst?
140
140
  source = child
141
- target = parent.to_resource
141
+ target = parent
142
142
  else
143
143
  source = parent
144
- target = child.to_resource
144
+ target = child
145
145
  end
146
146
 
147
147
  # For each potential relationship metaparam, check if parent or
@@ -170,8 +170,22 @@ class Puppet::Transaction::AdditionalResourceGenerator
170
170
  }
171
171
 
172
172
  if not edge_exists
173
+ # We *cannot* use target.to_resource here!
174
+ #
175
+ # For reasons that are beyond my (and, perhaps, human)
176
+ # comprehension, to_resource will call retrieve. This is
177
+ # problematic if a generated resource needs the system to be
178
+ # changed by a previous resource (think a file on a path
179
+ # controlled by a mount resource).
180
+ #
181
+ # Instead of using to_resource, we just construct a resource as
182
+ # if the arguments to the Type instance had been passed to a
183
+ # Resource instead.
184
+ resource = ::Puppet::Resource.new(target.class, target.title,
185
+ :parameters => target.original_parameters)
186
+
173
187
  source[:before] ||= []
174
- source[:before] << target
188
+ source[:before] << resource
175
189
  end
176
190
  end
177
191
 
@@ -80,7 +80,9 @@ module Puppet
80
80
 
81
81
  newproperty(:members, :array_matching => :all, :required_features => :manages_members) do
82
82
  desc "The members of the group. For directory services where group
83
- membership is stored in the group objects, not the users."
83
+ membership is stored in the group objects, not the users. Use
84
+ with auth_membership to determine whether the specified members
85
+ are inclusive or the minimum."
84
86
 
85
87
  def change_to_s(currentvalue, newvalue)
86
88
  currentvalue = currentvalue.join(",") if currentvalue != :absent
@@ -116,7 +118,9 @@ module Puppet
116
118
  end
117
119
 
118
120
  newparam(:auth_membership, :boolean => true, :parent => Puppet::Parameter::Boolean) do
119
- desc "whether the provider is authoritative for group membership."
121
+ desc "Whether the provider is authoritative for group membership. This
122
+ must be set to true to allow setting the group to no members with
123
+ `members => [],`."
120
124
  defaultto false
121
125
  end
122
126
 
@@ -6,6 +6,9 @@ module Puppet::Util::Windows
6
6
  end
7
7
  module Registry
8
8
  end
9
+ module SID
10
+ class Principal; end
11
+ end
9
12
 
10
13
  if Puppet::Util::Platform.windows?
11
14
  # these reference platform specific gems
@@ -14,6 +17,7 @@ module Puppet::Util::Windows
14
17
  require 'puppet/util/windows/error'
15
18
  require 'puppet/util/windows/com'
16
19
  require 'puppet/util/windows/sid'
20
+ require 'puppet/util/windows/principal'
17
21
  require 'puppet/util/windows/file'
18
22
  require 'puppet/util/windows/security'
19
23
  require 'puppet/util/windows/user'
@@ -56,21 +56,30 @@ module Puppet::Util::Windows::ADSI
56
56
  "winmgmts:{impersonationLevel=impersonate}!//#{host}/root/cimv2"
57
57
  end
58
58
 
59
+ # This method should *only* be used to generate WinNT://<SID> style monikers
60
+ # used for IAdsGroup::Add / IAdsGroup::Remove. These URIs are not useable
61
+ # to resolve an account with WIN32OLE.connect
62
+ # Valid input is a SID::Principal, S-X-X style SID string or any valid
63
+ # account name with or without domain prefix
59
64
  # @api private
60
65
  def sid_uri_safe(sid)
61
- return sid_uri(sid) if sid.kind_of?(Win32::Security::SID)
66
+ return sid_uri(sid) if sid.kind_of?(Puppet::Util::Windows::SID::Principal)
62
67
 
63
68
  begin
64
- sid = Win32::Security::SID.new(Win32::Security::SID.string_to_sid(sid))
69
+ sid = Puppet::Util::Windows::SID.name_to_sid_object(sid)
65
70
  sid_uri(sid)
66
- rescue SystemCallError
71
+ rescue Puppet::Util::Windows::Error, Puppet::Error
67
72
  nil
68
73
  end
69
74
  end
70
75
 
76
+ # This method should *only* be used to generate WinNT://<SID> style monikers
77
+ # used for IAdsGroup::Add / IAdsGroup::Remove. These URIs are not useable
78
+ # to resolve an account with WIN32OLE.connect
71
79
  def sid_uri(sid)
72
- raise Puppet::Error.new( "Must use a valid SID object" ) if !sid.kind_of?(Win32::Security::SID)
73
- "WinNT://#{sid.to_s}"
80
+ raise Puppet::Error.new( "Must use a valid SID::Principal" ) if !sid.kind_of?(Puppet::Util::Windows::SID::Principal)
81
+
82
+ "WinNT://#{sid.sid}"
74
83
  end
75
84
 
76
85
  def uri(resource_name, resource_type, host = '.')
@@ -99,8 +108,6 @@ module Puppet::Util::Windows::ADSI
99
108
 
100
109
  module Shared
101
110
  def uri(name, host = '.')
102
- if sid_uri = Puppet::Util::Windows::ADSI.sid_uri_safe(name) then return sid_uri end
103
-
104
111
  host = '.' if ['NT AUTHORITY', 'BUILTIN', Socket.gethostname].include?(host)
105
112
 
106
113
  # group or user
@@ -136,7 +143,7 @@ module Puppet::Util::Windows::ADSI
136
143
  sids = names.map do |name|
137
144
  sid = Puppet::Util::Windows::SID.name_to_sid_object(name)
138
145
  raise Puppet::Error.new( "Could not resolve name: #{name}" ) if !sid
139
- [sid.to_s, sid]
146
+ [sid.sid, sid]
140
147
  end
141
148
 
142
149
  Hash[ sids ]
@@ -247,20 +254,12 @@ module Puppet::Util::Windows::ADSI
247
254
 
248
255
 
249
256
  def add_group_sids(*sids)
250
- group_names = []
251
- sids.each do |sid|
252
- group_names << Puppet::Util::Windows::SID.sid_to_name(sid)
253
- end
254
-
257
+ group_names = sids.map { |s| s.domain_account }
255
258
  add_to_groups(*group_names)
256
259
  end
257
260
 
258
261
  def remove_group_sids(*sids)
259
- group_names = []
260
- sids.each do |sid|
261
- group_names << Puppet::Util::Windows::SID.sid_to_name(sid)
262
- end
263
-
262
+ group_names = sids.map { |s| s.domain_account }
264
263
  remove_from_groups(*group_names)
265
264
  end
266
265
 
@@ -273,7 +272,7 @@ module Puppet::Util::Windows::ADSI
273
272
 
274
273
  desired_groups = desired_groups.split(',').map(&:strip)
275
274
 
276
- current_hash = Hash[ self.group_sids.map { |sid| [sid.to_s, sid] } ]
275
+ current_hash = Hash[ self.group_sids.map { |sid| [sid.sid, sid] } ]
277
276
  desired_hash = self.class.name_sid_hash(desired_groups)
278
277
 
279
278
  # First we add the user to all the groups it should be in but isn't
@@ -321,10 +320,30 @@ module Puppet::Util::Windows::ADSI
321
320
  user_name
322
321
  end
323
322
 
324
- def self.exists?(name)
325
- Puppet::Util::Windows::ADSI::connectable?(User.uri(*User.parse_name(name)))
323
+ def self.exists?(name_or_sid)
324
+ well_known = false
325
+ if (sid = Puppet::Util::Windows::SID.name_to_sid_object(name_or_sid))
326
+ return true if sid.account_type == :SidTypeUser
327
+
328
+ # 'well known group' is special as it can be a group like Everyone OR a user like SYSTEM
329
+ # so try to resolve it
330
+ # https://msdn.microsoft.com/en-us/library/cc234477.aspx
331
+ well_known = sid.account_type == :SidTypeWellKnownGroup
332
+ return false if sid.account_type != :SidTypeAlias && !well_known
333
+ name_or_sid = "#{sid.domain}\\#{sid.account}"
334
+ end
335
+
336
+ user = Puppet::Util::Windows::ADSI.connect(User.uri(*User.parse_name(name_or_sid)))
337
+ # otherwise, verify that the account is actually a User account
338
+ user.Class == 'User'
339
+ rescue
340
+ # special accounts like SYSTEM cannot resolve via moniker like WinNT://./SYSTEM,user
341
+ # and thus fail to connect - so given a validly resolved SID, this failure is ambiguous as it
342
+ # may indicate either a group like Service or an account like SYSTEM
343
+ well_known
326
344
  end
327
345
 
346
+
328
347
  def self.delete(name)
329
348
  Puppet::Util::Windows::ADSI.delete(name, 'user')
330
349
  end
@@ -437,7 +456,7 @@ module Puppet::Util::Windows::ADSI
437
456
  def set_members(desired_members, inclusive = true)
438
457
  return if desired_members.nil?
439
458
 
440
- current_hash = Hash[ self.member_sids.map { |sid| [sid.to_s, sid] } ]
459
+ current_hash = Hash[ self.member_sids.map { |sid| [sid.sid, sid] } ]
441
460
  desired_hash = self.class.name_sid_hash(desired_members)
442
461
 
443
462
  # First we add all missing members
@@ -464,8 +483,26 @@ module Puppet::Util::Windows::ADSI
464
483
  new(name, Puppet::Util::Windows::ADSI.create(name, 'group'))
465
484
  end
466
485
 
467
- def self.exists?(name)
468
- Puppet::Util::Windows::ADSI.connectable?(Group.uri(name))
486
+ def self.exists?(name_or_sid)
487
+ well_known = false
488
+ if (sid = Puppet::Util::Windows::SID.name_to_sid_object(name_or_sid))
489
+ return true if sid.account_type == :SidTypeGroup
490
+
491
+ # 'well known group' is special as it can be a group like Everyone OR a user like SYSTEM
492
+ # so try to resolve it
493
+ # https://msdn.microsoft.com/en-us/library/cc234477.aspx
494
+ well_known = sid.account_type == :SidTypeWellKnownGroup
495
+ return false if sid.account_type != :SidTypeAlias && !well_known
496
+ name_or_sid = "#{sid.domain}\\#{sid.account}"
497
+ end
498
+
499
+ user = Puppet::Util::Windows::ADSI.connect(Group.uri(*Group.parse_name(name_or_sid)))
500
+ user.Class == 'Group'
501
+ rescue
502
+ # special groups like Authenticated Users cannot resolve via moniker like WinNT://./Authenticated Users,group
503
+ # and thus fail to connect - so given a validly resolved SID, this failure is ambiguous as it
504
+ # may indicate either a group like Service or an account like SYSTEM
505
+ well_known
469
506
  end
470
507
 
471
508
  def self.delete(name)