puppet 0.9.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 (182) hide show
  1. data/CHANGELOG +0 -0
  2. data/COPYING +340 -0
  3. data/LICENSE +17 -0
  4. data/README +24 -0
  5. data/Rakefile +294 -0
  6. data/TODO +4 -0
  7. data/bin/cf2puppet +186 -0
  8. data/bin/puppet +176 -0
  9. data/bin/puppetca +213 -0
  10. data/bin/puppetd +246 -0
  11. data/bin/puppetdoc +184 -0
  12. data/bin/puppetmasterd +258 -0
  13. data/examples/code/allatonce +13 -0
  14. data/examples/code/assignments +11 -0
  15. data/examples/code/classing +35 -0
  16. data/examples/code/components +73 -0
  17. data/examples/code/execs +16 -0
  18. data/examples/code/failers/badclassnoparam +10 -0
  19. data/examples/code/failers/badclassparam +10 -0
  20. data/examples/code/failers/badcompnoparam +9 -0
  21. data/examples/code/failers/badcompparam +9 -0
  22. data/examples/code/failers/badtypeparam +3 -0
  23. data/examples/code/file.bl +11 -0
  24. data/examples/code/filedefaults +10 -0
  25. data/examples/code/fileparsing +116 -0
  26. data/examples/code/filerecursion +15 -0
  27. data/examples/code/functions +3 -0
  28. data/examples/code/groups +7 -0
  29. data/examples/code/head +30 -0
  30. data/examples/code/importing +8 -0
  31. data/examples/code/nodes +20 -0
  32. data/examples/code/one +8 -0
  33. data/examples/code/relationships +34 -0
  34. data/examples/code/selectors +28 -0
  35. data/examples/code/simpletests +11 -0
  36. data/examples/code/snippets/argumentdefaults +14 -0
  37. data/examples/code/snippets/casestatement +39 -0
  38. data/examples/code/snippets/classheirarchy.pp +15 -0
  39. data/examples/code/snippets/classincludes.pp +17 -0
  40. data/examples/code/snippets/classpathtest +11 -0
  41. data/examples/code/snippets/dirchmod +19 -0
  42. data/examples/code/snippets/failmissingexecpath.pp +13 -0
  43. data/examples/code/snippets/falsevalues.pp +3 -0
  44. data/examples/code/snippets/filecreate +11 -0
  45. data/examples/code/snippets/implicititeration +15 -0
  46. data/examples/code/snippets/multipleinstances +7 -0
  47. data/examples/code/snippets/namevartest +9 -0
  48. data/examples/code/snippets/scopetest +13 -0
  49. data/examples/code/snippets/selectorvalues.pp +22 -0
  50. data/examples/code/snippets/simpledefaults +5 -0
  51. data/examples/code/snippets/simpleselector +38 -0
  52. data/examples/code/svncommit +13 -0
  53. data/examples/root/bin/sleeper +69 -0
  54. data/examples/root/etc/configfile +0 -0
  55. data/examples/root/etc/debian-passwd +29 -0
  56. data/examples/root/etc/debian-syslog.conf +71 -0
  57. data/examples/root/etc/init.d/sleeper +65 -0
  58. data/examples/root/etc/otherfile +0 -0
  59. data/examples/root/etc/puppet/fileserver.conf +3 -0
  60. data/examples/root/etc/puppet/puppetmasterd.conf +10 -0
  61. data/ext/module:puppet +195 -0
  62. data/install.rb +270 -0
  63. data/lib/puppet.rb +249 -0
  64. data/lib/puppet/base64.rb +19 -0
  65. data/lib/puppet/client.rb +519 -0
  66. data/lib/puppet/config.rb +49 -0
  67. data/lib/puppet/daemon.rb +208 -0
  68. data/lib/puppet/element.rb +71 -0
  69. data/lib/puppet/event.rb +259 -0
  70. data/lib/puppet/log.rb +321 -0
  71. data/lib/puppet/metric.rb +250 -0
  72. data/lib/puppet/parsedfile.rb +38 -0
  73. data/lib/puppet/parser/ast.rb +1560 -0
  74. data/lib/puppet/parser/interpreter.rb +150 -0
  75. data/lib/puppet/parser/lexer.rb +226 -0
  76. data/lib/puppet/parser/parser.rb +1354 -0
  77. data/lib/puppet/parser/scope.rb +755 -0
  78. data/lib/puppet/server.rb +170 -0
  79. data/lib/puppet/server/authstore.rb +227 -0
  80. data/lib/puppet/server/ca.rb +140 -0
  81. data/lib/puppet/server/filebucket.rb +147 -0
  82. data/lib/puppet/server/fileserver.rb +477 -0
  83. data/lib/puppet/server/logger.rb +43 -0
  84. data/lib/puppet/server/master.rb +103 -0
  85. data/lib/puppet/server/servlet.rb +247 -0
  86. data/lib/puppet/sslcertificates.rb +737 -0
  87. data/lib/puppet/statechange.rb +150 -0
  88. data/lib/puppet/storage.rb +95 -0
  89. data/lib/puppet/transaction.rb +179 -0
  90. data/lib/puppet/transportable.rb +151 -0
  91. data/lib/puppet/type.rb +1354 -0
  92. data/lib/puppet/type/component.rb +141 -0
  93. data/lib/puppet/type/cron.rb +543 -0
  94. data/lib/puppet/type/exec.rb +316 -0
  95. data/lib/puppet/type/group.rb +152 -0
  96. data/lib/puppet/type/nameservice.rb +3 -0
  97. data/lib/puppet/type/nameservice/netinfo.rb +173 -0
  98. data/lib/puppet/type/nameservice/objectadd.rb +146 -0
  99. data/lib/puppet/type/nameservice/posix.rb +200 -0
  100. data/lib/puppet/type/package.rb +420 -0
  101. data/lib/puppet/type/package/apt.rb +70 -0
  102. data/lib/puppet/type/package/dpkg.rb +108 -0
  103. data/lib/puppet/type/package/rpm.rb +81 -0
  104. data/lib/puppet/type/package/sun.rb +117 -0
  105. data/lib/puppet/type/package/yum.rb +58 -0
  106. data/lib/puppet/type/pfile.rb +569 -0
  107. data/lib/puppet/type/pfile/checksum.rb +219 -0
  108. data/lib/puppet/type/pfile/create.rb +108 -0
  109. data/lib/puppet/type/pfile/group.rb +129 -0
  110. data/lib/puppet/type/pfile/mode.rb +131 -0
  111. data/lib/puppet/type/pfile/source.rb +264 -0
  112. data/lib/puppet/type/pfile/type.rb +31 -0
  113. data/lib/puppet/type/pfile/uid.rb +166 -0
  114. data/lib/puppet/type/pfilebucket.rb +80 -0
  115. data/lib/puppet/type/pprocess.rb +97 -0
  116. data/lib/puppet/type/service.rb +347 -0
  117. data/lib/puppet/type/service/base.rb +17 -0
  118. data/lib/puppet/type/service/debian.rb +50 -0
  119. data/lib/puppet/type/service/init.rb +145 -0
  120. data/lib/puppet/type/service/smf.rb +29 -0
  121. data/lib/puppet/type/state.rb +182 -0
  122. data/lib/puppet/type/symlink.rb +183 -0
  123. data/lib/puppet/type/tidy.rb +183 -0
  124. data/lib/puppet/type/typegen.rb +149 -0
  125. data/lib/puppet/type/typegen/filerecord.rb +243 -0
  126. data/lib/puppet/type/typegen/filetype.rb +316 -0
  127. data/lib/puppet/type/user.rb +290 -0
  128. data/lib/puppet/util.rb +138 -0
  129. data/test/certmgr/certmgr.rb +265 -0
  130. data/test/client/client.rb +203 -0
  131. data/test/executables/puppetbin.rb +53 -0
  132. data/test/executables/puppetca.rb +79 -0
  133. data/test/executables/puppetd.rb +71 -0
  134. data/test/executables/puppetmasterd.rb +153 -0
  135. data/test/executables/puppetmodule.rb +60 -0
  136. data/test/language/ast.rb +412 -0
  137. data/test/language/interpreter.rb +71 -0
  138. data/test/language/scope.rb +412 -0
  139. data/test/language/snippets.rb +445 -0
  140. data/test/other/events.rb +111 -0
  141. data/test/other/log.rb +195 -0
  142. data/test/other/metrics.rb +92 -0
  143. data/test/other/overrides.rb +115 -0
  144. data/test/other/parsedfile.rb +31 -0
  145. data/test/other/relationships.rb +113 -0
  146. data/test/other/state.rb +106 -0
  147. data/test/other/storage.rb +39 -0
  148. data/test/other/transactions.rb +235 -0
  149. data/test/parser/lexer.rb +120 -0
  150. data/test/parser/parser.rb +180 -0
  151. data/test/puppet/conffiles.rb +104 -0
  152. data/test/puppet/defaults.rb +100 -0
  153. data/test/puppet/error.rb +23 -0
  154. data/test/puppet/utiltest.rb +120 -0
  155. data/test/puppettest.rb +774 -0
  156. data/test/server/authstore.rb +209 -0
  157. data/test/server/bucket.rb +227 -0
  158. data/test/server/ca.rb +201 -0
  159. data/test/server/fileserver.rb +710 -0
  160. data/test/server/logger.rb +175 -0
  161. data/test/server/master.rb +150 -0
  162. data/test/server/server.rb +130 -0
  163. data/test/tagging/tagging.rb +80 -0
  164. data/test/test +51 -0
  165. data/test/types/basic.rb +119 -0
  166. data/test/types/component.rb +272 -0
  167. data/test/types/cron.rb +261 -0
  168. data/test/types/exec.rb +273 -0
  169. data/test/types/file.rb +616 -0
  170. data/test/types/filebucket.rb +167 -0
  171. data/test/types/fileignoresource.rb +287 -0
  172. data/test/types/filesources.rb +587 -0
  173. data/test/types/filetype.rb +162 -0
  174. data/test/types/group.rb +271 -0
  175. data/test/types/package.rb +205 -0
  176. data/test/types/query.rb +101 -0
  177. data/test/types/service.rb +100 -0
  178. data/test/types/symlink.rb +93 -0
  179. data/test/types/tidy.rb +124 -0
  180. data/test/types/type.rb +135 -0
  181. data/test/types/user.rb +371 -0
  182. metadata +243 -0
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/ruby -w
2
+
3
+ #--------------------
4
+ # accept and serve files
5
+ #
6
+ # $Id: filebucket.rb 635 2005-09-07 18:13:36Z luke $
7
+
8
+
9
+ require 'webrick'
10
+ #require 'webrick/https'
11
+ require 'xmlrpc/server'
12
+ require 'xmlrpc/client'
13
+ #require 'webrick/httpstatus'
14
+ require 'facter'
15
+ require 'digest/md5'
16
+ require 'puppet/base64'
17
+
18
+ module Puppet
19
+ class Server
20
+ class BucketError < RuntimeError; end
21
+ class FileBucket < Handler
22
+ @interface = XMLRPC::Service::Interface.new("puppetbucket") { |iface|
23
+ iface.add_method("string addfile(string, string)")
24
+ iface.add_method("string getfile(string)")
25
+ }
26
+
27
+ # this doesn't work for relative paths
28
+ def FileBucket.paths(base,md5)
29
+ return [
30
+ File.join(base, md5),
31
+ File.join(base, md5, "contents"),
32
+ File.join(base, md5, "paths")
33
+ ]
34
+ end
35
+
36
+ def initialize(hash)
37
+ # build our AST
38
+
39
+ if hash.include?(:ConflictCheck)
40
+ @conflictchk = hash[:ConflictCheck]
41
+ hash.delete(:ConflictCheck)
42
+ else
43
+ @conflictchk = true
44
+ end
45
+
46
+ if hash.include?(:Path)
47
+ @bucket = hash[:Path]
48
+ hash.delete(:Path)
49
+ else
50
+ if defined? Puppet
51
+ @bucket = Puppet[:bucketdir]
52
+ else
53
+ @bucket = File.expand_path("~/.filebucket")
54
+ end
55
+ end
56
+
57
+ Puppet.recmkdir(@bucket)
58
+ end
59
+
60
+ # accept a file from a client
61
+ def addfile(string,path, client = nil, clientip = nil)
62
+ #puts "entering addfile"
63
+ contents = Base64.decode64(string)
64
+ #puts "string is decoded"
65
+
66
+ md5 = Digest::MD5.hexdigest(contents)
67
+ #puts "md5 is made"
68
+
69
+ bpath, bfile, pathpath = FileBucket.paths(@bucket,md5)
70
+
71
+ # if it's a new directory...
72
+ if Puppet.recmkdir(bpath)
73
+ # ...then just create the file
74
+ #puts "creating file"
75
+ File.open(bfile, File::WRONLY|File::CREAT) { |of|
76
+ of.print contents
77
+ }
78
+ #puts "File is created"
79
+ else # if the dir already existed...
80
+ # ...we need to verify that the contents match the existing file
81
+ if @conflictchk
82
+ unless FileTest.exists?(bfile)
83
+ raise(BucketError,
84
+ "No file at %s for sum %s" % [bfile,md5], caller)
85
+ end
86
+
87
+ curfile = ""
88
+ File.open(bfile) { |of|
89
+ curfile = of.read
90
+ }
91
+
92
+ # if the contents don't match, then we've found a conflict
93
+ # unlikely, but quite bad
94
+ if curfile != contents
95
+ raise(BucketError,
96
+ "Got passed new contents for sum %s" % md5, caller)
97
+ end
98
+ end
99
+ #puts "Conflict check is done"
100
+ end
101
+
102
+ # in either case, add the passed path to the list of paths
103
+ paths = nil
104
+ addpath = false
105
+ if FileTest.exists?(pathpath)
106
+ File.open(pathpath) { |of|
107
+ paths = of.readlines
108
+ }
109
+
110
+ # unless our path is already there...
111
+ unless paths.include?(path)
112
+ addpath = true
113
+ end
114
+ else
115
+ addpath = true
116
+ end
117
+ #puts "Path is checked"
118
+
119
+ # if it's a new file, or if our path isn't in the file yet, add it
120
+ if addpath
121
+ File.open(pathpath, File::WRONLY|File::CREAT|File::APPEND) { |of|
122
+ of.puts path
123
+ }
124
+ #puts "Path is added"
125
+ end
126
+
127
+ return md5
128
+ end
129
+
130
+ def getfile(md5, client = nil, clientip = nil)
131
+ bpath, bfile, bpaths = FileBucket.paths(@bucket,md5)
132
+
133
+ unless FileTest.exists?(bfile)
134
+ return false
135
+ end
136
+
137
+ contents = nil
138
+ File.open(bfile) { |of|
139
+ contents = of.read
140
+ }
141
+
142
+ return Base64.encode64(contents)
143
+ end
144
+ #---------------------------------------------------------------
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,477 @@
1
+ require 'puppet'
2
+ require 'webrick/httpstatus'
3
+ require 'cgi'
4
+
5
+ module Puppet
6
+ class Server
7
+ class FileServerError < Puppet::Error; end
8
+ class FileServer < Handler
9
+ attr_accessor :local
10
+
11
+ Puppet.setdefault(:fileserverconfig, [:puppetconf, "fileserver.conf"])
12
+
13
+ #CHECKPARAMS = %w{checksum type mode owner group}
14
+ CHECKPARAMS = [:mode, :type, :owner, :group, :checksum]
15
+
16
+ @interface = XMLRPC::Service::Interface.new("fileserver") { |iface|
17
+ iface.add_method("string describe(string)")
18
+ iface.add_method("string list(string, boolean, array)")
19
+ iface.add_method("string retrieve(string)")
20
+ }
21
+
22
+ # Run 'retrieve' on a file. This gets the actual parameters, so
23
+ # we can pass them to the client.
24
+ def check(dir)
25
+ unless FileTest.exists?(dir)
26
+ Puppet.notice "File source %s does not exist" % dir
27
+ return nil
28
+ end
29
+
30
+ obj = nil
31
+ unless obj = Puppet::Type::PFile[dir]
32
+ obj = Puppet::Type::PFile.create(
33
+ :name => dir,
34
+ :check => CHECKPARAMS
35
+ )
36
+ end
37
+ # we should really have a timeout here -- we don't
38
+ # want to actually check on every connection, maybe no more
39
+ # than every 60 seconds or something
40
+ #@files[mount].evaluate
41
+ obj.evaluate
42
+
43
+ return obj
44
+ end
45
+
46
+ # Describe a given file. This returns all of the manageable aspects
47
+ # of that file.
48
+ def describe(file, client = nil, clientip = nil)
49
+ readconfig
50
+ mount, path = splitpath(file)
51
+
52
+ unless mount.allowed?(client, clientip)
53
+ raise Puppet::Server::AuthorizationError, "Cannot access %s" % mount
54
+ end
55
+
56
+ sdir = nil
57
+ unless sdir = subdir(mount, path)
58
+ mount.notice "Could not find subdirectory %s" %
59
+ "//%s/%s" % [mount, path]
60
+ return ""
61
+ end
62
+
63
+ obj = nil
64
+ unless obj = self.check(sdir)
65
+ return ""
66
+ end
67
+
68
+ desc = []
69
+ CHECKPARAMS.each { |check|
70
+ if state = obj.state(check)
71
+ unless state.is
72
+ mount.notice "Manually retrieving info for %s" % check
73
+ state.retrieve
74
+ end
75
+ desc << state.is
76
+ else
77
+ if check == "checksum" and obj.state(:type).is == "file"
78
+ mount.notice "File %s does not have data for %s" %
79
+ [obj.name, check]
80
+ end
81
+ desc << nil
82
+ end
83
+ }
84
+
85
+ return desc.join("\t")
86
+ end
87
+
88
+ # Deal with ignore parameters.
89
+ def handleignore(children, path, ignore)
90
+ ignore.each { |ignore|
91
+ Dir.glob(File.join(path,ignore), File::FNM_DOTMATCH) { |match|
92
+ children.delete(File.basename(match))
93
+ }
94
+ }
95
+ return children
96
+ end
97
+
98
+ # Create a new fileserving module.
99
+ def initialize(hash = {})
100
+ @mounts = {}
101
+ @files = {}
102
+
103
+ if hash[:Local]
104
+ @local = hash[:Local]
105
+ else
106
+ @local = false
107
+ end
108
+
109
+ if hash[:Config] == false
110
+ @noreadconfig = true
111
+ else
112
+ @config = hash[:Config] || Puppet[:fileserverconfig]
113
+ @noreadconfig = false
114
+ end
115
+
116
+ @configtimeout = hash[:ConfigTimeout] || 60
117
+ @configstamp = nil
118
+ @congigstatted = nil
119
+
120
+ if hash.include?(:Mount)
121
+ @passedconfig = true
122
+ unless hash[:Mount].is_a?(Hash)
123
+ raise Puppet::DevError, "Invalid mount hash %s" %
124
+ hash[:Mount].inspect
125
+ end
126
+
127
+ hash[:Mount].each { |dir, name|
128
+ if FileTest.exists?(dir)
129
+ self.mount(dir, name)
130
+ end
131
+ }
132
+ else
133
+ @passedconfig = false
134
+ readconfig
135
+ end
136
+ end
137
+
138
+ # List a specific directory's contents.
139
+ def list(dir, recurse = false, ignore = false, client = nil, clientip = nil)
140
+ readconfig
141
+ mount, path = splitpath(dir)
142
+
143
+ unless mount.allowed?(client, clientip)
144
+ raise Puppet::Server::AuthorizationError, "Cannot access %s" % mount
145
+ end
146
+
147
+ subdir = nil
148
+ unless subdir = subdir(mount, path)
149
+ mount.notice "Could not find subdirectory %s" %
150
+ "%s:%s" % [mount, path]
151
+ return ""
152
+ end
153
+
154
+ obj = nil
155
+ unless FileTest.exists?(subdir)
156
+ return ""
157
+ end
158
+
159
+ rmdir = expand_mount(dir, mount)
160
+ desc = reclist(mount, rmdir, subdir, recurse, ignore)
161
+
162
+ if desc.length == 0
163
+ mount.notice "Got no information on //%s/%s" %
164
+ [mount, path]
165
+ return ""
166
+ end
167
+
168
+ desc.collect { |sub|
169
+ sub.join("\t")
170
+ }.join("\n")
171
+ end
172
+
173
+ # Mount a new directory with a name.
174
+ def mount(path, name)
175
+ if @mounts.include?(name)
176
+ if @mounts[name] != path
177
+ raise FileServerError, "%s is already mounted at %s" %
178
+ [@mounts[name].path, name]
179
+ else
180
+ # it's already mounted; no problem
181
+ return
182
+ end
183
+ end
184
+
185
+ if FileTest.directory?(path)
186
+ if FileTest.readable?(path)
187
+ @mounts[name] = Mount.new(name, path)
188
+ @mounts[name].info "Mounted"
189
+ else
190
+ raise FileServerError, "%s is not readable" % path
191
+ end
192
+ else
193
+ raise FileServerError, "%s is not a directory" % path
194
+ end
195
+ end
196
+
197
+ # Read the configuration file.
198
+ def readconfig
199
+ return if @noreadconfig
200
+
201
+ if @configstamp and FileTest.exists?(@config)
202
+ if @configtimeout and @configstatted
203
+ if Time.now - @configstatted > @configtimeout
204
+ @configstatted = Time.now
205
+ tmp = File.stat(@config).ctime
206
+
207
+ if tmp == @configstamp
208
+ return
209
+ end
210
+ else
211
+ return
212
+ end
213
+ end
214
+ end
215
+
216
+ newmounts = {}
217
+ begin
218
+ File.open(@config) { |f|
219
+ mount = nil
220
+ count = 1
221
+ f.each { |line|
222
+ case line
223
+ when /^\s*#/: next # skip comments
224
+ when /^\s*$/: next # skip blank lines
225
+ when /\[(\w+)\]/:
226
+ name = $1
227
+ if newmounts.include?(name)
228
+ raise FileServerError, "%s is already mounted at %s" %
229
+ [newmounts[name], name]
230
+ end
231
+ mount = Mount.new(name)
232
+ newmounts[name] = mount
233
+ when /^\s*(\w+)\s+(.+)$/:
234
+ var = $1
235
+ value = $2
236
+ case var
237
+ when "path":
238
+ begin
239
+ mount.path = value
240
+ rescue FileServerError => detail
241
+ Puppet.err "Removing mount %s: %s" %
242
+ [mount.name, detail]
243
+ newmounts.delete(mount.name)
244
+ end
245
+ when "allow":
246
+ value.split(/\s*,\s*/).each { |val|
247
+ begin
248
+ mount.info "Allowing %s access" % val
249
+ mount.allow(val)
250
+ rescue AuthStoreError => detail
251
+ raise FileServerError, "%s at line %s of %s" %
252
+ [detail.to_s, count, @config]
253
+ end
254
+ }
255
+ when "deny":
256
+ value.split(/\s*,\s*/).each { |val|
257
+ begin
258
+ mount.info "Denying %s access" % val
259
+ mount.deny(val)
260
+ rescue AuthStoreError => detail
261
+ raise FileServerError, "%s at line %s of %s" %
262
+ [detail.to_s, count, @config]
263
+ end
264
+ }
265
+ else
266
+ raise FileServerError,
267
+ "Invalid argument '%s' at line %s" % [var, count]
268
+ end
269
+ else
270
+ raise FileServerError, "Invalid line %s: %s" % [count, line]
271
+ end
272
+ count += 1
273
+ }
274
+ }
275
+ rescue Errno::EACCES => detail
276
+ Puppet.err "FileServer error: Cannot read %s; cannot serve" % @config
277
+ #raise Puppet::Error, "Cannot read %s" % @config
278
+ rescue Errno::ENOENT => detail
279
+ Puppet.err "FileServer error: '%s' does not exit; cannot serve" %
280
+ @config
281
+ #raise Puppet::Error, "%s does not exit" % @config
282
+ #rescue FileServerError => detail
283
+ # Puppet.err "FileServer error: %s" % detail
284
+ end
285
+
286
+ # Verify each of the mounts are valid.
287
+ # We let the check raise an error, so that it can raise an error
288
+ # pointing to the specific problem.
289
+ newmounts.each { |name, mount|
290
+ mount.valid?
291
+ }
292
+ @mounts = newmounts
293
+
294
+ @configstamp = File.stat(@config).ctime
295
+ @configstatted = Time.now
296
+ end
297
+
298
+ # Retrieve a file from the local disk and pass it to the remote
299
+ # client.
300
+ def retrieve(file, client = nil, clientip = nil)
301
+ readconfig
302
+ mount, path = splitpath(file)
303
+
304
+ unless mount.allowed?(client, clientip)
305
+ raise Puppet::Server::AuthorizationError, "Cannot access %s" % mount
306
+ end
307
+
308
+ fpath = nil
309
+ if path
310
+ fpath = File.join(mount.path, path)
311
+ else
312
+ fpath = mount.path
313
+ end
314
+
315
+ unless FileTest.exists?(fpath)
316
+ return ""
317
+ end
318
+
319
+ str = File.read(fpath)
320
+
321
+ if @local
322
+ return str
323
+ else
324
+ return CGI.escape(str)
325
+ end
326
+ end
327
+
328
+ private
329
+
330
+ # Convert from the '/mount/path' form to the real path on disk.
331
+ def expand_mount(name, mount)
332
+ # Note that the user could have passed a path with multiple /'s
333
+ # in it, and we are likely to result in multiples, so we have to
334
+ # get rid of all of them.
335
+ name.sub(/\/#{mount.name}/, mount.path).gsub(%r{/+}, '/').sub(
336
+ %r{/$}, ''
337
+ )
338
+ end
339
+
340
+ # Recursively list the directory.
341
+ def reclist(mount, root, path, recurse, ignore)
342
+ # Take out the root of the path.
343
+ name = path.sub(root, '')
344
+ if name == ""
345
+ name = "/"
346
+ end
347
+
348
+ if name == path
349
+ raise FileServerError, "Could not match %s in %s" %
350
+ [root, path]
351
+ end
352
+
353
+ desc = [name]
354
+ ftype = File.stat(path).ftype
355
+
356
+ desc << ftype
357
+ if recurse.is_a?(Integer)
358
+ recurse -= 1
359
+ end
360
+
361
+ ary = [desc]
362
+ if recurse == true or (recurse.is_a?(Integer) and recurse > -1)
363
+ if ftype == "directory"
364
+ children = Dir.entries(path)
365
+ if ignore
366
+ children = handleignore(children, path, ignore)
367
+ end
368
+ children.each { |child|
369
+ next if child =~ /^\.\.?$/
370
+ reclist(mount, root, File.join(path, child), recurse, ignore).each { |cobj|
371
+ ary << cobj
372
+ }
373
+ }
374
+ end
375
+ end
376
+
377
+ return ary.reject { |c| c.nil? }
378
+ end
379
+
380
+ # Split the path into the separate mount point and path.
381
+ def splitpath(dir)
382
+ # the dir is based on one of the mounts
383
+ # so first retrieve the mount path
384
+ mount = nil
385
+ path = nil
386
+ if dir =~ %r{/(\w+)/?}
387
+ mount = $1
388
+ path = dir.sub(%r{/#{mount}/?}, '')
389
+
390
+ unless @mounts.include?(mount)
391
+ raise FileServerError, "Fileserver module '%s' not mounted" % mount
392
+ end
393
+
394
+ unless @mounts[mount].path
395
+ raise FileServerError,
396
+ "Fileserver error: Mount '%s' does not have a path set" % mount
397
+ end
398
+
399
+ # And now replace the name with the actual object.
400
+ mount = @mounts[mount]
401
+ else
402
+ raise FileServerError, "Fileserver error: Invalid path '%s'" % dir
403
+ end
404
+
405
+ if path == ""
406
+ path = nil
407
+ end
408
+ return mount, path
409
+ end
410
+
411
+ # Retrieve a specific directory relative to a mount point.
412
+ def subdir(mount, dir)
413
+ basedir = mount.path
414
+
415
+ dirname = nil
416
+ if dir
417
+ dirname = File.join(basedir, dir.split("/").join(File::SEPARATOR))
418
+ else
419
+ dirname = basedir
420
+ end
421
+
422
+ dirname
423
+ end
424
+
425
+ # A simple class for wrapping mount points. Instances of this class
426
+ # don't know about the enclosing object; they're mainly just used for
427
+ # authorization.
428
+ class Mount < AuthStore
429
+ attr_reader :path, :name
430
+
431
+ Puppet::Util.logmethods(self, true)
432
+
433
+ # Create out orbject. It must have a name.
434
+ def initialize(name, path = nil)
435
+ unless name =~ %r{^\w+$}
436
+ raise FileServerError, "Invalid name format '%s'" % name
437
+ end
438
+ @name = name
439
+
440
+ if path
441
+ self.path = path
442
+ else
443
+ @path = nil
444
+ end
445
+
446
+ super()
447
+ end
448
+
449
+ # Set the path.
450
+ def path=(path)
451
+ unless FileTest.exists?(path)
452
+ raise FileServerError, "%s does not exist" % path
453
+ end
454
+ @path = path
455
+ end
456
+
457
+ def to_s
458
+ if @path
459
+ @name + ":" + @path
460
+ else
461
+ @name
462
+ end
463
+ end
464
+
465
+ # Verify our configuration is valid. This should really check to
466
+ # make sure at least someone will be allowed, but, eh.
467
+ def valid?
468
+ unless @path
469
+ raise FileServerError, "No path specified"
470
+ end
471
+ end
472
+ end
473
+ end
474
+ end
475
+ end
476
+
477
+ # $Id: fileserver.rb 742 2005-11-16 17:12:11Z luke $