3
$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/
6
require 'puppet/server/fileserver'
9
class TestFileServer < Test::Unit::TestCase
12
def mkmount(path = nil)
15
base = path || tempfile()
16
unless FileTest.exists?(base)
20
File.open(File.join(base, "file"), "w") { |f| f.puts "bazoo" }
21
assert_nothing_raised {
22
mount = Puppet::Server::FileServer::Mount.new(name, base)
27
# make a simple file source
29
testdir = File.join(tmpdir(), "remotefilecopytesting")
34
tmpfile = File.join(testdir, pattern)
35
assert_nothing_raised {
37
File.open(tmpfile, "w") { |f|
38
3.times { f.puts rand(100) }
42
return [testdir, %r{#{pattern}}, tmpfile]
45
# make a bunch of random test files
46
def mktestfiles(testdir)
48
assert_nothing_raised {
49
files = %w{a b c d e}.collect { |l|
50
name = File.join(testdir, "file%s" % l)
51
File.open(name, "w") { |f|
62
def assert_describe(base, file, server)
63
file = File.basename(file)
64
assert_nothing_raised {
65
desc = server.describe(base + file)
66
assert(desc, "Got no description for %s" % file)
67
assert(desc != "", "Got no description for %s" % file)
68
assert_match(/^\d+/, desc, "Got invalid description %s" % desc)
72
# test for invalid names
75
assert_nothing_raised {
76
server = Puppet::Server::FileServer.new(
82
assert_raise(Puppet::FileServerError) {
83
server.mount("/tmp", "invalid+name")
86
assert_raise(Puppet::FileServerError) {
87
server.mount("/tmp", "invalid-name")
90
assert_raise(Puppet::FileServerError) {
91
server.mount("/tmp", "invalid name")
94
assert_raise(Puppet::FileServerError) {
95
server.mount("/tmp", "")
99
# verify that listing the root behaves as expected
102
testdir, pattern, tmpfile = mktestdir()
105
checks = Puppet::Server::FileServer::CHECKPARAMS
107
# and make our fileserver
108
assert_nothing_raised {
109
server = Puppet::Server::FileServer.new(
116
assert_nothing_raised {
117
server.mount(testdir, "test")
120
# and verify different iterations of 'root' return the same value
122
assert_nothing_raised {
123
list = server.list("/test/", :ignore, true, false)
126
assert(list =~ pattern)
128
assert_nothing_raised {
129
list = server.list("/test", :ignore, true, false)
131
assert(list =~ pattern)
135
# test listing individual files
138
testdir, pattern, tmpfile = mktestdir()
142
assert_nothing_raised {
143
server = Puppet::Server::FileServer.new(
149
assert_nothing_raised {
150
server.mount(testdir, "test")
155
sfile = "/test/tmpfile"
156
assert_nothing_raised {
157
list = server.list(sfile, :ignore, true, false)
160
assert_nothing_raised {
161
file = Puppet.type(:file)[tmpfile]
166
# verify it got listed as a file
167
assert_equal(output, list)
169
# verify we got all fields
170
assert(list !~ /\t\t/)
172
# verify that we didn't get the directory itself
173
list.split("\n").each { |line|
174
assert(line !~ %r{remotefile})
177
# and then verify that the contents match
178
contents = File.read(tmpfile)
181
assert_nothing_raised {
182
ret = server.retrieve(sfile)
185
assert_equal(contents, ret)
188
# check that the fileserver is seeing newly created files
191
testdir, pattern, tmpfile = mktestdir()
194
newfile = File.join(testdir, "newfile")
196
# go through the whole schtick again...
198
checks = Puppet::Server::FileServer::CHECKPARAMS
200
assert_nothing_raised {
201
server = Puppet::Server::FileServer.new(
207
assert_nothing_raised {
208
server.mount(testdir, "test")
213
assert_nothing_raised {
214
list = server.list(sfile, :ignore, true, false)
217
# create the new file
218
File.open(newfile, "w") { |f|
219
3.times { f.puts rand(100) }
223
assert_nothing_raised {
224
newlist = server.list(sfile, :ignore, true, false)
227
# verify the list has changed
228
assert(list != newlist)
230
# and verify that we are specifically seeing the new file
231
assert(newlist =~ /newfile/)
234
# verify we can mount /, which is what local file servers will
238
assert_nothing_raised {
239
server = Puppet::Server::FileServer.new(
245
assert_nothing_raised {
246
server.mount("/", "root")
249
testdir, pattern, tmpfile = mktestdir()
252
assert_nothing_raised {
253
list = server.list("/root/" + testdir, :ignore, true, false)
256
assert(list =~ pattern)
257
assert_nothing_raised {
258
list = server.list("/root" + testdir, :ignore, true, false)
261
assert(list =~ pattern)
264
# verify that we're correctly recursing the right number of levels
265
def test_recursionlevels
267
assert_nothing_raised {
268
server = Puppet::Server::FileServer.new(
274
# make our deep recursion
275
basedir = File.join(tmpdir(), "recurseremotetesting")
276
testdir = "%s/with/some/sub/directories/for/the/purposes/of/testing" % basedir
277
oldfile = File.join(testdir, "oldfile")
278
assert_nothing_raised {
279
system("mkdir -p %s" % testdir)
280
File.open(oldfile, "w") { |f|
281
3.times { f.puts rand(100) }
283
@@tmpfiles << basedir
286
assert_nothing_raised {
287
server.mount(basedir, "test")
292
assert_nothing_raised {
293
list = server.list("/test/with", :ignore, false, false)
296
# make sure we only got one line, since we're not recursing
299
# for each level of recursion, make sure we get the right list
300
[0, 1, 2].each { |num|
301
assert_nothing_raised {
302
list = server.list("/test/with", :ignore, num, false)
310
assert_equal(num, count)
314
# verify that we're not seeing the dir we ask for; i.e., that our
315
# list is relative to that dir, not it's parent dir
318
assert_nothing_raised {
319
server = Puppet::Server::FileServer.new(
328
testdir = "%s/with/some/sub/directories/for/testing" % basedir
329
oldfile = File.join(testdir, "oldfile")
330
assert_nothing_raised {
331
system("mkdir -p %s" % testdir)
332
File.open(oldfile, "w") { |f|
333
3.times { f.puts rand(100) }
335
@@tmpfiles << basedir
339
assert_nothing_raised {
340
server.mount(basedir, "localhost")
344
# and then check a few dirs
345
assert_nothing_raised {
346
list = server.list("/localhost/with", :ignore, false, false)
349
assert(list !~ /with/)
351
assert_nothing_raised {
352
list = server.list("/localhost/with/some/sub", :ignore, true, false)
355
assert(list !~ /sub/)
358
# test many dirs, not necessarily very deep
361
assert_nothing_raised {
362
server = Puppet::Server::FileServer.new(
369
dirs = %w{a set of directories}
370
assert_nothing_raised {
373
Dir.mkdir(File.join(basedir, dir))
375
@@tmpfiles << basedir
378
assert_nothing_raised {
379
server.mount(basedir, "localhost")
383
assert_nothing_raised {
384
list = server.list("/localhost/", :ignore, 1, false)
386
assert_instance_of(String, list, "Server returned %s instead of string")
387
list = list.split("\n")
389
assert_equal(dirs.length + 1, list.length)
392
# verify that 'describe' works as advertised
396
files = mktestfiles(testdir)
399
checks = Puppet::Server::FileServer::CHECKPARAMS
401
assert_nothing_raised {
402
server = Puppet::Server::FileServer.new(
408
assert_nothing_raised {
409
server.mount(testdir, "test")
415
assert_nothing_raised {
416
list = server.list(sfile, :ignore, true, false)
419
# and describe each file in the list
420
assert_nothing_raised {
421
list.split("\n").each { |line|
422
file, type = line.split("\t")
424
desc = server.describe(sfile + file)
428
# and then make sure we can describe everything that we know is there
430
assert_describe(sfile, file, server)
433
# And then describe some files that we know aren't there
435
assert_nothing_raised("Describing non-existent files raised an error") {
436
retval = server.describe(sfile + "noexisties")
439
assert_equal("", retval, "Description of non-existent files returned a value")
441
# Now try to describe some sources that don't even exist
443
assert_raise(Puppet::FileServerError,
444
"Describing non-existent mount did not raise an error") {
445
retval = server.describe("/notmounted/" + "noexisties")
448
assert_nil(retval, "Description of non-existent mounts returned a value")
451
# test that our config file is parsing and working as planned
454
basedir = File.join(tmpdir, "fileserverconfigfiletesting")
455
@@tmpfiles << basedir
457
# make some dirs for mounting
460
%w{thing thus these those}.each { |dir|
461
path = File.join(basedir, dir)
463
mounts[dir] = mktestfiles(path)
467
# create an example file with each of them
469
@@tmpfiles << conffile
471
File.open(conffile, "w") { |f|
472
f.print "# a test config file
475
path #{basedir}/thing
480
allow *.madstop.com, *.kanies.com
481
deny *.sub.madstop.com
484
path #{basedir}/these
487
path #{basedir}/those
493
# create a server with the file
494
assert_nothing_raised {
495
server = Puppet::Server::FileServer.new(
502
# run through once with no host/ip info, to verify everything is working
503
mounts.each { |mount, files|
505
assert_nothing_raised {
506
list = server.list(mount, :ignore, true, false)
509
assert_nothing_raised {
510
list.split("\n").each { |line|
511
file, type = line.split("\t")
513
desc = server.describe(mount + file)
518
assert_describe(mount, f, server)
522
# now let's check that things are being correctly forbidden
523
# this is just a map of names and expected results
527
["hostname.com", "192.168.1.0"],
528
["hostname.com", "192.158.0.0"]
531
["hostname.com", "192.168.0.0"],
532
["hostname.com", "192.168.0.245"],
537
["hostname.com", "192.168.1.0"],
538
["name.sub.madstop.com", "192.158.0.0"]
541
["luke.kanies.com", "192.168.0.0"],
542
["luke.madstop.com", "192.168.0.245"],
545
}.each { |mount, hash|
548
# run through the map
549
hash.each { |type, ary|
555
assert_raise(Puppet::Server::AuthorizationError,
556
"Host %s, ip %s, allowed %s" %
558
list = server.list(mount, :ignore, true, false, host, ip)
561
assert_nothing_raised("Host %s, ip %s, denied %s" %
563
list = server.list(mount, :ignore, true, false, host, ip)
572
# Test that we smoothly handle invalid config files
573
def test_configfailures
574
# create an example file with each of them
575
conffile = tempfile()
578
"noexist" => "[noexist]
579
path /this/path/does/not/exist
586
path /this/path/does/not/exist
599
invalidmounts.each { |mount, text|
600
File.open(conffile, "w") { |f|
605
# create a server with the file
607
assert_nothing_raised {
608
server = Puppet::Server::FileServer.new(
614
assert_raise(Puppet::FileServerError,
615
"Invalid mount was mounted") {
616
server.list(mount, :ignore)
620
invalidconfigs.each_with_index { |text, i|
621
File.open(conffile, "w") { |f|
626
# create a server with the file
628
assert_raise(Puppet::FileServerError,
629
"Invalid config %s did not raise error" % i) {
630
server = Puppet::Server::FileServer.new(
638
# verify we reread the config file when it changes
642
conffile = tempfile()
645
files = mktestfiles(dir)
646
File.open(conffile, "w") { |f|
647
f.print "# a test config file
651
allow test1.domain.com
655
# Reset the timeout, so we reload faster
656
Puppet[:filetimeout] = 0.5
658
# start our server with a fast timeout
659
assert_nothing_raised {
660
server = Puppet::Server::FileServer.new(
667
assert_nothing_raised {
668
list = server.list("/thing/", :ignore, false, false,
669
"test1.domain.com", "127.0.0.1")
671
assert(list != "", "List returned nothing in rereard test")
673
assert_raise(Puppet::Server::AuthorizationError, "List allowed invalid host") {
674
list = server.list("/thing/", :ignore, false, false,
675
"test2.domain.com", "127.0.0.1")
679
File.open(conffile, "w") { |f|
680
f.print "# a test config file
684
allow test2.domain.com
688
assert_raise(Puppet::Server::AuthorizationError, "List allowed invalid host") {
689
list = server.list("/thing/", :ignore, false, false,
690
"test1.domain.com", "127.0.0.1")
693
assert_nothing_raised {
694
list = server.list("/thing/", :ignore, false, false,
695
"test2.domain.com", "127.0.0.1")
698
assert(list != "", "List returned nothing in rereard test")
703
# Verify that we get converted to the right kind of string
708
assert_nothing_raised {
709
mount = Puppet::Server::FileServer::Mount.new(name, path)
712
assert_equal("mount[#{name}]", mount.to_s)
715
def test_servinglinks
718
file = File.join(source, "file")
719
link = File.join(source, "link")
721
File.open(file, "w") { |f| f.puts "yay" }
722
File.symlink(file, link)
723
assert_nothing_raised {
724
server = Puppet::Server::FileServer.new(
730
assert_nothing_raised {
731
server.mount(source, "mount")
734
# First describe the link when following
736
assert_nothing_raised {
737
server.describe("/mount/link", :follow).split("\t").zip(
738
Puppet::Server::FileServer::CHECKPARAMS
739
).each { |v,p| results[p] = v }
742
assert_equal("file", results[:type])
746
assert_nothing_raised {
747
server.describe("/mount/link", :ignore).split("\t").zip(
748
Puppet::Server::FileServer::CHECKPARAMS
749
).each { |v,p| results[p] = v }
752
assert_equal("link", results[:type])
755
assert(v, "%s has no value" % p)
756
assert(v != "", "%s has no value" % p)
760
# Test that substitution patterns in the path are exapanded
761
# properly. Disabled, because it was testing too much of the process
762
# and in a non-portable way. This is a thorough enough test that it should
763
# be kept, but it should be done in a way that is clearly portable (e.g.,
764
# no md5 sums of file paths).
765
def test_host_specific
766
client1 = "client1.example.com"
767
client2 = "client2.example.com"
770
# Setup a directory hierarchy for the tests
771
fsdir = File.join(tmpdir(), "host-specific")
773
hostdir = File.join(fsdir, "host")
774
fqdndir = File.join(fsdir, "fqdn")
775
client1_hostdir = File.join(hostdir, "client1")
776
client2_fqdndir = File.join(fqdndir, client2)
778
client1_hostdir => "client1\n",
779
client2_fqdndir => client2 + "\n"
781
[fsdir, hostdir, fqdndir,
782
client1_hostdir, client2_fqdndir].each { |d| Dir.mkdir(d) }
784
[client1_hostdir, client2_fqdndir].each do |d|
785
File.open(File.join(d, "file.txt"), "w") do |f|
789
conffile = tempfile()
790
File.open(conffile, "w") do |f|
802
assert_nothing_raised {
803
server = Puppet::Server::FileServer.new(
809
# check that list returns the correct thing for the two clients
811
sfile = "/host/file.txt"
812
assert_nothing_raised {
813
list = server.list(sfile, :ignore, true, false, client1, ip)
815
assert_equal("/\tfile", list)
816
assert_nothing_raised {
817
list = server.list(sfile, :ignore, true, false, client2, ip)
819
assert_equal("", list)
821
sfile = "/fqdn/file.txt"
822
assert_nothing_raised {
823
list = server.list(sfile, :ignore, true, false, client1, ip)
825
assert_equal("", list)
826
assert_nothing_raised {
827
list = server.list(sfile, :ignore, true, false, client2, ip)
829
assert_equal("/\tfile", list)
832
sfile = "/host/file.txt"
833
assert_nothing_raised {
834
list = server.describe(sfile, :ignore, client1, ip).split("\t")
836
assert_equal(5, list.size)
837
assert_equal("file", list[1])
838
md5 = Digest::MD5.hexdigest(contents[client1_hostdir])
839
assert_equal("{md5}#{md5}", list[4])
841
assert_nothing_raised {
842
list = server.describe(sfile, :ignore, client2, ip).split("\t")
844
assert_equal([], list)
846
sfile = "/fqdn/file.txt"
847
assert_nothing_raised {
848
list = server.describe(sfile, :ignore, client1, ip).split("\t")
850
assert_equal([], list)
852
assert_nothing_raised {
853
list = server.describe(sfile, :ignore, client2, ip).split("\t")
855
assert_equal(5, list.size)
856
assert_equal("file", list[1])
857
md5 = Digest::MD5.hexdigest(contents[client2_fqdndir])
858
assert_equal("{md5}#{md5}", list[4])
861
sfile = "/host/file.txt"
862
assert_nothing_raised {
863
list = server.retrieve(sfile, :ignore, client1, ip).chomp
865
assert_equal(contents[client1_hostdir].chomp, list)
867
assert_nothing_raised {
868
list = server.retrieve(sfile, :ignore, client2, ip).chomp
870
assert_equal("", list)
872
sfile = "/fqdn/file.txt"
873
assert_nothing_raised {
874
list = server.retrieve(sfile, :ignore, client1, ip).chomp
876
assert_equal("", list)
878
assert_nothing_raised {
879
list = server.retrieve(sfile, :ignore, client2, ip).chomp
881
assert_equal(contents[client2_fqdndir].chomp, list)
884
# Make sure the 'subdir' method in Mount works.
885
def test_mount_subdir
889
subdir = File.join(base, "subdir")
891
[base, subdir].each do |d|
892
File.open(File.join(d, "file"), "w") { |f| f.puts "bazoo" }
894
mount = mkmount(base)
896
assert_equal(base, mount.subdir(), "Did not default to base path")
897
assert_equal(subdir, mount.subdir("subdir"), "Did not default to base path")
900
# Make sure mounts get correctly marked expandable or not, depending on
908
assert_nothing_raised {
912
assert(! mount.expandable?, "Mount incorrectly called expandable")
914
assert_nothing_raised {
915
mount.path = "/dir/a%a"
917
assert(mount.expandable?, "Mount not called expandable")
919
# This isn't a valid replacement pattern, so it should throw an error
920
# because the dir doesn't exist
921
assert_raise(Puppet::FileServerError) {
922
mount.path = "/dir/a%"
925
# Now send it back to a normal path
926
assert_nothing_raised {
929
# Make sure it got reverted
930
assert(! mount.expandable?, "Mount incorrectly called expandable")
935
def test_mount_expand
938
check = proc do |client, pattern, repl|
939
path = "/my/#{pattern}/file"
940
assert_equal("/my/#{repl}/file", mount.expand(path, client))
943
# Do a round of checks with a fake client
944
client = "host.domain.com"
945
{"%h" => "host", # Short name
946
"%H" => client, # Full name
947
"%d" => "domain.com", # domain
948
"%%" => "%", # escape
950
}.each do |pat, repl|
951
result = check.call(client, pat, repl)
954
# Now, check that they use Facter info
955
Puppet.notice "The following messages are normal"
957
local = Facter["hostname"].value
958
domain = Facter["domain"].value
959
fqdn = [local, domain].join(".")
960
{"%h" => local, # Short name
961
"%H" => fqdn, # Full name
962
"%d" => domain, # domain
963
"%%" => "%", # escape
965
}.each do |pat, repl|
966
check.call(client, pat, repl)
971
def test_fileserver_expansion
973
assert_nothing_raised {
974
server = Puppet::Server::FileServer.new(
981
ip = Facter.value(:ipaddress)
984
host = "host.domain.com"
986
"%H" => "host.domain.com", "%h" => "host", "%d" => "domain.com"
987
}.each do |pattern, string|
988
file = File.join(dir, string)
989
mount = File.join(dir, pattern)
990
File.open(file, "w") do |f| f.puts "yayness: %s" % string end
993
assert_nothing_raised {
994
obj = server.mount(mount, name)
999
assert_nothing_raised do
1000
ret = server.list("/name", :ignore, false, false, host, ip)
1003
assert_equal("/\tfile", ret)
1005
assert_nothing_raised do
1006
ret = server.describe("/name", :ignore, host, ip)
1008
assert(ret =~ /\tfile\t/, "Did not get valid a description")
1010
assert_nothing_raised do
1011
ret = server.retrieve("/name", :ignore, host, ip)
1014
assert_equal(ret, File.read(file))
1023
# $Id: fileserver.rb 1793 2006-10-16 22:01:40Z luke $