puppet 6.16.0-x86-mingw32 → 6.17.0-x86-mingw32

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 (138) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -2
  3. data/Gemfile.lock +10 -10
  4. data/README.md +2 -2
  5. data/lib/puppet/agent.rb +2 -2
  6. data/lib/puppet/application/agent.rb +14 -3
  7. data/lib/puppet/configurer.rb +20 -12
  8. data/lib/puppet/confine.rb +1 -1
  9. data/lib/puppet/defaults.rb +25 -8
  10. data/lib/puppet/file_serving/http_metadata.rb +13 -1
  11. data/lib/puppet/file_serving/metadata.rb +4 -1
  12. data/lib/puppet/file_serving/terminus_selector.rb +7 -8
  13. data/lib/puppet/file_system/file_impl.rb +1 -1
  14. data/lib/puppet/file_system/uniquefile.rb +8 -16
  15. data/lib/puppet/forge.rb +1 -1
  16. data/lib/puppet/forge/cache.rb +1 -1
  17. data/lib/puppet/forge/repository.rb +3 -7
  18. data/lib/puppet/http/client.rb +5 -0
  19. data/lib/puppet/http/redirector.rb +9 -7
  20. data/lib/puppet/http/response.rb +19 -0
  21. data/lib/puppet/indirector.rb +1 -1
  22. data/lib/puppet/indirector/file_content/rest.rb +1 -1
  23. data/lib/puppet/indirector/file_metadata/http.rb +24 -5
  24. data/lib/puppet/indirector/file_metadata/rest.rb +2 -2
  25. data/lib/puppet/indirector/request.rb +1 -1
  26. data/lib/puppet/network/http/api/indirected_routes.rb +1 -1
  27. data/lib/puppet/network/http/api/master/v3/environment.rb +3 -0
  28. data/lib/puppet/network/http/connection_adapter.rb +6 -4
  29. data/lib/puppet/parser/ast/leaf.rb +5 -5
  30. data/lib/puppet/parser/ast/pops_bridge.rb +0 -4
  31. data/lib/puppet/parser/compiler.rb +1 -1
  32. data/lib/puppet/parser/compiler/catalog_validator/env_relationship_validator.rb +2 -0
  33. data/lib/puppet/parser/compiler/catalog_validator/site_validator.rb +2 -0
  34. data/lib/puppet/parser/environment_compiler.rb +4 -1
  35. data/lib/puppet/parser/resource.rb +3 -2
  36. data/lib/puppet/parser/resource/param.rb +6 -0
  37. data/lib/puppet/pops/evaluator/evaluator_impl.rb +5 -5
  38. data/lib/puppet/pops/issues.rb +5 -0
  39. data/lib/puppet/pops/resource/resource_type_impl.rb +2 -0
  40. data/lib/puppet/pops/validation/checker4_0.rb +10 -0
  41. data/lib/puppet/pops/validation/validator_factory_4_0.rb +1 -0
  42. data/lib/puppet/provider/package/aptitude.rb +1 -1
  43. data/lib/puppet/provider/package/yum.rb +1 -1
  44. data/lib/puppet/provider/service/windows.rb +23 -7
  45. data/lib/puppet/provider/user/useradd.rb +11 -4
  46. data/lib/puppet/reports/http.rb +2 -0
  47. data/lib/puppet/resource.rb +2 -1
  48. data/lib/puppet/resource/type.rb +8 -0
  49. data/lib/puppet/ssl/ssl_context.rb +2 -2
  50. data/lib/puppet/ssl/ssl_provider.rb +20 -1
  51. data/lib/puppet/test/test_helper.rb +8 -10
  52. data/lib/puppet/trusted_external.rb +29 -1
  53. data/lib/puppet/type.rb +12 -5
  54. data/lib/puppet/type/file.rb +38 -13
  55. data/lib/puppet/type/file/checksum.rb +4 -4
  56. data/lib/puppet/type/file/source.rb +4 -4
  57. data/lib/puppet/type/service.rb +49 -0
  58. data/lib/puppet/util.rb +39 -15
  59. data/lib/puppet/util/checksums.rb +19 -4
  60. data/lib/puppet/util/fileparsing.rb +2 -2
  61. data/lib/puppet/util/provider_features.rb +1 -1
  62. data/lib/puppet/util/reference.rb +1 -1
  63. data/lib/puppet/util/windows/api_types.rb +45 -32
  64. data/lib/puppet/util/windows/eventlog.rb +1 -6
  65. data/lib/puppet/util/windows/principal.rb +8 -6
  66. data/lib/puppet/util/windows/registry.rb +11 -11
  67. data/lib/puppet/util/windows/service.rb +43 -26
  68. data/lib/puppet/util/windows/user.rb +23 -8
  69. data/lib/puppet/version.rb +1 -1
  70. data/locales/puppet.pot +249 -221
  71. data/man/man5/puppet.conf.5 +19 -8
  72. data/man/man8/puppet-agent.8 +2 -2
  73. data/man/man8/puppet-apply.8 +1 -1
  74. data/man/man8/puppet-catalog.8 +1 -1
  75. data/man/man8/puppet-config.8 +1 -1
  76. data/man/man8/puppet-describe.8 +1 -1
  77. data/man/man8/puppet-device.8 +1 -1
  78. data/man/man8/puppet-doc.8 +1 -1
  79. data/man/man8/puppet-epp.8 +1 -1
  80. data/man/man8/puppet-facts.8 +1 -1
  81. data/man/man8/puppet-filebucket.8 +1 -1
  82. data/man/man8/puppet-generate.8 +1 -1
  83. data/man/man8/puppet-help.8 +1 -1
  84. data/man/man8/puppet-key.8 +1 -1
  85. data/man/man8/puppet-lookup.8 +1 -1
  86. data/man/man8/puppet-man.8 +1 -1
  87. data/man/man8/puppet-module.8 +1 -1
  88. data/man/man8/puppet-node.8 +1 -1
  89. data/man/man8/puppet-parser.8 +1 -1
  90. data/man/man8/puppet-plugin.8 +1 -1
  91. data/man/man8/puppet-report.8 +1 -1
  92. data/man/man8/puppet-resource.8 +1 -1
  93. data/man/man8/puppet-script.8 +1 -1
  94. data/man/man8/puppet-ssl.8 +1 -1
  95. data/man/man8/puppet-status.8 +1 -1
  96. data/man/man8/puppet.8 +2 -2
  97. data/spec/integration/application/agent_spec.rb +89 -0
  98. data/spec/integration/defaults_spec.rb +1 -2
  99. data/spec/integration/network/http_pool_spec.rb +26 -9
  100. data/spec/integration/parser/compiler_spec.rb +11 -0
  101. data/spec/integration/type/file_spec.rb +1 -1
  102. data/spec/integration/util/windows/registry_spec.rb +7 -7
  103. data/spec/integration/util/windows/user_spec.rb +40 -5
  104. data/spec/unit/configurer/fact_handler_spec.rb +4 -4
  105. data/spec/unit/context/trusted_information_spec.rb +10 -4
  106. data/spec/unit/file_serving/http_metadata_spec.rb +37 -14
  107. data/spec/unit/file_serving/terminus_selector_spec.rb +45 -26
  108. data/spec/unit/http/client_spec.rb +64 -8
  109. data/spec/unit/http/response_spec.rb +6 -0
  110. data/spec/unit/indirector/file_metadata/http_spec.rb +27 -0
  111. data/spec/unit/indirector/request_spec.rb +1 -1
  112. data/spec/unit/interface_spec.rb +3 -3
  113. data/spec/unit/network/http/api/indirected_routes_spec.rb +2 -1
  114. data/spec/unit/network/http/connection_spec.rb +42 -32
  115. data/spec/unit/parser/ast/block_expression_spec.rb +1 -1
  116. data/spec/unit/parser/environment_compiler_spec.rb +7 -0
  117. data/spec/unit/parser/scope_spec.rb +1 -1
  118. data/spec/unit/pops/evaluator/evaluating_parser_spec.rb +15 -1
  119. data/spec/unit/pops/loaders/loaders_spec.rb +1 -1
  120. data/spec/unit/pops/types/type_calculator_spec.rb +1 -11
  121. data/spec/unit/provider/service/windows_spec.rb +22 -14
  122. data/spec/unit/provider/user/openbsd_spec.rb +1 -0
  123. data/spec/unit/provider/user/useradd_spec.rb +22 -16
  124. data/spec/unit/resource_spec.rb +3 -3
  125. data/spec/unit/ssl/ssl_provider_spec.rb +69 -43
  126. data/spec/unit/test/test_helper_spec.rb +17 -0
  127. data/spec/unit/transaction/report_spec.rb +1 -1
  128. data/spec/unit/type/file/source_spec.rb +3 -3
  129. data/spec/unit/type/file_spec.rb +122 -96
  130. data/spec/unit/type/service_spec.rb +176 -0
  131. data/spec/unit/type_spec.rb +50 -0
  132. data/spec/unit/util/checksums_spec.rb +16 -0
  133. data/spec/unit/util/windows/api_types_spec.rb +104 -40
  134. data/spec/unit/util/windows/service_spec.rb +4 -4
  135. data/spec/unit/util_spec.rb +3 -3
  136. data/spec/unit/x509/cert_provider_spec.rb +1 -1
  137. metadata +5 -5
  138. data/spec/integration/test/test_helper_spec.rb +0 -31
@@ -138,10 +138,17 @@ Puppet::Type.type(:user).provide :useradd, :parent => Puppet::Provider::NameServ
138
138
 
139
139
  def check_manage_home
140
140
  cmd = []
141
- if @resource.managehome? && (!@resource.forcelocal?)
142
- cmd << "-m"
143
- elsif (!@resource.managehome?) && Facter.value(:osfamily) == 'RedHat'
144
- cmd << "-M"
141
+ if @resource.managehome?
142
+ # libuser does not implement the -m flag
143
+ cmd << "-m" unless @resource.forcelocal?
144
+ else
145
+ osfamily = Facter.value(:osfamily)
146
+ osversion = Facter.value(:operatingsystemmajrelease).to_i
147
+ # SLES 11 uses pwdutils instead of shadow, which does not have -M
148
+ # Solaris and OpenBSD use different useradd flavors
149
+ unless osfamily =~ /Solaris|OpenBSD/ || osfamily == 'Suse' && osversion <= 11
150
+ cmd << "-M"
151
+ end
145
152
  end
146
153
  cmd
147
154
  end
@@ -25,6 +25,8 @@ Puppet::Reports.register_report(:http) do
25
25
  :include_system_store => Puppet[:report_include_system_store],
26
26
  }
27
27
 
28
+ # Puppet's http client implementation accepts userinfo in the URL
29
+ # but puppetserver's does not. So pass credentials explicitly.
28
30
  if url.user && url.password
29
31
  options[:basic_auth] = {
30
32
  user: url.user,
@@ -628,7 +628,8 @@ class Puppet::Resource
628
628
  def self.extract_type_and_title(argtype, argtitle)
629
629
  if (argtype.nil? || argtype == :component || argtype == :whit) &&
630
630
  argtitle =~ /^([^\[\]]+)\[(.+)\]$/m then [ $1, $2 ]
631
- elsif argtitle.nil? && argtype =~ /^([^\[\]]+)\[(.+)\]$/m then [ $1, $2 ]
631
+ elsif argtitle.nil? && argtype.is_a?(String) &&
632
+ argtype =~ /^([^\[\]]+)\[(.+)\]$/m then [ $1, $2 ]
632
633
  elsif argtitle then [ argtype, argtitle ]
633
634
  elsif argtype.is_a?(Puppet::Type) then [ argtype.class.name, argtype.title ]
634
635
  else raise ArgumentError, _("No title provided and %{type} is not a valid resource reference") % { type: argtype.inspect }
@@ -11,6 +11,7 @@ class Puppet::Resource::Type
11
11
  include Puppet::Util::Warnings
12
12
  include Puppet::Util::Errors
13
13
 
14
+ # @deprecated application orchestration will be removed in puppet 7 (capability_mapping, application, site)
14
15
  RESOURCE_KINDS = [:hostclass, :node, :definition, :capability_mapping, :application, :site]
15
16
 
16
17
  # Map the names used in our documentation to the names used internally
@@ -69,6 +70,8 @@ class Puppet::Resource::Type
69
70
 
70
71
  # Evaluate the resources produced by the given resource. These resources are
71
72
  # evaluated in a separate but identical scope from the rest of the resource.
73
+ #
74
+ # @deprecated application orchestration will be removed in puppet 7
72
75
  def evaluate_produces(resource, scope)
73
76
  # Only defined types and classes can produce capabilities
74
77
  return unless definition? || hostclass?
@@ -161,19 +164,23 @@ class Puppet::Resource::Type
161
164
  @module_name = options[:module_name]
162
165
  end
163
166
 
167
+ # @deprecated application orchestration will be removed in puppet 7
164
168
  def produces
165
169
  @produces || EMPTY_ARRAY
166
170
  end
167
171
 
172
+ # @deprecated application orchestration will be removed in puppet 7
168
173
  def consumes
169
174
  @consumes || EMPTY_ARRAY
170
175
  end
171
176
 
177
+ # @deprecated application orchestration will be removed in puppet 7
172
178
  def add_produces(blueprint)
173
179
  @produces ||= []
174
180
  @produces << blueprint
175
181
  end
176
182
 
183
+ # @deprecated application orchestration will be removed in puppet 7
177
184
  def add_consumes(blueprint)
178
185
  @consumes ||= []
179
186
  @consumes << blueprint
@@ -235,6 +242,7 @@ class Puppet::Resource::Type
235
242
  when :node
236
243
  :node
237
244
  when :site
245
+ # @deprecated application orchestration will be removed in puppet 7
238
246
  :site
239
247
  end
240
248
 
@@ -22,9 +22,9 @@ module Puppet::SSL
22
22
  # This is an idiom to initialize a Struct from keyword
23
23
  # arguments. Ruby 2.5 introduced `keyword_init: true` for
24
24
  # that purpose, but we need to support older versions.
25
- def initialize(**kwargs)
25
+ def initialize(kwargs = {})
26
26
  super({})
27
- DEFAULTS.merge(kwargs).each { |k,v| self[k] = v }
27
+ DEFAULTS.merge(**kwargs).each { |k,v| self[k] = v }
28
28
  end
29
29
  end
30
30
  end
@@ -46,13 +46,32 @@ class Puppet::SSL::SSLProvider
46
46
  # perform revocation checking.
47
47
  #
48
48
  # @param cacerts [Array<OpenSSL::X509::Certificate>] Array of trusted CA certs
49
+ # @param path [String, nil] A file containing additional trusted CA certs.
49
50
  # @return [Puppet::SSL::SSLContext] A context to use to create connections
50
51
  # @raise (see #create_context)
51
52
  # @api private
52
- def create_system_context(cacerts:)
53
+ def create_system_context(cacerts:, path: Puppet[:ssl_trust_store])
53
54
  store = create_x509_store(cacerts, [], false)
54
55
  store.set_default_paths
55
56
 
57
+ if path
58
+ stat = Puppet::FileSystem.stat(path)
59
+ if stat
60
+ if stat.ftype == 'file'
61
+ # don't add empty files as ruby/openssl will raise
62
+ if stat.size > 0
63
+ begin
64
+ store.add_file(path)
65
+ rescue => e
66
+ Puppet.err(_("Failed to add '%{path}' as a trusted CA file: %{detail}" % { path: path, detail: e.message }, e))
67
+ end
68
+ end
69
+ else
70
+ Puppet.warning(_("The 'ssl_trust_store' setting does not refer to a file and will be ignored: '%{path}'" % { path: path }))
71
+ end
72
+ end
73
+ end
74
+
56
75
  Puppet::SSL::SSLContext.new(store: store, cacerts: cacerts, crls: [], revocation: false).freeze
57
76
  end
58
77
 
@@ -68,7 +68,14 @@ module Puppet::Test
68
68
  # any individual tests.
69
69
  # @return nil
70
70
  def self.before_all_tests()
71
- # Make sure that all of the setup is also done for any before(:all) blocks
71
+ # The process environment is a shared, persistent resource.
72
+ # Can't use Puppet.features.microsoft_windows? as it may be mocked out in a test. This can cause test recurring test failures
73
+ if (!!File::ALT_SEPARATOR)
74
+ mode = :windows
75
+ else
76
+ mode = :posix
77
+ end
78
+ $old_env = Puppet::Util.get_environment(mode)
72
79
  end
73
80
 
74
81
  # Call this method once, at the end of a test run, when no more tests
@@ -118,15 +125,6 @@ module Puppet::Test
118
125
  }
119
126
  end
120
127
 
121
- # The process environment is a shared, persistent resource.
122
- # Can't use Puppet.features.microsoft_windows? as it may be mocked out in a test. This can cause test recurring test failures
123
- if (!!File::ALT_SEPARATOR)
124
- mode = :windows
125
- else
126
- mode = :posix
127
- end
128
- $old_env = Puppet::Util.get_environment(mode)
129
-
130
128
  # So is the load_path
131
129
  $old_load_path = $LOAD_PATH.dup
132
130
 
@@ -3,11 +3,39 @@ module Puppet::TrustedExternal
3
3
  def retrieve(certname)
4
4
  command = Puppet[:trusted_external_command]
5
5
  return nil unless command
6
+ Puppet.debug _("Retrieving trusted external data from %{command}") % {command: command}
7
+ setting_type = Puppet.settings.setting(:trusted_external_command).type
8
+ if setting_type == :file
9
+ return fetch_data(command, certname)
10
+ end
11
+ # command is a directory. Thus, data is a hash of <basename> => <data> for
12
+ # each executable file in command. For example, if the files 'servicenow.rb',
13
+ # 'unicorn.sh' are in command, then data is the following hash:
14
+ # { 'servicenow' => <servicenow.rb output>, 'unicorn' => <unicorn.sh output> }
15
+ data = {}
16
+ Puppet::FileSystem.children(command).each do |file|
17
+ abs_path = Puppet::FileSystem.expand_path(file)
18
+ executable_file = Puppet::FileSystem.file?(abs_path) && Puppet::FileSystem.executable?(abs_path)
19
+ unless executable_file
20
+ Puppet.debug _("Skipping non-executable file %{file}") % { file: abs_path }
21
+ next
22
+ end
23
+ basename = file.basename(file.extname).to_s
24
+ unless data[basename].nil?
25
+ raise Puppet::Error, _("There is more than one '%{basename}' script in %{dir}") % { basename: basename, dir: command }
26
+ end
27
+ data[basename] = fetch_data(abs_path, certname)
28
+ end
29
+ data
30
+ end
31
+ module_function :retrieve
32
+
33
+ def fetch_data(command, certname)
6
34
  result = Puppet::Util::Execution.execute([command, certname], {
7
35
  :combine => false,
8
36
  :failonfail => true,
9
37
  })
10
38
  JSON.parse(result)
11
39
  end
12
- module_function :retrieve
40
+ module_function :fetch_data
13
41
  end
@@ -116,8 +116,10 @@ class Type
116
116
 
117
117
  # Allow declaring that a type is actually a capability
118
118
  class << self
119
+ # @deprecated application orchestration will be removed in puppet 7
119
120
  attr_accessor :is_capability
120
121
 
122
+ # @deprecated application orchestration will be removed in puppet 7
121
123
  def is_capability?
122
124
  c = is_capability
123
125
  c.nil? ? false : c
@@ -129,6 +131,8 @@ class Type
129
131
  # represent application instances, this implementation always returns
130
132
  # +false+. Having this method though makes code checking whether a
131
133
  # resource is an application instance simpler
134
+ #
135
+ # @deprecated application orchestration will be removed in puppet 7
132
136
  def self.application?
133
137
  false
134
138
  end
@@ -749,7 +753,7 @@ class Type
749
753
  # @param options [Hash] options merged with a fixed set of options defined by this method, passed on to {Puppet::Transaction::Event}.
750
754
  # @return [Puppet::Transaction::Event] the created event
751
755
  def event(options = {})
752
- Puppet::Transaction::Event.new({:resource => self, :file => file, :line => line, :tags => tags}.merge(options))
756
+ Puppet::Transaction::Event.new(**{:resource => self, :file => file, :line => line, :tags => tags}.merge(options))
753
757
  end
754
758
 
755
759
  # @return [Object, nil] Returns the 'should' (wanted state) value for a specified property, or nil if the
@@ -1205,15 +1209,16 @@ class Type
1205
1209
  provider.instances.collect do |instance|
1206
1210
  # We always want to use the "first" provider instance we find, unless the resource
1207
1211
  # is already managed and has a different provider set
1208
- other = provider_instances[instance.name]
1212
+ title = instance.respond_to?(:title) ? instance.title : instance.name
1213
+ other = provider_instances[title]
1209
1214
  if other
1210
1215
  Puppet.debug "%s %s found in both %s and %s; skipping the %s version" %
1211
- [self.name.to_s.capitalize, instance.name, other.class.name, instance.class.name, instance.class.name]
1216
+ [self.name.to_s.capitalize, title, other.class.name, instance.class.name, instance.class.name]
1212
1217
  next
1213
1218
  end
1214
- provider_instances[instance.name] = instance
1219
+ provider_instances[title] = instance
1215
1220
 
1216
- result = new(:name => instance.name, :provider => instance)
1221
+ result = new(:name => instance.name, :provider => instance, :title => title)
1217
1222
  properties.each { |name| result.newattr(name) }
1218
1223
  result
1219
1224
  end
@@ -1714,6 +1719,7 @@ class Type
1714
1719
  }
1715
1720
  end
1716
1721
 
1722
+ # @deprecated application orchestration will be removed in puppet 7
1717
1723
  newmetaparam(:export, :parent => RelationshipMetaparam, :attributes => {:direction => :out, :events => :NONE}) do
1718
1724
  desc <<EOS
1719
1725
  Export a capability resource.
@@ -1739,6 +1745,7 @@ web { server:
1739
1745
  EOS
1740
1746
  end
1741
1747
 
1748
+ # @deprecated application orchestration will be removed in puppet 7
1742
1749
  newmetaparam(:consume, :parent => RelationshipMetaparam, :attributes => {:direction => :in, :events => :NONE}) do
1743
1750
  desc <<EOS
1744
1751
  Consume a capability resource.
@@ -401,8 +401,12 @@ Puppet::Type.newtype(:file) do
401
401
  end
402
402
  end
403
403
 
404
- CREATORS = [:content, :source, :target]
405
- SOURCE_ONLY_CHECKSUMS = [:none, :ctime, :mtime]
404
+ # mutually exclusive ways to create files
405
+ CREATORS = [:content, :source, :target].freeze
406
+
407
+ # This is both "checksum types that can't be used with the content property"
408
+ # and "checksum types that are not digest based"
409
+ SOURCE_ONLY_CHECKSUMS = [:none, :ctime, :mtime].freeze
406
410
 
407
411
  validate do
408
412
  creator_count = 0
@@ -428,7 +432,7 @@ Puppet::Type.newtype(:file) do
428
432
  @parameters[:content].value = @parameters[:checksum].sum(@parameters[:content].actual_content)
429
433
  end
430
434
 
431
- if self[:checksum] && self[:checksum_value] && !send("#{self[:checksum]}?", self[:checksum_value])
435
+ if self[:checksum] && self[:checksum_value] && !valid_checksum?(self[:checksum], self[:checksum_value])
432
436
  self.fail _("Checksum value '%{value}' is not a valid checksum type %{checksum}") % { value: self[:checksum_value], checksum: self[:checksum] }
433
437
  end
434
438
 
@@ -930,7 +934,7 @@ Puppet::Type.newtype(:file) do
930
934
  # that out.
931
935
  end
932
936
 
933
- fail_if_checksum_is_wrong(file.path, content_checksum) if validate_checksum?
937
+ fail_if_checksum_is_wrong(property, file.path, content_checksum)
934
938
  end
935
939
  else
936
940
  umask = mode ? 000 : 022
@@ -1040,17 +1044,38 @@ Puppet::Type.newtype(:file) do
1040
1044
  end
1041
1045
  end
1042
1046
 
1043
- # Should we validate the checksum of the file we're writing?
1044
- def validate_checksum?
1045
- self[:checksum] !~ /time/
1046
- end
1047
-
1048
1047
  # Make sure the file we wrote out is what we think it is.
1049
- def fail_if_checksum_is_wrong(path, content_checksum)
1050
- newsum = parameter(:checksum).sum_file(path)
1051
- return if [:absent, nil, content_checksum].include?(newsum)
1048
+ # @param [Puppet::Parameter] property the param or property that wrote the file, or nil
1049
+ # @param [String] path to the file
1050
+ # @param [String] the checksum for the local file
1051
+ #
1052
+ # @api private
1053
+ #
1054
+ def fail_if_checksum_is_wrong(property, path, content_checksum)
1055
+ desired_checksum = desired_checksum(property, path)
1052
1056
 
1053
- self.fail _("File written to disk did not match checksum; discarding changes (%{content_checksum} vs %{newsum})") % { content_checksum: content_checksum, newsum: newsum }
1057
+ if desired_checksum && content_checksum != desired_checksum
1058
+ self.fail _("File written to disk did not match desired checksum; discarding changes (%{content_checksum} vs %{desired_checksum})") % { content_checksum: content_checksum, desired_checksum: desired_checksum }
1059
+ end
1060
+ end
1061
+
1062
+ # Return the desired checksum or nil
1063
+ def desired_checksum(property, path)
1064
+ return if SOURCE_ONLY_CHECKSUMS.include?(self[:checksum])
1065
+
1066
+ if self[:checksum] && self[:checksum_value]
1067
+ "{#{self[:checksum]}}#{self[:checksum_value]}"
1068
+ elsif property && property.name == :source
1069
+ meta = property.metadata
1070
+ return unless meta
1071
+
1072
+ # due to HttpMetadata the checksum type may fallback to mtime, so recheck
1073
+ return if SOURCE_ONLY_CHECKSUMS.include?(meta.checksum_type)
1074
+ meta.checksum
1075
+ elsif property && property.name == :content
1076
+ str = property.actual_content
1077
+ str ? parameter(:checksum).sum(str) : nil
1078
+ end
1054
1079
  end
1055
1080
 
1056
1081
  def write_temporary_file?
@@ -9,7 +9,7 @@ Puppet::Type.type(:file).newparam(:checksum) do
9
9
 
10
10
  The default checksum type is md5."
11
11
 
12
- newvalues "md5", "md5lite", "sha224", "sha256", "sha256lite", "sha384", "sha512", "mtime", "ctime", "none"
12
+ newvalues(*Puppet::Util::Checksums.known_checksum_types)
13
13
 
14
14
  defaultto do
15
15
  Puppet[:digest_algorithm].to_sym
@@ -23,18 +23,18 @@ Puppet::Type.type(:file).newparam(:checksum) do
23
23
 
24
24
  def sum(content)
25
25
  content = content.is_a?(Puppet::Pops::Types::PBinaryType::Binary) ? content.binary_buffer : content
26
- type = digest_algorithm()
26
+ type = digest_algorithm
27
27
  "{#{type}}" + send(type, content)
28
28
  end
29
29
 
30
30
  def sum_file(path)
31
- type = digest_algorithm()
31
+ type = digest_algorithm
32
32
  method = type.to_s + "_file"
33
33
  "{#{type}}" + send(method, path).to_s
34
34
  end
35
35
 
36
36
  def sum_stream(&block)
37
- type = digest_algorithm()
37
+ type = digest_algorithm
38
38
  method = type.to_s + "_stream"
39
39
  checksum = send(method, &block)
40
40
  "{#{type}}#{checksum}"
@@ -98,8 +98,8 @@ module Puppet
98
98
  # Ruby 1.9.3 and earlier have a URI bug in URI
99
99
  # to_s returns an ASCII string despite UTF-8 fragments
100
100
  # since its escaped its safe to universally call encode
101
- # URI.unescape always returns strings in the original encoding
102
- URI.unescape(uri_string.encode(Encoding::UTF_8))
101
+ # Puppet::Util.uri_unescape always returns strings in the original encoding
102
+ Puppet::Util.uri_unescape(uri_string.encode(Encoding::UTF_8))
103
103
  else
104
104
  source
105
105
  end
@@ -278,7 +278,7 @@ module Puppet
278
278
  api = session.route_to(:fileserver, url: url)
279
279
 
280
280
  api.get_static_file_content(
281
- path: URI.unescape(url.path),
281
+ path: Puppet::Util.uri_unescape(url.path),
282
282
  environment: resource.catalog.environment_instance.to_s,
283
283
  code_id: resource.catalog.code_id,
284
284
  &block
@@ -290,7 +290,7 @@ module Puppet
290
290
  api = session.route_to(:fileserver, url: url)
291
291
 
292
292
  api.get_file_content(
293
- path: URI.unescape(url.path),
293
+ path: Puppet::Util.uri_unescape(url.path),
294
294
  environment: resource.catalog.environment_instance.to_s,
295
295
  &block
296
296
  )
@@ -47,6 +47,8 @@ module Puppet
47
47
 
48
48
  feature :configurable_timeout, "The provider can specify a minumum timeout for syncing service properties"
49
49
 
50
+ feature :manages_logon_credentials, "The provider can specify the logon credentials used for a service"
51
+
50
52
  newproperty(:enable, :required_features => :enableable) do
51
53
  desc "Whether a service should be enabled to start at boot.
52
54
  This property behaves differently depending on the platform;
@@ -116,6 +118,12 @@ module Puppet
116
118
  end
117
119
 
118
120
  def sync
121
+ property = @resource.property(:logonaccount)
122
+ if property
123
+ val = property.retrieve
124
+ property.sync unless property.safe_insync?(val)
125
+ end
126
+
119
127
  event = super()
120
128
 
121
129
  property = @resource.property(:enable)
@@ -128,6 +136,47 @@ module Puppet
128
136
  end
129
137
  end
130
138
 
139
+ newproperty(:logonaccount, :required_features => :manages_logon_credentials) do
140
+ desc "Specify an account for service logon"
141
+
142
+ munge do |value|
143
+ return value unless Puppet::Util::Platform.windows?
144
+ return 'LocalSystem' if Puppet::Util::Windows::User::localsystem?(value)
145
+
146
+ value.sub!(/^\.\\/, "#{Puppet::Util::Windows::ADSI.computer_name}\\")
147
+ user_information = Puppet::Util::Windows::SID.name_to_principal(value)
148
+ raise Puppet::Error.new("\"#{value}\" is not a valid account") unless user_information && [:SidTypeUser, :SidTypeWellKnownGroup].include?(user_information.account_type)
149
+
150
+ if user_information.domain == Puppet::Util::Windows::ADSI.computer_name
151
+ ".\\#{user_information.account}"
152
+ else
153
+ user_information.domain_account
154
+ end
155
+ end
156
+ end
157
+
158
+ newparam(:logonpassword, :required_features => :manages_logon_credentials) do
159
+ desc "Specify a password for service logon. Default value is an empty string (when logonaccount is specified)."
160
+
161
+ validate do |value|
162
+ raise Puppet::Error.new(_"The 'logonaccount' parameter is mandatory when setting 'logonpassword'.") unless @resource[:logonaccount]
163
+ raise ArgumentError, _("Passwords cannot include ':'") if value.is_a?(String) and value.include?(":")
164
+ return unless Puppet::Util::Platform.windows?
165
+
166
+ is_a_predefined_local_account = Puppet::Util::Windows::User::default_system_account?(@resource[:logonaccount]) || @resource[:logonaccount] == 'LocalSystem'
167
+
168
+ account_info = @resource[:logonaccount].split("\\")
169
+ able_to_logon = Puppet::Util::Windows::User.password_is?(account_info[1], value, account_info[0]) unless is_a_predefined_local_account
170
+
171
+ raise Puppet::Error.new("The given password is invalid for user '#{@resource[:logonaccount]}'.") unless is_a_predefined_local_account || able_to_logon
172
+
173
+ provider.logonpassword=(value)
174
+ end
175
+
176
+ sensitive true
177
+ defaultto { @resource[:logonaccount] ? "" : nil }
178
+ end
179
+
131
180
  newproperty(:flags, :required_features => :flaggable) do
132
181
  desc "Specify a string of flags to pass to the startup script."
133
182
  end