puppet 2.7.5 → 2.7.6

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 (140) hide show
  1. data/CHANGELOG +121 -0
  2. data/conf/redhat/puppet.spec +16 -7
  3. data/lib/puppet.rb +1 -1
  4. data/lib/puppet/application/cert.rb +17 -3
  5. data/lib/puppet/application/device.rb +1 -0
  6. data/lib/puppet/application/kick.rb +0 -2
  7. data/lib/puppet/application/resource.rb +73 -66
  8. data/lib/puppet/configurer/plugin_handler.rb +6 -2
  9. data/lib/puppet/defaults.rb +60 -5
  10. data/lib/puppet/face/ca.rb +11 -2
  11. data/lib/puppet/face/certificate.rb +33 -4
  12. data/lib/puppet/file_serving/fileset.rb +1 -1
  13. data/lib/puppet/file_serving/indirection_hooks.rb +2 -2
  14. data/lib/puppet/file_serving/metadata.rb +43 -4
  15. data/lib/puppet/indirector.rb +0 -1
  16. data/lib/puppet/indirector/request.rb +3 -4
  17. data/lib/puppet/indirector/resource/active_record.rb +3 -10
  18. data/lib/puppet/indirector/resource/ral.rb +2 -2
  19. data/lib/puppet/indirector/rest.rb +1 -1
  20. data/lib/puppet/network/handler/ca.rb +16 -106
  21. data/lib/puppet/network/handler/master.rb +0 -3
  22. data/lib/puppet/network/handler/runner.rb +1 -0
  23. data/lib/puppet/parser/scope.rb +10 -0
  24. data/lib/puppet/provider/file/posix.rb +72 -34
  25. data/lib/puppet/provider/file/windows.rb +100 -0
  26. data/lib/puppet/provider/group/windows_adsi.rb +2 -2
  27. data/lib/puppet/provider/user/windows_adsi.rb +19 -4
  28. data/lib/puppet/resource.rb +16 -0
  29. data/lib/puppet/resource/catalog.rb +1 -1
  30. data/lib/puppet/ssl/certificate.rb +2 -2
  31. data/lib/puppet/ssl/certificate_authority.rb +86 -10
  32. data/lib/puppet/ssl/certificate_authority/interface.rb +64 -19
  33. data/lib/puppet/ssl/certificate_factory.rb +112 -91
  34. data/lib/puppet/ssl/certificate_request.rb +88 -1
  35. data/lib/puppet/ssl/host.rb +20 -3
  36. data/lib/puppet/type/file.rb +15 -34
  37. data/lib/puppet/type/file/group.rb +11 -91
  38. data/lib/puppet/type/file/mode.rb +11 -41
  39. data/lib/puppet/type/file/owner.rb +18 -34
  40. data/lib/puppet/type/file/source.rb +22 -7
  41. data/lib/puppet/type/group.rb +4 -3
  42. data/lib/puppet/type/user.rb +4 -1
  43. data/lib/puppet/util.rb +59 -6
  44. data/lib/puppet/util/adsi.rb +11 -0
  45. data/lib/puppet/util/log.rb +4 -0
  46. data/lib/puppet/util/log/destinations.rb +7 -1
  47. data/lib/puppet/util/monkey_patches.rb +19 -0
  48. data/lib/puppet/util/network_device/config.rb +4 -5
  49. data/lib/puppet/util/settings.rb +5 -0
  50. data/lib/puppet/util/suidmanager.rb +0 -1
  51. data/lib/puppet/util/windows.rb +4 -0
  52. data/lib/puppet/util/windows/error.rb +16 -0
  53. data/lib/puppet/util/windows/security.rb +593 -0
  54. data/spec/integration/defaults_spec.rb +27 -0
  55. data/spec/integration/network/handler_spec.rb +1 -1
  56. data/spec/integration/type/file_spec.rb +382 -145
  57. data/spec/integration/util/windows/security_spec.rb +468 -0
  58. data/spec/shared_behaviours/file_serving.rb +4 -3
  59. data/spec/unit/application/agent_spec.rb +1 -0
  60. data/spec/unit/application/device_spec.rb +5 -0
  61. data/spec/unit/application/resource_spec.rb +62 -101
  62. data/spec/unit/configurer/downloader_spec.rb +2 -2
  63. data/spec/unit/configurer/plugin_handler_spec.rb +15 -8
  64. data/spec/unit/configurer_spec.rb +2 -2
  65. data/spec/unit/face/ca_spec.rb +34 -0
  66. data/spec/unit/face/certificate_spec.rb +168 -1
  67. data/spec/unit/file_serving/fileset_spec.rb +1 -1
  68. data/spec/unit/file_serving/indirection_hooks_spec.rb +1 -1
  69. data/spec/unit/file_serving/metadata_spec.rb +151 -107
  70. data/spec/unit/indirector/certificate_request/ca_spec.rb +0 -3
  71. data/spec/unit/indirector/direct_file_server_spec.rb +10 -9
  72. data/spec/unit/indirector/file_metadata/file_spec.rb +6 -4
  73. data/spec/unit/indirector/request_spec.rb +13 -3
  74. data/spec/unit/indirector/resource/active_record_spec.rb +4 -10
  75. data/spec/unit/indirector/resource/ral_spec.rb +6 -4
  76. data/spec/unit/indirector/rest_spec.rb +5 -6
  77. data/spec/unit/network/handler/ca_spec.rb +86 -0
  78. data/spec/unit/parser/collector_spec.rb +7 -7
  79. data/spec/unit/parser/scope_spec.rb +20 -0
  80. data/spec/unit/provider/file/posix_spec.rb +226 -0
  81. data/spec/unit/provider/file/windows_spec.rb +136 -0
  82. data/spec/unit/provider/group/windows_adsi_spec.rb +7 -2
  83. data/spec/unit/provider/user/windows_adsi_spec.rb +36 -3
  84. data/spec/unit/resource/catalog_spec.rb +20 -10
  85. data/spec/unit/resource_spec.rb +55 -8
  86. data/spec/unit/ssl/certificate_authority/interface_spec.rb +97 -54
  87. data/spec/unit/ssl/certificate_authority_spec.rb +133 -23
  88. data/spec/unit/ssl/certificate_factory_spec.rb +90 -70
  89. data/spec/unit/ssl/certificate_request_spec.rb +62 -1
  90. data/spec/unit/ssl/certificate_spec.rb +20 -14
  91. data/spec/unit/ssl/host_spec.rb +52 -6
  92. data/spec/unit/type/file/content_spec.rb +4 -4
  93. data/spec/unit/type/file/group_spec.rb +34 -96
  94. data/spec/unit/type/file/mode_spec.rb +88 -0
  95. data/spec/unit/type/file/owner_spec.rb +32 -123
  96. data/spec/unit/type/file/source_spec.rb +120 -41
  97. data/spec/unit/type/file_spec.rb +1033 -753
  98. data/spec/unit/type_spec.rb +19 -1
  99. data/spec/unit/util/adsi_spec.rb +19 -0
  100. data/spec/unit/util/log/destinations_spec.rb +75 -0
  101. data/spec/unit/util/log_spec.rb +15 -0
  102. data/spec/unit/util/network_device/config_spec.rb +7 -0
  103. data/spec/unit/util/settings_spec.rb +10 -0
  104. data/spec/unit/util_spec.rb +126 -13
  105. data/test/language/functions.rb +0 -1
  106. data/test/language/snippets.rb +0 -9
  107. data/test/lib/puppettest/exetest.rb +1 -1
  108. data/test/lib/puppettest/servertest.rb +0 -1
  109. data/test/rails/rails.rb +0 -1
  110. data/test/ral/type/filesources.rb +0 -60
  111. metadata +13 -33
  112. data/lib/puppet/network/client.rb +0 -174
  113. data/lib/puppet/network/client/ca.rb +0 -56
  114. data/lib/puppet/network/client/file.rb +0 -6
  115. data/lib/puppet/network/client/proxy.rb +0 -27
  116. data/lib/puppet/network/client/report.rb +0 -26
  117. data/lib/puppet/network/client/runner.rb +0 -10
  118. data/lib/puppet/network/client/status.rb +0 -4
  119. data/lib/puppet/network/http_server.rb +0 -3
  120. data/lib/puppet/network/http_server/mongrel.rb +0 -130
  121. data/lib/puppet/network/http_server/webrick.rb +0 -155
  122. data/lib/puppet/network/xmlrpc/client.rb +0 -211
  123. data/lib/puppet/provider/file/win32.rb +0 -72
  124. data/lib/puppet/sslcertificates.rb +0 -146
  125. data/lib/puppet/sslcertificates/ca.rb +0 -375
  126. data/lib/puppet/sslcertificates/certificate.rb +0 -255
  127. data/lib/puppet/sslcertificates/inventory.rb +0 -38
  128. data/lib/puppet/sslcertificates/support.rb +0 -146
  129. data/spec/integration/network/client_spec.rb +0 -18
  130. data/spec/unit/network/xmlrpc/client_spec.rb +0 -172
  131. data/spec/unit/sslcertificates/ca_spec.rb +0 -106
  132. data/test/certmgr/certmgr.rb +0 -308
  133. data/test/certmgr/inventory.rb +0 -69
  134. data/test/certmgr/support.rb +0 -105
  135. data/test/network/client/ca.rb +0 -69
  136. data/test/network/client/dipper.rb +0 -34
  137. data/test/network/handler/ca.rb +0 -273
  138. data/test/network/server/mongrel_test.rb +0 -99
  139. data/test/network/server/webrick.rb +0 -111
  140. data/test/network/xmlrpc/client.rb +0 -45
@@ -34,6 +34,10 @@ class Puppet::SSL::Host
34
34
  @localhost
35
35
  end
36
36
 
37
+ def self.reset
38
+ @localhost = nil
39
+ end
40
+
37
41
  # This is the constant that people will use to mark that a given host is
38
42
  # a certificate authority.
39
43
  def self.ca_name
@@ -152,11 +156,24 @@ class Puppet::SSL::Host
152
156
  @certificate_request ||= CertificateRequest.indirection.find(name)
153
157
  end
154
158
 
159
+ def this_csr_is_for_the_current_host
160
+ name == Puppet[:certname].downcase
161
+ end
162
+
155
163
  # Our certificate request requires the key but that's all.
156
- def generate_certificate_request
164
+ def generate_certificate_request(options = {})
157
165
  generate_key unless key
166
+
167
+ # If this is for the current machine...
168
+ if this_csr_is_for_the_current_host
169
+ # ...add our configured dns_alt_names
170
+ if Puppet[:dns_alt_names] and Puppet[:dns_alt_names] != ''
171
+ options[:dns_alt_names] ||= Puppet[:dns_alt_names]
172
+ end
173
+ end
174
+
158
175
  @certificate_request = CertificateRequest.new(name)
159
- @certificate_request.generate(key.content)
176
+ @certificate_request.generate(key.content, options)
160
177
  begin
161
178
  CertificateRequest.indirection.save(@certificate_request)
162
179
  rescue
@@ -199,7 +216,7 @@ class Puppet::SSL::Host
199
216
  # should use it to sign our request; else, just try to read
200
217
  # the cert.
201
218
  if ! certificate and ca = Puppet::SSL::CertificateAuthority.instance
202
- ca.sign(self.name)
219
+ ca.sign(self.name, true)
203
220
  end
204
221
  end
205
222
 
@@ -3,10 +3,11 @@ require 'cgi'
3
3
  require 'etc'
4
4
  require 'uri'
5
5
  require 'fileutils'
6
+ require 'enumerator'
7
+ require 'pathname'
6
8
  require 'puppet/network/handler'
7
9
  require 'puppet/util/diff'
8
10
  require 'puppet/util/checksums'
9
- require 'puppet/network/client'
10
11
  require 'puppet/util/backups'
11
12
 
12
13
  Puppet::Type.newtype(:file) do
@@ -35,8 +36,7 @@ Puppet::Type.newtype(:file) do
35
36
  isnamevar
36
37
 
37
38
  validate do |value|
38
- # accept various path syntaxes: lone slash, posix, win32, unc
39
- unless (Puppet.features.posix? and value =~ /^\//) or (value =~ /^[A-Za-z]:\// or value =~ /^\/\/[^\/]+\/[^\/]+/)
39
+ unless Puppet::Util.absolute_path?(value)
40
40
  fail Puppet::Error, "File paths must be fully qualified, not '#{value}'"
41
41
  end
42
42
  end
@@ -44,20 +44,8 @@ Puppet::Type.newtype(:file) do
44
44
  # convert the current path in an index into the collection and the last
45
45
  # path name. The aim is to use less storage for all common paths in a hierarchy
46
46
  munge do |value|
47
- # We need to save off, and remove the volume designator in the
48
- # path if it is there, since File.split does not handle paths
49
- # with volume designators properly, except when run on Windows.
50
- # Since we are potentially compiling a catalog for a Windows
51
- # machine on a non-Windows master, we need to handle this
52
- # ourselves.
53
- optional_volume_designator = value.match(/^([a-z]:)[\/\\].*/i)
54
- value_without_designator = value.sub(/^(?:[a-z]:)?(.*)/i, '\1')
55
-
56
- path, name = ::File.split(value_without_designator.gsub(/\/+/,'/'))
57
-
58
- if optional_volume_designator
59
- path = optional_volume_designator[1] + path
60
- end
47
+ # We know the value is absolute, so expanding it will just standardize it.
48
+ path, name = ::File.split(::File.expand_path value)
61
49
 
62
50
  { :index => Puppet::FileCollection.collection.index(path), :name => name }
63
51
  end
@@ -65,12 +53,8 @@ Puppet::Type.newtype(:file) do
65
53
  # and the reverse
66
54
  unmunge do |value|
67
55
  basedir = Puppet::FileCollection.collection.path(value[:index])
68
- # a lone slash as :name indicates a root dir on windows
69
- if value[:name] == '/'
70
- basedir
71
- else
72
- ::File.join( basedir, value[:name] )
73
- end
56
+
57
+ ::File.expand_path ::File.join( basedir, value[:name] )
74
58
  end
75
59
  end
76
60
 
@@ -275,17 +259,12 @@ Puppet::Type.newtype(:file) do
275
259
 
276
260
  # Autorequire the nearest ancestor directory found in the catalog.
277
261
  autorequire(:file) do
278
- basedir = ::File.dirname(self[:path])
279
- if basedir != self[:path]
280
- parents = []
281
- until basedir == parents.last
282
- parents << basedir
283
- basedir = ::File.dirname(basedir)
284
- end
285
- # The filename of the first ancestor found, or nil
286
- parents.find { |dir| catalog.resource(:file, dir) }
287
- else
288
- nil
262
+ path = Pathname(self[:path])
263
+ if !path.root?
264
+ # Start at our parent, to avoid autorequiring ourself
265
+ parents = path.parent.enum_for(:ascend)
266
+ found = parents.find { |p| catalog.resource(:file, p.to_s) }
267
+ found and found.to_s
289
268
  end
290
269
  end
291
270
 
@@ -632,6 +611,7 @@ Puppet::Type.newtype(:file) do
632
611
  FileUtils.rmtree(self[:path])
633
612
  else
634
613
  notice "Not removing directory; use 'force' to override"
614
+ return
635
615
  end
636
616
  when "link", "file"
637
617
  debug "Removing existing #{s.ftype} for replacement with #{should}"
@@ -640,6 +620,7 @@ Puppet::Type.newtype(:file) do
640
620
  self.fail "Could not back up files of type #{s.ftype}"
641
621
  end
642
622
  @stat = :needs_stat
623
+ true
643
624
  end
644
625
 
645
626
  def retrieve
@@ -3,111 +3,31 @@ require 'puppet/util/posix'
3
3
  # Manage file group ownership.
4
4
  module Puppet
5
5
  Puppet::Type.type(:file).newproperty(:group) do
6
- include Puppet::Util::POSIX
7
-
8
- require 'etc'
9
6
  desc "Which group should own the file. Argument can be either group
10
7
  name or group ID."
11
- @event = :file_changed
12
8
 
13
9
  validate do |group|
14
10
  raise(Puppet::Error, "Invalid group name '#{group.inspect}'") unless group and group != ""
15
11
  end
16
12
 
17
- def id2name(id)
18
- return id.to_s if id.is_a?(Symbol)
19
- return nil if id > Puppet[:maximum_uid].to_i
20
- begin
21
- group = Etc.getgrgid(id)
22
- rescue ArgumentError
23
- return nil
24
- end
25
- if group.gid == ""
26
- return nil
27
- else
28
- return group.name
29
- end
30
- end
31
-
32
- # We want to print names, not numbers
33
- def is_to_s(currentvalue)
34
- if currentvalue.is_a? Integer
35
- id2name(currentvalue) || currentvalue
36
- else
37
- return currentvalue.to_s
38
- end
39
- end
40
-
41
- def should_to_s(newvalue = @should)
42
- if newvalue.is_a? Integer
43
- id2name(newvalue) || newvalue
44
- else
45
- return newvalue.to_s
46
- end
47
- end
48
-
49
13
  def insync?(current)
50
- @should.each do |value|
51
- if value =~ /^\d+$/
52
- gid = Integer(value)
53
- elsif value.is_a?(String)
54
- fail "Could not find group #{value}" unless gid = gid(value)
55
- else
56
- gid = value
57
- end
58
-
59
- return true if gid == current
14
+ # We don't want to validate/munge groups until we actually start to
15
+ # evaluate this property, because they might be added during the catalog
16
+ # apply.
17
+ @should.map! do |val|
18
+ provider.name2gid(val) or raise "Could not find group #{val}"
60
19
  end
61
- false
62
- end
63
-
64
- def retrieve
65
- return :absent unless stat = resource.stat
66
20
 
67
- currentvalue = stat.gid
68
-
69
- # On OS X, files that are owned by -2 get returned as really
70
- # large GIDs instead of negative ones. This isn't a Ruby bug,
71
- # it's an OS X bug, since it shows up in perl, too.
72
- if currentvalue > Puppet[:maximum_uid].to_i
73
- self.warning "Apparently using negative GID (#{currentvalue}) on a platform that does not consistently handle them"
74
- currentvalue = :silly
75
- end
76
-
77
- currentvalue
21
+ @should.include?(current)
78
22
  end
79
23
 
80
- # Determine if the group is valid, and if so, return the GID
81
- def validgroup?(value)
82
- Integer(value) rescue gid(value) || false
24
+ # We want to print names, not numbers
25
+ def is_to_s(currentvalue)
26
+ provider.gid2name(currentvalue) || currentvalue
83
27
  end
84
28
 
85
- # Normal users will only be able to manage certain groups. Right now,
86
- # we'll just let it fail, but we should probably set things up so
87
- # that users get warned if they try to change to an unacceptable group.
88
- def sync
89
- # Set our method appropriately, depending on links.
90
- if resource[:links] == :manage
91
- method = :lchown
92
- else
93
- method = :chown
94
- end
95
-
96
- gid = nil
97
- @should.each do |group|
98
- break if gid = validgroup?(group)
99
- end
100
-
101
- raise Puppet::Error, "Could not find group(s) #{@should.join(",")}" unless gid
102
-
103
- begin
104
- # set owner to nil so it's ignored
105
- File.send(method, nil, gid, resource[:path])
106
- rescue => detail
107
- error = Puppet::Error.new( "failed to chgrp #{resource[:path]} to #{gid}: #{detail.message}")
108
- raise error
109
- end
110
- :file_changed
29
+ def should_to_s(newvalue)
30
+ provider.gid2name(newvalue) || newvalue
111
31
  end
112
32
  end
113
33
  end
@@ -3,7 +3,6 @@
3
3
  # specifying the full mode.
4
4
  module Puppet
5
5
  Puppet::Type.type(:file).newproperty(:mode) do
6
- require 'etc'
7
6
  desc "Mode the file should be. Currently relatively limited:
8
7
  you must specify the exact mode the file should be.
9
8
 
@@ -23,33 +22,31 @@ module Puppet
23
22
  In this case all of the files underneath `/some/dir` will have
24
23
  mode 644, and all of the directories will have mode 755."
25
24
 
26
- @event = :file_changed
25
+ validate do |value|
26
+ if value.is_a?(String) and value !~ /^[0-7]+$/
27
+ raise Puppet::Error, "File modes can only be octal numbers, not #{should.inspect}"
28
+ end
29
+ end
27
30
 
28
31
  munge do |should|
29
- if should.is_a?(String)
30
- unless should =~ /^[0-7]+$/
31
- raise Puppet::Error, "File modes can only be octal numbers, not #{should.inspect}"
32
- end
33
- should.to_i(8).to_s(8)
34
- else
35
- should.to_s(8)
36
- end
32
+ dirmask(should)
37
33
  end
38
34
 
39
35
  # If we're a directory, we need to be executable for all cases
40
36
  # that are readable. This should probably be selectable, but eh.
41
37
  def dirmask(value)
42
- if FileTest.directory?(@resource[:path])
43
- value = value.to_i(8)
38
+ value = value.to_i(8) unless value.is_a? Integer
39
+ if FileTest.directory?(resource[:path])
44
40
  value |= 0100 if value & 0400 != 0
45
41
  value |= 010 if value & 040 != 0
46
42
  value |= 01 if value & 04 != 0
47
- value = value.to_s(8)
48
43
  end
49
44
 
50
- value
45
+ value.to_s(8)
51
46
  end
52
47
 
48
+ # If we're not following links and we're a link, then we just turn
49
+ # off mode management entirely.
53
50
  def insync?(currentvalue)
54
51
  if stat = @resource.stat and stat.ftype == "link" and @resource[:links] != :follow
55
52
  self.debug "Not managing symlink mode"
@@ -58,33 +55,6 @@ module Puppet
58
55
  return super(currentvalue)
59
56
  end
60
57
  end
61
-
62
- def retrieve
63
- # If we're not following links and we're a link, then we just turn
64
- # off mode management entirely.
65
-
66
- if stat = @resource.stat
67
- unless defined?(@fixed)
68
- @should &&= @should.collect { |s| self.dirmask(s) }
69
- end
70
- return (stat.mode & 007777).to_s(8)
71
- else
72
- return :absent
73
- end
74
- end
75
-
76
- def sync
77
- mode = self.should
78
-
79
- begin
80
- File.chmod(mode.to_i(8), @resource[:path])
81
- rescue => detail
82
- error = Puppet::Error.new("failed to chmod #{@resource[:path]}: #{detail.message}")
83
- error.set_backtrace detail.backtrace
84
- raise error
85
- end
86
- :file_changed
87
- end
88
58
  end
89
59
  end
90
60
 
@@ -1,51 +1,35 @@
1
1
  module Puppet
2
2
  Puppet::Type.type(:file).newproperty(:owner) do
3
+ include Puppet::Util::Warnings
3
4
 
4
5
  desc "To whom the file should belong. Argument can be user name or
5
6
  user ID."
6
- @event = :file_changed
7
7
 
8
8
  def insync?(current)
9
- provider.is_owner_insync?(current, @should)
10
- end
9
+ # We don't want to validate/munge users until we actually start to
10
+ # evaluate this property, because they might be added during the catalog
11
+ # apply.
12
+ @should.map! do |val|
13
+ provider.name2uid(val) or raise "Could not find user #{val}"
14
+ end
11
15
 
12
- # We want to print names, not numbers
13
- def is_to_s(currentvalue)
14
- provider.id2name(currentvalue) || currentvalue
15
- end
16
+ return true if @should.include?(current)
16
17
 
17
- def should_to_s(newvalue = @should)
18
- case newvalue
19
- when Symbol
20
- newvalue.to_s
21
- when Integer
22
- provider.id2name(newvalue) || newvalue
23
- when String
24
- newvalue
25
- else
26
- raise Puppet::DevError, "Invalid uid type #{newvalue.class}(#{newvalue})"
18
+ unless Puppet.features.root?
19
+ warnonce "Cannot manage ownership unless running as root"
20
+ return true
27
21
  end
22
+
23
+ false
28
24
  end
29
25
 
30
- def retrieve
31
- if self.should
32
- @should = @should.collect do |val|
33
- unless val.is_a?(Integer)
34
- if tmp = provider.validuser?(val)
35
- val = tmp
36
- else
37
- raise "Could not find user #{val}"
38
- end
39
- else
40
- val
41
- end
42
- end
43
- end
44
- provider.retrieve(@resource)
26
+ # We want to print names, not numbers
27
+ def is_to_s(currentvalue)
28
+ provider.uid2name(currentvalue) || currentvalue
45
29
  end
46
30
 
47
- def sync
48
- provider.sync(resource[:path], resource[:links], @should)
31
+ def should_to_s(newvalue)
32
+ provider.uid2name(newvalue) || newvalue
49
33
  end
50
34
  end
51
35
  end
@@ -66,19 +66,33 @@ module Puppet
66
66
  validate do |sources|
67
67
  sources = [sources] unless sources.is_a?(Array)
68
68
  sources.each do |source|
69
+ next if Puppet::Util.absolute_path?(source)
70
+
69
71
  begin
70
72
  uri = URI.parse(URI.escape(source))
71
73
  rescue => detail
72
74
  self.fail "Could not understand source #{source}: #{detail}"
73
75
  end
74
76
 
75
- self.fail "Cannot use URLs of type '#{uri.scheme}' as source for fileserving" unless uri.scheme.nil? or %w{file puppet}.include?(uri.scheme) or (Puppet.features.microsoft_windows? and uri.scheme =~ /^[a-z]$/i)
77
+ self.fail "Cannot use relative URLs '#{source}'" unless uri.absolute?
78
+ self.fail "Cannot use opaque URLs '#{source}'" unless uri.hierarchical?
79
+ self.fail "Cannot use URLs of type '#{uri.scheme}' as source for fileserving" unless %w{file puppet}.include?(uri.scheme)
76
80
  end
77
81
  end
78
82
 
83
+ SEPARATOR_REGEX = [Regexp.escape(File::SEPARATOR.to_s), Regexp.escape(File::ALT_SEPARATOR.to_s)].join
84
+
79
85
  munge do |sources|
80
86
  sources = [sources] unless sources.is_a?(Array)
81
- sources.collect { |source| source.sub(/\/$/, '') }
87
+ sources.map do |source|
88
+ source = source.sub(/[#{SEPARATOR_REGEX}]+$/, '')
89
+
90
+ if Puppet::Util.absolute_path?(source)
91
+ URI.unescape(Puppet::Util.path_to_uri(source).to_s)
92
+ else
93
+ source
94
+ end
95
+ end
82
96
  end
83
97
 
84
98
  def change_to_s(currentvalue, newvalue)
@@ -162,11 +176,11 @@ module Puppet
162
176
  end
163
177
 
164
178
  def local?
165
- found? and uri and (uri.scheme || "file") == "file"
179
+ found? and scheme == "file"
166
180
  end
167
181
 
168
182
  def full_path
169
- URI.unescape(uri.path) if found? and uri
183
+ Puppet::Util.uri_to_path(uri) if found?
170
184
  end
171
185
 
172
186
  def server
@@ -176,12 +190,13 @@ module Puppet
176
190
  def port
177
191
  (uri and uri.port) or Puppet.settings[:masterport]
178
192
  end
179
-
180
193
  private
181
194
 
182
- def uri
183
- return nil if metadata.source =~ /^[a-z]:[\/\\]/i # Abspath for Windows
195
+ def scheme
196
+ (uri and uri.scheme)
197
+ end
184
198
 
199
+ def uri
185
200
  @uri ||= URI.parse(URI.escape(metadata.source))
186
201
  end
187
202
  end