diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-02-08 02:22:57 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2007-02-08 02:22:57 +0000 |
| commit | a216df2bcb304ad379e152f2f59ef7d942f54f3b (patch) | |
| tree | eef3289c588cf44373fe959619d732c5a05ab7b5 /test/network/server | |
| parent | 7e07e3dc843798bdbc7a03428ca054adaff2fb72 (diff) | |
| download | puppet-a216df2bcb304ad379e152f2f59ef7d942f54f3b.tar.gz puppet-a216df2bcb304ad379e152f2f59ef7d942f54f3b.tar.xz puppet-a216df2bcb304ad379e152f2f59ef7d942f54f3b.zip | |
Okay, last file moves for the night. The test code has been moved to match the lib directory, and I have moved a couple of things into network/ instead of network/server, since they did not belong as much.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2180 980ebf18-57e1-0310-9a29-db15c13687c0
Diffstat (limited to 'test/network/server')
| -rwxr-xr-x | test/network/server/authconfig.rb | 53 | ||||
| -rwxr-xr-x | test/network/server/authstore.rb | 211 | ||||
| -rwxr-xr-x | test/network/server/bucket.rb | 259 | ||||
| -rwxr-xr-x | test/network/server/ca.rb | 233 | ||||
| -rwxr-xr-x | test/network/server/fileserver.rb | 1024 | ||||
| -rwxr-xr-x | test/network/server/logger.rb | 179 | ||||
| -rwxr-xr-x | test/network/server/master.rb | 346 | ||||
| -rwxr-xr-x | test/network/server/report.rb | 185 | ||||
| -rwxr-xr-x | test/network/server/resource.rb | 296 | ||||
| -rwxr-xr-x | test/network/server/rights.rb | 37 | ||||
| -rwxr-xr-x | test/network/server/runner.rb | 106 | ||||
| -rwxr-xr-x | test/network/server/server.rb | 197 |
12 files changed, 3126 insertions, 0 deletions
diff --git a/test/network/server/authconfig.rb b/test/network/server/authconfig.rb new file mode 100755 index 000000000..c48282973 --- /dev/null +++ b/test/network/server/authconfig.rb @@ -0,0 +1,53 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' + +require 'puppet/network/authconfig' + +class TestAuthConfig < Test::Unit::TestCase + include PuppetTest + + def test_parsingconfigfile + file = tempfile() + assert(Puppet[:authconfig], "No config path") + + Puppet[:authconfig] = file + + File.open(file, "w") { |f| + f.puts "[pelementserver.describe] + allow *.madstop.com + deny 10.10.1.1 + +[fileserver] + allow *.madstop.com + deny 10.10.1.1 + +[fileserver.list] + allow 10.10.1.1 +" + } + + config = nil + assert_nothing_raised { + config = Puppet::Network::AuthConfig.new(file) + } + + assert_nothing_raised { + assert(config.allowed?("pelementserver.describe", + "culain.madstop.com", "1.1.1.1"), "Did not allow host") + assert(! config.allowed?("pelementserver.describe", + "culain.madstop.com", "10.10.1.1"), "Allowed host") + assert(config.allowed?("fileserver.yay", + "culain.madstop.com", "10.1.1.1"), "Did not allow host to fs") + assert(! config.allowed?("fileserver.yay", + "culain.madstop.com", "10.10.1.1"), "Allowed host to fs") + assert(config.allowed?("fileserver.list", + "culain.madstop.com", "10.10.1.1"), "Did not allow host to fs.list") + } + end +end + +# $Id$ + diff --git a/test/network/server/authstore.rb b/test/network/server/authstore.rb new file mode 100755 index 000000000..0dc804079 --- /dev/null +++ b/test/network/server/authstore.rb @@ -0,0 +1,211 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' + +require 'puppet/network/authstore' + +class TestAuthStore < Test::Unit::TestCase + include PuppetTest + def mkstore + store = nil + assert_nothing_raised { + store = Puppet::Network::AuthStore.new + } + + return store + end + + def test_localallow + store = mkstore + + assert_nothing_raised { + assert(store.allowed?(nil, nil), "Store disallowed local access") + } + + assert_raise(Puppet::DevError) { + store.allowed?("kirby.madstop.com", nil) + } + + assert_raise(Puppet::DevError) { + store.allowed?(nil, "192.168.0.1") + } + end + + def test_hostnames + store = mkstore + + %w{ + kirby.madstop.com + luke.madstop.net + name-other.madstop.net + }.each { |name| + assert_nothing_raised("Failed to store simple name %s" % name) { + store.allow(name) + } + assert(store.allowed?(name, "192.168.0.1"), "Name %s not allowed" % name) + } + + %w{ + invalid + ^invalid! + inval$id + + }.each { |pat| + assert_raise(Puppet::AuthStoreError, + "name '%s' was allowed" % pat) { + store.allow(pat) + } + } + end + + def test_domains + store = mkstore + + assert_nothing_raised("Failed to store domains") { + store.allow("*.a.very.long.domain.name.com") + store.allow("*.madstop.com") + store.allow("*.some-other.net") + store.allow("*.much.longer.more-other.net") + } + + %w{ + madstop.com + culain.madstop.com + kirby.madstop.com + funtest.some-other.net + ya-test.madstop.com + some.much.much.longer.more-other.net + }.each { |name| + assert(store.allowed?(name, "192.168.0.1"), "Host %s not allowed" % name) + } + + assert_raise(Puppet::AuthStoreError) { + store.allow("domain.*.com") + } + + assert(!store.allowed?("very.long.domain.name.com", "1.2.3.4"), + "Long hostname allowed") + + assert_raise(Puppet::AuthStoreError) { + store.allow("domain.*.other.com") + } + end + + def test_simpleips + store = mkstore + + %w{ + 192.168.0.5 + 7.0.48.7 + }.each { |ip| + assert_nothing_raised("Failed to store IP address %s" % ip) { + store.allow(ip) + } + + assert(store.allowed?("hosttest.com", ip), "IP %s not allowed" % ip) + } + + #assert_raise(Puppet::AuthStoreError) { + # store.allow("192.168.674.0") + #} + + assert_raise(Puppet::AuthStoreError) { + store.allow("192.168.0") + } + end + + def test_ipranges + store = mkstore + + %w{ + 192.168.0.* + 192.168.1.0/24 + 192.178.* + 193.179.0.0/8 + }.each { |range| + assert_nothing_raised("Failed to store IP range %s" % range) { + store.allow(range) + } + } + + %w{ + 192.168.0.1 + 192.168.1.5 + 192.178.0.5 + 193.0.0.1 + }.each { |ip| + assert(store.allowed?("fakename.com", ip), "IP %s is not allowed" % ip) + } + end + + def test_iprangedenials + store = mkstore + + assert_nothing_raised("Failed to store overlapping IP ranges") { + store.allow("192.168.0.0/16") + store.deny("192.168.0.0/24") + } + + assert(store.allowed?("fake.name", "192.168.1.50"), "/16 ip not allowed") + assert(! store.allowed?("fake.name", "192.168.0.50"), "/24 ip allowed") + end + + def test_subdomaindenails + store = mkstore + + assert_nothing_raised("Failed to store overlapping IP ranges") { + store.allow("*.madstop.com") + store.deny("*.sub.madstop.com") + } + + assert(store.allowed?("hostname.madstop.com", "192.168.1.50"), + "hostname not allowed") + assert(! store.allowed?("name.sub.madstop.com", "192.168.0.50"), + "subname name allowed") + end + + def test_orderingstuff + store = mkstore + + assert_nothing_raised("Failed to store overlapping IP ranges") { + store.allow("*.madstop.com") + store.deny("192.168.0.0/24") + } + + assert(store.allowed?("hostname.madstop.com", "192.168.1.50"), + "hostname not allowed") + assert(! store.allowed?("hostname.madstop.com", "192.168.0.50"), + "Host allowed over IP") + end + + def test_globalallow + store = mkstore + + assert_nothing_raised("Failed to add global allow") { + store.allow("*") + } + + [ + %w{hostname.com 192.168.0.4}, + %w{localhost 192.168.0.1}, + %w{localhost 127.0.0.1} + + ].each { |ary| + assert(store.allowed?(*ary), "Failed to allow %s" % [ary.join(",")]) + } + end + + # Make sure people can specify TLDs + def test_match_tlds + store = mkstore + + assert_nothing_raised { + store.allow("*.tld") + } + end +end + +# $Id$ + diff --git a/test/network/server/bucket.rb b/test/network/server/bucket.rb new file mode 100755 index 000000000..c76e35be2 --- /dev/null +++ b/test/network/server/bucket.rb @@ -0,0 +1,259 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'base64' + +class TestBucket < Test::Unit::TestCase + include PuppetTest::ServerTest + + def out + if defined? @num + @num += 1 + else + @num = 1 + end + + #Puppet.err "#{Process.pid}: %s: %s" % [@num, memory()] + #gcdebug(String) + end + + # run through all of the files and exercise the filebucket methods + def checkfiles(client) + files = filelist() + #files = %w{/usr/local/bin/vim /etc/motd /etc/motd /etc/motd /etc/motd} + #files = %w{/usr/local/bin/vim} + + # iterate across all of the files + files.each { |file| + Puppet.warning file + out + tempdir = tempfile() + Dir.mkdir(tempdir) + name = File.basename(file) + tmppath = File.join(tempdir,name) + @@tmpfiles << tmppath + + out + # copy the files to our tmp directory so we can modify them... + FileUtils.cp(file, tmppath) + + # make sure the copy worked + assert(FileTest.exists?(tmppath)) + + # backup both the orig file and the tmp file + osum = nil + tsum = nil + nsum = nil + out + assert_nothing_raised { + osum = client.backup(file) + } + out + assert_nothing_raised { + tsum = client.backup(tmppath) + } + out + + # verify you got the same sum back for both + assert(tsum == osum) + + # modify our tmp file + unless FileTest.writable?(tmppath) + File.chmod(0644, tmppath) + end + File.open(tmppath,File::WRONLY|File::TRUNC) { |wf| + wf.print "This is some test text\n" + } + out + + # back it up + assert_nothing_raised { + #STDERR.puts("backing up %s" % tmppath) if $debug + nsum = client.backup(tmppath) + } + out + + # and verify the sum changed + assert(tsum != nsum) + + # restore the orig + assert_nothing_raised { + nsum = client.restore(tmppath,tsum) + } + out + + # and verify it actually got restored + contents = File.open(tmppath) { |rf| + #STDERR.puts("reading %s" % tmppath) if $debug + rf.read + } + out + csum = Digest::MD5.hexdigest(contents) + out + assert(tsum == csum) + } + end + + # a list of files that should be on the system + # just something to test moving files around + def filelist + if defined? @files + return @files + else + @files = [] + end + + %w{ + who bash sh uname /etc/passwd /etc/syslog.conf /etc/hosts + }.each { |file| + # if it's fully qualified, just add it + if file =~ /^\// + if FileTest.exists?(file) + @files.push file + end + else + # else if it's unqualified, look for it in our path + begin + path = %x{which #{file}} + rescue => detail + #STDERR.puts "Could not search for binaries: %s" % detail + next + end + + if path != "" + @files.push path.chomp + end + end + } + + return @files + end + + def setup + super + @bucket = tempfile() + end + + #def teardown + # system("lsof -p %s" % Process.pid) + # super + #end + + # test operating against the local filebucket object + # this calls the direct server methods, which are different than the + # Dipper methods + def test_localserver + files = filelist() + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileBucket.new( + :Bucket => @bucket + ) + } + + # iterate across them... + files.each { |file| + contents = File.open(file) { |of| of.read } + + md5 = nil + + # add a file to the repository + assert_nothing_raised { + #STDERR.puts("adding %s" % file) if $debug + md5 = server.addfile(Base64.encode64(contents),file) + } + + # and get it back again + newcontents = nil + assert_nothing_raised { + #STDERR.puts("getting %s" % file) if $debug + newcontents = Base64.decode64(server.getfile(md5)) + } + + # and then make sure they're still the same + assert( + contents == newcontents + ) + } + end + + # test with a server and a Dipper + def test_localboth + files = filelist() + + bucket = nil + client = nil + threads = [] + assert_nothing_raised { + bucket = Puppet::Network::Server::FileBucket.new( + :Bucket => @bucket + ) + } + + #sleep(30) + assert_nothing_raised { + client = Puppet::Network::Client::Dipper.new( + :Bucket => bucket + ) + } + + #4.times { checkfiles(client) } + checkfiles(client) + end + + # test that things work over the wire + def test_webxmlmix + files = filelist() + + tmpdir = File.join(tmpdir(),"tmpfiledir") + @@tmpfiles << tmpdir + FileUtils.mkdir_p(tmpdir) + + Puppet[:autosign] = true + client = nil + port = Puppet[:masterport] + + pid = mkserver(:CA => {}, :FileBucket => { :Bucket => @bucket}) + + assert_nothing_raised { + client = Puppet::Network::Client::Dipper.new( + :Server => "localhost", + :Port => @@port + ) + } + + checkfiles(client) + + unless pid + raise "Uh, we don't have a child pid" + end + Process.kill("TERM", pid) + end + + def test_no_path_duplicates + bucket = nil + assert_nothing_raised { + bucket = Puppet::Network::Server::FileBucket.new( + :Bucket => @bucket + ) + } + + sum = nil + assert_nothing_raised { + sum = bucket.addfile("yayness", "/my/file") + } + assert_nothing_raised { + bucket.addfile("yayness", "/my/file") + } + + pathfile = File.join(bucket.path, sum, "paths") + + assert(FileTest.exists?(pathfile), "No path file at %s" % pathfile) + + assert_equal("/my/file\n", File.read(pathfile)) + end +end + +# $Id$ diff --git a/test/network/server/ca.rb b/test/network/server/ca.rb new file mode 100755 index 000000000..31b4994a5 --- /dev/null +++ b/test/network/server/ca.rb @@ -0,0 +1,233 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppet/network/server/ca' +require 'puppet/sslcertificates' + +# $Id$ + +if ARGV.length > 0 and ARGV[0] == "short" + $short = true +else + $short = false +end + +class TestCA < Test::Unit::TestCase + include PuppetTest::ServerTest + # Verify that we're autosigning. We have to autosign a "different" machine, + # since we always autosign the CA server's certificate. + def test_autocertgeneration + ca = nil + + # create our ca + assert_nothing_raised { + ca = Puppet::Network::Server::CA.new(:autosign => true) + } + + # create a cert with a fake name + key = nil + csr = nil + cert = nil + hostname = "test.domain.com" + assert_nothing_raised { + cert = Puppet::SSLCertificates::Certificate.new( + :name => "test.domain.com" + ) + } + + # make the request + assert_nothing_raised { + cert.mkcsr + } + + # and get it signed + certtext = nil + cacerttext = nil + assert_nothing_raised { + certtext, cacerttext = ca.getcert(cert.csr.to_s) + } + + # they should both be strings + assert_instance_of(String, certtext) + assert_instance_of(String, cacerttext) + + # and they should both be valid certs + assert_nothing_raised { + OpenSSL::X509::Certificate.new(certtext) + } + assert_nothing_raised { + OpenSSL::X509::Certificate.new(cacerttext) + } + + # and pull it again, just to make sure we're getting the same thing + newtext = nil + assert_nothing_raised { + newtext, cacerttext = ca.getcert( + cert.csr.to_s, "test.reductivelabs.com", "127.0.0.1" + ) + } + + assert_equal(certtext,newtext) + end + + # this time don't use autosign + def test_storeAndSign + ca = nil + caserv = nil + + # make our CA server + assert_nothing_raised { + caserv = Puppet::Network::Server::CA.new(:autosign => false) + } + + # retrieve the actual ca object + assert_nothing_raised { + ca = caserv.ca + } + + # make our test cert again + key = nil + csr = nil + cert = nil + hostname = "test.domain.com" + assert_nothing_raised { + cert = Puppet::SSLCertificates::Certificate.new( + :name => "anothertest.domain.com" + ) + } + # and the CSR + assert_nothing_raised { + cert.mkcsr + } + + # retrieve them + certtext = nil + assert_nothing_raised { + certtext, cacerttext = caserv.getcert( + cert.csr.to_s, "test.reductivelabs.com", "127.0.0.1" + ) + } + + # verify we got nothing back, since autosign is off + assert_equal("", certtext) + + # now sign it manually, with the CA object + x509 = nil + assert_nothing_raised { + x509, cacert = ca.sign(cert.csr) + } + + # and write it out + cert.cert = x509 + assert_nothing_raised { + cert.write + } + + assert(File.exists?(cert.certfile)) + + # now get them again, and verify that we actually get them + newtext = nil + assert_nothing_raised { + newtext, cacerttext = caserv.getcert(cert.csr.to_s) + } + + assert(newtext) + assert_nothing_raised { + OpenSSL::X509::Certificate.new(newtext) + } + + # Now verify that we can clean a given host's certs + assert_nothing_raised { + ca.clean("anothertest.domain.com") + } + + assert(!File.exists?(cert.certfile), "Cert still exists after clean") + end + + # and now test the autosign file + def test_autosign + autosign = File.join(tmpdir, "autosigntesting") + @@tmpfiles << autosign + File.open(autosign, "w") { |f| + f.puts "hostmatch.domain.com" + f.puts "*.other.com" + } + + caserv = nil + assert_nothing_raised { + caserv = Puppet::Network::Server::CA.new(:autosign => autosign) + } + + # make sure we know what's going on + assert(caserv.autosign?("hostmatch.domain.com")) + assert(caserv.autosign?("fakehost.other.com")) + assert(!caserv.autosign?("kirby.reductivelabs.com")) + assert(!caserv.autosign?("culain.domain.com")) + end + + # verify that things aren't autosigned by default + def test_nodefaultautosign + caserv = nil + assert_nothing_raised { + caserv = Puppet::Network::Server::CA.new() + } + + # make sure we know what's going on + assert(!caserv.autosign?("hostmatch.domain.com")) + assert(!caserv.autosign?("fakehost.other.com")) + assert(!caserv.autosign?("kirby.reductivelabs.com")) + assert(!caserv.autosign?("culain.domain.com")) + end + + # We want the CA to autosign its own certificate, because otherwise + # the puppetmasterd CA does not autostart. + def test_caautosign + server = nil + assert_nothing_raised { + server = Puppet::Network::Server.new( + :Port => @@port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :Status => nil + } + ) + } + end + + # Make sure true/false causes the file to be ignored. + def test_autosign_true_beats_file + caserv = nil + assert_nothing_raised { + caserv = Puppet::Network::Server::CA.new() + } + + host = "hostname.domain.com" + + # Create an autosign file + file = tempfile() + Puppet[:autosign] = file + + File.open(file, "w") { |f| + f.puts host + } + + # Start with "false" + Puppet[:autosign] = false + + assert(! caserv.autosign?(host), "Host was incorrectly autosigned") + + # Then set it to true + Puppet[:autosign] = true + assert(caserv.autosign?(host), "Host was not autosigned") + # And try a different host + assert(caserv.autosign?("other.yay.com"), "Host was not autosigned") + + # And lastly the file + Puppet[:autosign] = file + assert(caserv.autosign?(host), "Host was not autosigned") + + # And try a different host + assert(! caserv.autosign?("other.yay.com"), "Host was autosigned") + end +end diff --git a/test/network/server/fileserver.rb b/test/network/server/fileserver.rb new file mode 100755 index 000000000..4186f0e3b --- /dev/null +++ b/test/network/server/fileserver.rb @@ -0,0 +1,1024 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/server/fileserver' + +class TestFileServer < Test::Unit::TestCase + include PuppetTest + + def mkmount(path = nil) + mount = nil + name = "yaytest" + base = path || tempfile() + unless FileTest.exists?(base) + Dir.mkdir(base) + end + # Create a test file + File.open(File.join(base, "file"), "w") { |f| f.puts "bazoo" } + assert_nothing_raised { + mount = Puppet::Network::Server::FileServer::Mount.new(name, base) + } + + return mount + end + # make a simple file source + def mktestdir + testdir = File.join(tmpdir(), "remotefilecopytesting") + @@tmpfiles << testdir + + # create a tmpfile + pattern = "tmpfile" + tmpfile = File.join(testdir, pattern) + assert_nothing_raised { + Dir.mkdir(testdir) + File.open(tmpfile, "w") { |f| + 3.times { f.puts rand(100) } + } + } + + return [testdir, %r{#{pattern}}, tmpfile] + end + + # make a bunch of random test files + def mktestfiles(testdir) + @@tmpfiles << testdir + assert_nothing_raised { + files = %w{a b c d e}.collect { |l| + name = File.join(testdir, "file%s" % l) + File.open(name, "w") { |f| + f.puts rand(100) + } + + name + } + + return files + } + end + + def assert_describe(base, file, server) + file = File.basename(file) + assert_nothing_raised { + desc = server.describe(base + file) + assert(desc, "Got no description for %s" % file) + assert(desc != "", "Got no description for %s" % file) + assert_match(/^\d+/, desc, "Got invalid description %s" % desc) + } + end + + # test for invalid names + def test_namefailures + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + assert_raise(Puppet::Network::Server::FileServerError) { + server.mount("/tmp", "invalid+name") + } + + assert_raise(Puppet::Network::Server::FileServerError) { + server.mount("/tmp", "invalid-name") + } + + assert_raise(Puppet::Network::Server::FileServerError) { + server.mount("/tmp", "invalid name") + } + + assert_raise(Puppet::Network::Server::FileServerError) { + server.mount("/tmp", "") + } + end + + # verify that listing the root behaves as expected + def test_listroot + server = nil + testdir, pattern, tmpfile = mktestdir() + + file = nil + checks = Puppet::Network::Server::FileServer::CHECKPARAMS + + # and make our fileserver + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + # mount the testdir + assert_nothing_raised { + server.mount(testdir, "test") + } + + # and verify different iterations of 'root' return the same value + list = nil + assert_nothing_raised { + list = server.list("/test/", :ignore, true, false) + } + + assert(list =~ pattern) + + assert_nothing_raised { + list = server.list("/test", :ignore, true, false) + } + assert(list =~ pattern) + + end + + # test listing individual files + def test_getfilelist + server = nil + testdir, pattern, tmpfile = mktestdir() + + file = nil + + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + assert_nothing_raised { + server.mount(testdir, "test") + } + + # get our listing + list = nil + sfile = "/test/tmpfile" + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false) + } + + assert_nothing_raised { + file = Puppet.type(:file)[tmpfile] + } + + output = "/\tfile" + + # verify it got listed as a file + assert_equal(output, list) + + # verify we got all fields + assert(list !~ /\t\t/) + + # verify that we didn't get the directory itself + list.split("\n").each { |line| + assert(line !~ %r{remotefile}) + } + + # and then verify that the contents match + contents = File.read(tmpfile) + + ret = nil + assert_nothing_raised { + ret = server.retrieve(sfile) + } + + assert_equal(contents, ret) + end + + # check that the fileserver is seeing newly created files + def test_seenewfiles + server = nil + testdir, pattern, tmpfile = mktestdir() + + + newfile = File.join(testdir, "newfile") + + # go through the whole schtick again... + file = nil + checks = Puppet::Network::Server::FileServer::CHECKPARAMS + + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + assert_nothing_raised { + server.mount(testdir, "test") + } + + list = nil + sfile = "/test/" + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false) + } + + # create the new file + File.open(newfile, "w") { |f| + 3.times { f.puts rand(100) } + } + + newlist = nil + assert_nothing_raised { + newlist = server.list(sfile, :ignore, true, false) + } + + # verify the list has changed + assert(list != newlist) + + # and verify that we are specifically seeing the new file + assert(newlist =~ /newfile/) + end + + # verify we can mount /, which is what local file servers will + # normally do + def test_zmountroot + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + assert_nothing_raised { + server.mount("/", "root") + } + + testdir, pattern, tmpfile = mktestdir() + + list = nil + assert_nothing_raised { + list = server.list("/root/" + testdir, :ignore, true, false) + } + + assert(list =~ pattern) + assert_nothing_raised { + list = server.list("/root" + testdir, :ignore, true, false) + } + + assert(list =~ pattern) + end + + # verify that we're correctly recursing the right number of levels + def test_recursionlevels + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + # make our deep recursion + basedir = File.join(tmpdir(), "recurseremotetesting") + testdir = "%s/with/some/sub/directories/for/the/purposes/of/testing" % basedir + oldfile = File.join(testdir, "oldfile") + assert_nothing_raised { + system("mkdir -p %s" % testdir) + File.open(oldfile, "w") { |f| + 3.times { f.puts rand(100) } + } + @@tmpfiles << basedir + } + + assert_nothing_raised { + server.mount(basedir, "test") + } + + # get our list + list = nil + assert_nothing_raised { + list = server.list("/test/with", :ignore, false, false) + } + + # make sure we only got one line, since we're not recursing + assert(list !~ /\n/) + + # for each level of recursion, make sure we get the right list + [0, 1, 2].each { |num| + assert_nothing_raised { + list = server.list("/test/with", :ignore, num, false) + } + + count = 0 + while list =~ /\n/ + list.sub!(/\n/, '') + count += 1 + end + assert_equal(num, count) + } + end + + # verify that we're not seeing the dir we ask for; i.e., that our + # list is relative to that dir, not it's parent dir + def test_listedpath + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + + # create a deep dir + basedir = tempfile() + testdir = "%s/with/some/sub/directories/for/testing" % basedir + oldfile = File.join(testdir, "oldfile") + assert_nothing_raised { + system("mkdir -p %s" % testdir) + File.open(oldfile, "w") { |f| + 3.times { f.puts rand(100) } + } + @@tmpfiles << basedir + } + + # mounty mounty + assert_nothing_raised { + server.mount(basedir, "localhost") + } + + list = nil + # and then check a few dirs + assert_nothing_raised { + list = server.list("/localhost/with", :ignore, false, false) + } + + assert(list !~ /with/) + + assert_nothing_raised { + list = server.list("/localhost/with/some/sub", :ignore, true, false) + } + + assert(list !~ /sub/) + end + + # test many dirs, not necessarily very deep + def test_widelists + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + basedir = tempfile() + dirs = %w{a set of directories} + assert_nothing_raised { + Dir.mkdir(basedir) + dirs.each { |dir| + Dir.mkdir(File.join(basedir, dir)) + } + @@tmpfiles << basedir + } + + assert_nothing_raised { + server.mount(basedir, "localhost") + } + + list = nil + assert_nothing_raised { + list = server.list("/localhost/", :ignore, 1, false) + } + assert_instance_of(String, list, "Server returned %s instead of string") + list = list.split("\n") + + assert_equal(dirs.length + 1, list.length) + end + + # verify that 'describe' works as advertised + def test_describe + server = nil + testdir = tstdir() + files = mktestfiles(testdir) + + file = nil + checks = Puppet::Network::Server::FileServer::CHECKPARAMS + + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + assert_nothing_raised { + server.mount(testdir, "test") + } + + # get our list + list = nil + sfile = "/test/" + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false) + } + + # and describe each file in the list + assert_nothing_raised { + list.split("\n").each { |line| + file, type = line.split("\t") + + desc = server.describe(sfile + file) + } + } + + # and then make sure we can describe everything that we know is there + files.each { |file| + assert_describe(sfile, file, server) + } + + # And then describe some files that we know aren't there + retval = nil + assert_nothing_raised("Describing non-existent files raised an error") { + retval = server.describe(sfile + "noexisties") + } + + assert_equal("", retval, "Description of non-existent files returned a value") + + # Now try to describe some sources that don't even exist + retval = nil + assert_raise(Puppet::Network::Server::FileServerError, + "Describing non-existent mount did not raise an error") { + retval = server.describe("/notmounted/" + "noexisties") + } + + assert_nil(retval, "Description of non-existent mounts returned a value") + end + + # test that our config file is parsing and working as planned + def test_configfile + server = nil + basedir = File.join(tmpdir, "fileserverconfigfiletesting") + @@tmpfiles << basedir + + # make some dirs for mounting + Dir.mkdir(basedir) + mounts = {} + %w{thing thus these those}.each { |dir| + path = File.join(basedir, dir) + Dir.mkdir(path) + mounts[dir] = mktestfiles(path) + + } + + # create an example file with each of them + conffile = tempfile + @@tmpfiles << conffile + + File.open(conffile, "w") { |f| + f.print "# a test config file + +[thing] + path #{basedir}/thing + allow 192.168.0.* + +[thus] + path #{basedir}/thus + allow *.madstop.com, *.kanies.com + deny *.sub.madstop.com + +[these] + path #{basedir}/these + +[those] + path #{basedir}/those + +" + } + + + # create a server with the file + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => false, + :Config => conffile + ) + } + + list = nil + # run through once with no host/ip info, to verify everything is working + mounts.each { |mount, files| + mount = "/#{mount}/" + assert_nothing_raised { + list = server.list(mount, :ignore, true, false) + } + + assert_nothing_raised { + list.split("\n").each { |line| + file, type = line.split("\t") + + desc = server.describe(mount + file) + } + } + + files.each { |f| + assert_describe(mount, f, server) + } + } + + # now let's check that things are being correctly forbidden + # this is just a map of names and expected results + { + "thing" => { + :deny => [ + ["hostname.com", "192.168.1.0"], + ["hostname.com", "192.158.0.0"] + ], + :allow => [ + ["hostname.com", "192.168.0.0"], + ["hostname.com", "192.168.0.245"], + ] + }, + "thus" => { + :deny => [ + ["hostname.com", "192.168.1.0"], + ["name.sub.madstop.com", "192.158.0.0"] + ], + :allow => [ + ["luke.kanies.com", "192.168.0.0"], + ["luke.madstop.com", "192.168.0.245"], + ] + } + }.each { |mount, hash| + mount = "/#{mount}/" + + # run through the map + hash.each { |type, ary| + ary.each { |sub| + host, ip = sub + + case type + when :deny: + assert_raise(Puppet::AuthorizationError, + "Host %s, ip %s, allowed %s" % + [host, ip, mount]) { + list = server.list(mount, :ignore, true, false, host, ip) + } + when :allow: + assert_nothing_raised("Host %s, ip %s, denied %s" % + [host, ip, mount]) { + list = server.list(mount, :ignore, true, false, host, ip) + } + end + } + } + } + + end + + # Test that we smoothly handle invalid config files + def test_configfailures + # create an example file with each of them + conffile = tempfile() + + invalidmounts = { + "noexist" => "[noexist] + path /this/path/does/not/exist + allow 192.168.0.* +" +} + + invalidconfigs = [ +"[not valid] + path /this/path/does/not/exist + allow 192.168.0.* +", +"[valid] + invalidstatement + path /etc + allow 192.168.0.* +", +"[valid] + allow 192.168.0.* +" +] + + invalidmounts.each { |mount, text| + File.open(conffile, "w") { |f| + f.print text + } + + + # create a server with the file + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => conffile + ) + } + + assert_raise(Puppet::Network::Server::FileServerError, + "Invalid mount was mounted") { + server.list(mount, :ignore) + } + } + + invalidconfigs.each_with_index { |text, i| + File.open(conffile, "w") { |f| + f.print text + } + + + # create a server with the file + server = nil + assert_raise(Puppet::Network::Server::FileServerError, + "Invalid config %s did not raise error" % i) { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => conffile + ) + } + } + end + + # verify we reread the config file when it changes + def test_filereread + server = nil + + conffile = tempfile() + dir = tstdir() + + files = mktestfiles(dir) + File.open(conffile, "w") { |f| + f.print "# a test config file + +[thing] + path #{dir} + allow test1.domain.com +" + } + + # Reset the timeout, so we reload faster + Puppet[:filetimeout] = 0.5 + + # start our server with a fast timeout + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => false, + :Config => conffile + ) + } + + list = nil + assert_nothing_raised { + list = server.list("/thing/", :ignore, false, false, + "test1.domain.com", "127.0.0.1") + } + assert(list != "", "List returned nothing in rereard test") + + assert_raise(Puppet::AuthorizationError, "List allowed invalid host") { + list = server.list("/thing/", :ignore, false, false, + "test2.domain.com", "127.0.0.1") + } + + sleep 1 + File.open(conffile, "w") { |f| + f.print "# a test config file + +[thing] + path #{dir} + allow test2.domain.com +" + } + + assert_raise(Puppet::AuthorizationError, "List allowed invalid host") { + list = server.list("/thing/", :ignore, false, false, + "test1.domain.com", "127.0.0.1") + } + + assert_nothing_raised { + list = server.list("/thing/", :ignore, false, false, + "test2.domain.com", "127.0.0.1") + } + + assert(list != "", "List returned nothing in rereard test") + + list = nil + end + + # Verify that we get converted to the right kind of string + def test_mountstring + mount = nil + name = "yaytest" + path = tmpdir() + assert_nothing_raised { + mount = Puppet::Network::Server::FileServer::Mount.new(name, path) + } + + assert_equal("mount[#{name}]", mount.to_s) + end + + def test_servinglinks + server = nil + source = tempfile() + file = File.join(source, "file") + link = File.join(source, "link") + Dir.mkdir(source) + File.open(file, "w") { |f| f.puts "yay" } + File.symlink(file, link) + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + assert_nothing_raised { + server.mount(source, "mount") + } + + # First describe the link when following + results = {} + assert_nothing_raised { + server.describe("/mount/link", :follow).split("\t").zip( + Puppet::Network::Server::FileServer::CHECKPARAMS + ).each { |v,p| results[p] = v } + } + + assert_equal("file", results[:type]) + + # Then not + results = {} + assert_nothing_raised { + server.describe("/mount/link", :ignore).split("\t").zip( + Puppet::Network::Server::FileServer::CHECKPARAMS + ).each { |v,p| results[p] = v } + } + + assert_equal("link", results[:type]) + + results.each { |p,v| + assert(v, "%s has no value" % p) + assert(v != "", "%s has no value" % p) + } + end + + # Test that substitution patterns in the path are exapanded + # properly. Disabled, because it was testing too much of the process + # and in a non-portable way. This is a thorough enough test that it should + # be kept, but it should be done in a way that is clearly portable (e.g., + # no md5 sums of file paths). + def test_host_specific + client1 = "client1.example.com" + client2 = "client2.example.com" + ip = "127.0.0.1" + + # Setup a directory hierarchy for the tests + fsdir = File.join(tmpdir(), "host-specific") + @@tmpfiles << fsdir + hostdir = File.join(fsdir, "host") + fqdndir = File.join(fsdir, "fqdn") + client1_hostdir = File.join(hostdir, "client1") + client2_fqdndir = File.join(fqdndir, client2) + contents = { + client1_hostdir => "client1\n", + client2_fqdndir => client2 + "\n" + } + [fsdir, hostdir, fqdndir, + client1_hostdir, client2_fqdndir].each { |d| Dir.mkdir(d) } + + [client1_hostdir, client2_fqdndir].each do |d| + File.open(File.join(d, "file.txt"), "w") do |f| + f.print contents[d] + end + end + conffile = tempfile() + File.open(conffile, "w") do |f| + f.print(" +[host] +path #{hostdir}/%h +allow * +[fqdn] +path #{fqdndir}/%H +allow * +") + end + + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => conffile + ) + } + + # check that list returns the correct thing for the two clients + list = nil + sfile = "/host/file.txt" + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false, client1, ip) + } + assert_equal("/\tfile", list) + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false, client2, ip) + } + assert_equal("", list) + + sfile = "/fqdn/file.txt" + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false, client1, ip) + } + assert_equal("", list) + assert_nothing_raised { + list = server.list(sfile, :ignore, true, false, client2, ip) + } + assert_equal("/\tfile", list) + + # check describe + sfile = "/host/file.txt" + assert_nothing_raised { + list = server.describe(sfile, :ignore, client1, ip).split("\t") + } + assert_equal(5, list.size) + assert_equal("file", list[1]) + md5 = Digest::MD5.hexdigest(contents[client1_hostdir]) + assert_equal("{md5}#{md5}", list[4]) + + assert_nothing_raised { + list = server.describe(sfile, :ignore, client2, ip).split("\t") + } + assert_equal([], list) + + sfile = "/fqdn/file.txt" + assert_nothing_raised { + list = server.describe(sfile, :ignore, client1, ip).split("\t") + } + assert_equal([], list) + + assert_nothing_raised { + list = server.describe(sfile, :ignore, client2, ip).split("\t") + } + assert_equal(5, list.size) + assert_equal("file", list[1]) + md5 = Digest::MD5.hexdigest(contents[client2_fqdndir]) + assert_equal("{md5}#{md5}", list[4]) + + # Check retrieve + sfile = "/host/file.txt" + assert_nothing_raised { + list = server.retrieve(sfile, :ignore, client1, ip).chomp + } + assert_equal(contents[client1_hostdir].chomp, list) + + assert_nothing_raised { + list = server.retrieve(sfile, :ignore, client2, ip).chomp + } + assert_equal("", list) + + sfile = "/fqdn/file.txt" + assert_nothing_raised { + list = server.retrieve(sfile, :ignore, client1, ip).chomp + } + assert_equal("", list) + + assert_nothing_raised { + list = server.retrieve(sfile, :ignore, client2, ip).chomp + } + assert_equal(contents[client2_fqdndir].chomp, list) + end + + # Make sure the 'subdir' method in Mount works. + def test_mount_subdir + mount = nil + base = tempfile() + Dir.mkdir(base) + subdir = File.join(base, "subdir") + Dir.mkdir(subdir) + [base, subdir].each do |d| + File.open(File.join(d, "file"), "w") { |f| f.puts "bazoo" } + end + mount = mkmount(base) + + assert_equal(base, mount.subdir(), "Did not default to base path") + assert_equal(subdir, mount.subdir("subdir"), "Did not default to base path") + end + + # Make sure mounts get correctly marked expandable or not, depending on + # the path. + def test_expandable + name = "yaytest" + dir = tempfile() + Dir.mkdir(dir) + + mount = mkmount() + assert_nothing_raised { + mount.path = dir + } + + assert(! mount.expandable?, "Mount incorrectly called expandable") + + assert_nothing_raised { + mount.path = "/dir/a%a" + } + assert(mount.expandable?, "Mount not called expandable") + + # This isn't a valid replacement pattern, so it should throw an error + # because the dir doesn't exist + assert_raise(Puppet::Network::Server::FileServerError) { + mount.path = "/dir/a%" + } + + # Now send it back to a normal path + assert_nothing_raised { + mount.path = dir + } + # Make sure it got reverted + assert(! mount.expandable?, "Mount incorrectly called expandable") + + + end + + def test_mount_expand + mount = mkmount() + + check = proc do |client, pattern, repl| + path = "/my/#{pattern}/file" + assert_equal("/my/#{repl}/file", mount.expand(path, client)) + end + + # Do a round of checks with a fake client + client = "host.domain.com" + {"%h" => "host", # Short name + "%H" => client, # Full name + "%d" => "domain.com", # domain + "%%" => "%", # escape + "%o" => "%o" # other + }.each do |pat, repl| + result = check.call(client, pat, repl) + end + + # Now, check that they use Facter info + Puppet.notice "The following messages are normal" + client = nil + local = Facter["hostname"].value + domain = Facter["domain"].value + fqdn = [local, domain].join(".") + {"%h" => local, # Short name + "%H" => fqdn, # Full name + "%d" => domain, # domain + "%%" => "%", # escape + "%o" => "%o" # other + }.each do |pat, repl| + check.call(client, pat, repl) + end + + end + + # Test that the fileserver expands the %h and %d things. + def test_fileserver_expansion + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::FileServer.new( + :Local => true, + :Config => false + ) + } + + dir = tempfile() + ip = Facter.value(:ipaddress) + + Dir.mkdir(dir) + host = "host.domain.com" + { + "%H" => "host.domain.com", "%h" => "host", "%d" => "domain.com" + }.each do |pattern, string| + file = File.join(dir, string) + mount = File.join(dir, pattern) + File.open(file, "w") do |f| f.puts "yayness: %s" % string end + name = "name" + obj = nil + assert_nothing_raised { + obj = server.mount(mount, name) + } + obj.allow "*" + + ret = nil + assert_nothing_raised do + ret = server.list("/name", :ignore, false, false, host, ip) + end + + assert_equal("/\tfile", ret) + + assert_nothing_raised do + ret = server.describe("/name", :ignore, host, ip) + end + assert(ret =~ /\tfile\t/, "Did not get valid a description") + + assert_nothing_raised do + ret = server.retrieve("/name", :ignore, host, ip) + end + + assert_equal(ret, File.read(file)) + + server.umount(name) + + File.unlink(file) + end + end +end + +# $Id$ + diff --git a/test/network/server/logger.rb b/test/network/server/logger.rb new file mode 100755 index 000000000..7298062ca --- /dev/null +++ b/test/network/server/logger.rb @@ -0,0 +1,179 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'base64' +require 'cgi' + +class TestLogger < Test::Unit::TestCase + include PuppetTest::ServerTest + + def setup + super + #Puppet[:debug] = true + Puppet::Util::Log.newdestination :console + end + + # Test the log driver manually + def test_localaddlog + logger = nil + assert_nothing_raised { + logger = Puppet::Network::Server::Logger.new + } + + msg = nil + assert_nothing_raised { + msg = Puppet::Util::Log.create( + :level => :warning, + :message => "This is a message" + ) + } + + assert_nothing_raised { + logger.addlog(msg) + } + end + + # Test it while replicating a remote client + def test_remoteaddlog + logger = nil + assert_nothing_raised { + logger = Puppet::Network::Server::Logger.new + } + + msg = nil + assert_nothing_raised { + msg = Puppet::Util::Log.create( + :level => :warning, + :message => "This is a remote message" + ) + } + + assert_nothing_raised { + msg = CGI.escape(YAML.dump(msg)) + } + assert_nothing_raised { + logger.addlog(msg, "localhost", "127.0.0.1") + } + end + + # Now test it with a real client and server, but not remote + def test_localclient + client = nil + assert_nothing_raised { + client = Puppet::Network::Client::LogClient.new(:Logger => true) + } + + msg = nil + assert_nothing_raised { + msg = Puppet::Util::Log.create( + :level => :warning, + :message => "This is a logclient message" + ) + } + + msg = CGI.escape(YAML.dump(msg)) + + assert_nothing_raised { + client.addlog(msg, "localhost", "127.0.0.1") + } + end + + # And now test over the network + # This test is disabled, since it doesn't work well and it's not the right + # solution anyway. + def disabled_test_logclient + pid = nil + clientlog = tempfile() + serverlog = tempfile() + Puppet.warning "serverlog is %s" % serverlog + Puppet::Util::Log.newdestination clientlog + Puppet::Util::Log.close(:syslog) + + # For testing + Puppet[:autosign] = true + + logger = nil + # Create our server + assert_nothing_raised { + logger = Puppet::Network::Server.new( + :Port => @@port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :Logger => {} + } + ) + } + + # Start our server + serverpid = fork { + Puppet::Util::Log.close(clientlog) + Puppet::Util::Log.newdestination serverlog + assert_nothing_raised() { + trap(:INT) { logger.shutdown } + logger.start + } + } + @@tmppids << serverpid + sleep(0.5) + + # Start a raw xmlrpc client + client = nil + assert_nothing_raised() { + client = Puppet::Network::Client::LogClient.new( + :Server => "localhost", + :Port => @@port + ) + unless client.readcert + raise "Could not get certs" + end + } + retval = nil + + { + :notice => "XMLRPC1", + :warning => "XMLRPC2", + :err => "XMLRPC3" + }.each { |level, str| + msg = CGI.escape(YAML.dump(Puppet::Util::Log.create( + :level => level, + :message => str + ))) + assert_nothing_raised { + retval = client.addlog(msg) + } + } + + # and now use the normal client action + + # Set the log destination to be the server + Puppet::Util::Log.newdestination "localhost:%s" % @@port + + # And now do some logging + assert_nothing_raised { + Puppet.notice "TEST1" + Puppet.warning "TEST2" + Puppet.err "TEST3" + } + + assert_nothing_raised { + Process.kill("INT", serverpid) + } + + assert(FileTest.exists?(serverlog), "Server log does not exist") + + # Give it a bit to flush to disk + sleep(0.5) + content = nil + assert_nothing_raised { + content = File.read(serverlog) + } + + %w{TEST1 TEST2 TEST3}.each { |str| + assert(content =~ %r{#{str}}, "Content does not match %s" % str) + } + end +end + +# $Id$ diff --git a/test/network/server/master.rb b/test/network/server/master.rb new file mode 100755 index 000000000..797e75e3d --- /dev/null +++ b/test/network/server/master.rb @@ -0,0 +1,346 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/server' + +class TestMaster < Test::Unit::TestCase + include PuppetTest::ServerTest + def teardown + super + #print "\n\n\n\n" if Puppet[:debug] + end + + # run through all of the existing test files and make sure everything + # works + def test_files + count = 0 + textfiles { |file| + Puppet.debug("parsing %s" % file) + client = nil + master = nil + + # create our master + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => file, + :UseNodes => false, + :Local => true + ) + } + + # and our client + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Master => master + ) + } + + # pull our configuration a few times + assert_nothing_raised() { + client.getconfig + stopservices + Puppet::Type.allclear + } + assert_nothing_raised() { + client.getconfig + stopservices + Puppet::Type.allclear + } + assert_nothing_raised() { + client.getconfig + stopservices + Puppet::Type.allclear + } + # only test three files; that's plenty + if count > 3 + break + end + count += 1 + } + end + + def test_defaultmanifest + textfiles { |file| + Puppet[:manifest] = file + client = nil + master = nil + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => file, + :UseNodes => false, + :Local => true + ) + } + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Master => master + ) + } + + # pull our configuration + assert_nothing_raised() { + client.getconfig + stopservices + Puppet::Type.allclear + } + + break + } + end + + def test_filereread + # Start with a normal setting + Puppet[:filetimeout] = 15 + manifest = mktestmanifest() + + file2 = @createdfile + "2" + @@tmpfiles << file2 + + client = master = nil + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => manifest, + :UseNodes => false, + :Local => true + ) + } + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Master => master + ) + } + + # The client doesn't have a config, so it can't be up to date + assert(! client.fresh?, "Client is incorrectly up to date") + + Puppet.config.use(:puppet) + assert_nothing_raised { + client.getconfig + client.apply + } + + # Now it should be up to date + assert(client.fresh?, "Client is not up to date") + + # Cache this value for later + parse1 = master.freshness + + # Verify the config got applied + assert(FileTest.exists?(@createdfile), + "Created file %s does not exist" % @createdfile) + Puppet::Type.allclear + + sleep 1.5 + # Create a new manifest + File.open(manifest, "w") { |f| + f.puts "file { \"%s\": ensure => file }\n" % file2 + } + + # Verify that the master doesn't immediately reparse the file; we + # want to wait through the timeout + assert_equal(parse1, master.freshness, "Master did not wait through timeout") + assert(client.fresh?, "Client is not up to date") + + # Then eliminate it + Puppet[:filetimeout] = 0 + + # Now make sure the master does reparse + #Puppet.notice "%s vs %s" % [parse1, master.freshness] + assert(parse1 != master.freshness, "Master did not reparse file") + assert(! client.fresh?, "Client is incorrectly up to date") + + # Retrieve and apply the new config + assert_nothing_raised { + client.getconfig + client.apply + } + assert(client.fresh?, "Client is not up to date") + + assert(FileTest.exists?(file2), "Second file %s does not exist" % file2) + end + + def test_addfacts + master = nil + file = mktestmanifest() + # create our master + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => file, + :UseNodes => false, + :Local => true + ) + } + + facts = {} + + assert_nothing_raised { + master.addfacts(facts) + } + + %w{serverversion servername serverip}.each do |fact| + assert(facts.include?(fact), "Fact %s was not set" % fact) + end + end + + # Make sure we're using the hostname as configured with :node_name + def test_hostname_in_getconfig + master = nil + file = tempfile() + #@createdfile = File.join(tmpdir(), self.class.to_s + "manifesttesting" + + # "_" + @method_name) + file_cert = tempfile() + file_fact = tempfile() + + certname = "y4yn3ss" + factname = Facter.value("hostname") + + File.open(file, "w") { |f| + f.puts %{ + node #{certname} { file { "#{file_cert}": ensure => file, mode => 755 } } + node #{factname} { file { "#{file_fact}": ensure => file, mode => 755 } } +} + } + # create our master + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => file, + :UseNodes => true, + :Local => true + ) + } + + result = nil + + # Use the hostname from facter + Puppet[:node_name] = 'facter' + assert_nothing_raised { + result = master.getconfig({"hostname" => factname}, "yaml", certname, "127.0.0.1") + } + + result = result.flatten + + assert(result.find { |obj| obj.name == file_fact }, + "Could not find correct file") + assert(!result.find { |obj| obj.name == file_cert }, + "Found incorrect file") + + # Use the hostname from the cert + Puppet[:node_name] = 'cert' + assert_nothing_raised { + result = master.getconfig({"hostname" => factname}, "yaml", certname, "127.0.0.1") + } + + result = result.flatten + + assert(!result.find { |obj| obj.name == file_fact }, + "Could not find correct file") + assert(result.find { |obj| obj.name == file_cert }, + "Found incorrect file") + end + + # Make sure we're correctly doing clientname manipulations. + # Testing to make sure we always get a hostname and IP address. + def test_clientname + master = nil + file = tempfile() + + File.open(file, "w") { |f| + f.puts %{ + node yay { file { "/something": ensure => file, mode => 755 } } +} + } + # create our master + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => file, + :UseNodes => true, + :Local => true + ) + } + + Puppet[:node_name] = "cert" + # First act like we're local + fakename = nil + fakeip = nil + + name = ip = nil + facts = Facter.to_hash + assert_nothing_raised do + name, ip = master.clientname(fakename, fakeip, facts) + end + + assert(facts["hostname"], "Removed hostname fact") + assert(facts["ipaddress"], "Removed ipaddress fact") + + assert_equal(facts["hostname"], name) + assert_equal(facts["ipaddress"], ip) + + # Now set them to something real, and make sure we get them back + fakename = "yayness" + fakeip = "192.168.0.1" + facts = Facter.to_hash + assert_nothing_raised do + name, ip = master.clientname(fakename, fakeip, facts) + end + + assert(facts["hostname"], "Removed hostname fact") + assert(facts["ipaddress"], "Removed ipaddress fact") + + assert_equal(fakename, name) + assert_equal(fakeip, ip) + end + + if Puppet.features.rails? + def test_freshness_connect_update + Puppet::Rails.init + Puppet[:storeconfigs] = true + + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Code => "", + :UseNodes => true, + :Local => true + ) + + # Create a host + Puppet::Rails::Host.new(:name => "test", :ip => "192.168.0.3").save + + assert_nothing_raised("Failed to update last_connect for unknown host") do + master.freshness("created",'192.168.0.1') + end + + # Make sure it created the host + created = Puppet::Rails::Host.find_by_name("created") + assert(created, "Freshness did not create host") + assert(created.last_freshcheck, + "Did not set last_freshcheck on created host") + assert_equal("192.168.0.1", created.ip, + "Did not set IP address on created host") + + # Now check on the existing host + assert_nothing_raised("Failed to update last_connect for unknown host") do + master.freshness("test",'192.168.0.2') + end + + # Recreate it, so we're not using the cached object. + host = Puppet::Rails::Host.find_by_name("test") + + # Make sure it created the host + assert(host.last_freshcheck, + "Did not set last_freshcheck on existing host") + assert_equal("192.168.0.3", host.ip, + "Overrode IP on found host") + end + end +end + +# $Id$ + diff --git a/test/network/server/report.rb b/test/network/server/report.rb new file mode 100755 index 000000000..f61d9f6d4 --- /dev/null +++ b/test/network/server/report.rb @@ -0,0 +1,185 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/server/report' +require 'puppettest/reporttesting' + +class TestReportServer < Test::Unit::TestCase + include PuppetTest + include PuppetTest::Reporttesting + + Report = Puppet::Network::Server::Report + Puppet::Util.logmethods(self) + + def mkserver + server = nil + assert_nothing_raised { + server = Puppet::Network::Server::Report.new() + } + server + end + + def mkclient(server = nil) + server ||= mkserver() + client = nil + assert_nothing_raised { + client = Puppet::Network::Client::Reporter.new(:Report => server) + } + + client + end + + def test_report_autoloading + # Create a fake report + fakedir = tempfile() + $: << fakedir + cleanup do $:.delete(fakedir) end + + libdir = File.join(fakedir, "puppet", "reports") + FileUtils.mkdir_p(libdir) + + $myreportrun = false + file = File.join(libdir, "myreport.rb") + File.open(file, "w") { |f| f.puts %{ + Puppet::Network::Server::Report.newreport(:myreport) do + def process(report) + $myreportrun = true + return report + end + end + } + } + Puppet[:reports] = "myreport" + + # Create a server + server = Puppet::Network::Server::Report.new + + report = nil + assert_nothing_raised { + report = Puppet::Network::Server::Report.report(:myreport) + } + assert(report, "Did not get report") + + end + + def test_process + server = Puppet::Network::Server::Report.new + + # We have to run multiple reports to make sure there's no conflict + reports = [] + $run = [] + 5.times do |i| + name = "processtest%s" % i + reports << name + + Report.newreport(name) do + def process + $run << self.report_name + end + end + end + Puppet[:reports] = reports.collect { |r| r.to_s }.join(",") + + report = fakereport + + retval = nil + assert_nothing_raised { + retval = server.send(:process, YAML.dump(report)) + } + + reports.each do |name| + assert($run.include?(name.intern), "Did not run %s" % name) + end + + # Now make sure our server doesn't die on missing reports + Puppet[:reports] = "fakereport" + assert_nothing_raised { + retval = server.send(:process, YAML.dump(report)) + } + end + + # Make sure reports can specify whether to use yaml or not + def test_useyaml + server = Puppet::Network::Server::Report.new + + Report.newreport(:yamlyes, :useyaml => true) do + def process(report) + $yamlyes = :yesyaml + end + end + + Report.newreport(:yamlno) do + def process + $yamlno = :noyaml + end + end + + Puppet[:reports] = "yamlyes, yamlno" + + report = fakereport + yaml = YAML.dump(report) + + assert_nothing_raised do + server.send(:process, yaml) + end + + assert_equal(:noyaml, $yamlno, "YAML was used for non-yaml report") + assert_equal(:yesyaml, $yamlyes, "YAML was not used for yaml report") + end + + def test_reports + Puppet[:reports] = "myreport" + + # Create a server + server = Puppet::Network::Server::Report.new + + {"myreport" => ["myreport"], + " fake, another, yay " => ["fake", "another", "yay"] + }.each do |str, ary| + Puppet[:reports] = str + assert_equal(ary, server.send(:reports)) + end + end + + def test_newreport + name = :newreporttest + assert_nothing_raised do + Report.newreport(name) do + attr_accessor :processed + + def process(report) + @processed = report + end + end + end + + assert(Report.report(name), "Did not get report") + assert_instance_of(Module, Report.report(name)) + + obj = "yay" + obj.extend(Report.report(name)) + + assert_nothing_raised do + obj.process("yay") + end + + assert_equal("yay", obj.processed) + end + + # Make sure we get a list of all reports + def test_report_list + list = nil + assert_nothing_raised do + list = Puppet::Network::Server::Report.reports + end + + [:rrdgraph, :store, :tagmail].each do |name| + assert(list.include?(name), "Did not load %s" % name) + end + end +end + +# $Id$ + diff --git a/test/network/server/resource.rb b/test/network/server/resource.rb new file mode 100755 index 000000000..579bc609a --- /dev/null +++ b/test/network/server/resource.rb @@ -0,0 +1,296 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/server/resource' +require 'base64' +require 'cgi' + +class TestResourceServer < Test::Unit::TestCase + include PuppetTest::ServerTest + + def verify_described(type, described) + described.each do |name, trans| + type.clear + obj = nil + assert_nothing_raised do + obj = trans.to_type + end + + assert(obj, "Could not create object") + assert_nothing_raised do + obj.retrieve + end + + if trans.type == :package + assert_equal(Puppet::Type.type(:package).defaultprovider.name, obj[:provider]) + end + end + type.clear + end + + def test_describe_file + # Make a file to describe + file = tempfile() + str = "yayness\n" + + server = nil + + assert_nothing_raised do + server = Puppet::Network::Server::Resource.new() + end + + # The first run we create the file on the copy, the second run + # the file is already there so the object should be in sync + 2.times do |i| + [ [nil], + [[:content, :mode], []], + [[], [:content]], + [[:content], [:mode]] + ].each do |ary| + retrieve = ary[0] || [] + ignore = ary[1] || [] + + File.open(file, "w") { |f| f.print str } + + result = nil + assert_nothing_raised do + result = server.describe("file", file, *ary) + end + + assert(result, "Could not retrieve file information") + + assert_instance_of(Puppet::TransObject, result) + + # Now we have to clear, so that the server's object gets removed + Puppet::Type.type(:file).clear + + # And remove the file, so we can verify it gets recreated + if i == 0 + File.unlink(file) + end + + object = nil + assert_nothing_raised do + object = result.to_type + end + + assert(object, "Could not create type") + + retrieve.each do |property| + assert(object.should(property), "Did not retrieve %s" % property) + end + + ignore.each do |property| + assert(! object.should(property), "Incorrectly retrieved %s" % property) + end + + if i == 0 + assert_events([:file_created], object) + else + assert_nothing_raised { + object.retrieve + } + assert(object.insync?, "Object was not in sync") + end + + assert(FileTest.exists?(file), "File did not get recreated") + + if i == 0 + if object.should(:content) + assert_equal(str, File.read(file), "File contents are not the same") + else + assert_equal("", File.read(file), "File content was incorrectly made") + end + end + if FileTest.exists? file + File.unlink(file) + end + end + end + end + + def test_describe_directory + # Make a file to describe + file = tempfile() + + server = nil + + assert_nothing_raised do + server = Puppet::Network::Server::Resource.new() + end + + [ [nil], + [[:ensure, :checksum, :mode], []], + [[], [:checksum]], + [[:ensure, :checksum], [:mode]] + ].each do |ary| + retrieve = ary[0] || [] + ignore = ary[1] || [] + + Dir.mkdir(file) + + result = nil + assert_nothing_raised do + result = server.describe("file", file, *ary) + end + + assert(result, "Could not retrieve file information") + + assert_instance_of(Puppet::TransObject, result) + + # Now we have to clear, so that the server's object gets removed + Puppet::Type.type(:file).clear + + # And remove the file, so we can verify it gets recreated + Dir.rmdir(file) + + object = nil + assert_nothing_raised do + object = result.to_type + end + + assert(object, "Could not create type") + + retrieve.each do |property| + assert(object.should(property), "Did not retrieve %s" % property) + end + + ignore.each do |property| + assert(! object.should(property), "Incorrectly retrieved %s" % property) + end + + assert_events([:directory_created], object) + + assert(FileTest.directory?(file), "Directory did not get recreated") + Dir.rmdir(file) + end + end + + def test_describe_alltypes + # Systems get pretty retarded, so I'm going to set the path to some fake + # data for ports + #Puppet::Type::ParsedType::Port.path = File.join(basedir, + # "test/data/types/ports/1") + #Puppet.err Puppet::Type::ParsedType::Port.path + server = nil + assert_nothing_raised do + server = Puppet::Network::Server::Resource.new() + end + + require 'etc' + + # Make the example schedules, for testing + Puppet::Type.type(:schedule).mkdefaultschedules + + Puppet::Type.eachtype do |type| + unless type.respond_to? :list + Puppet.warning "%s does not respond to :list" % type.name + next + end + next unless type.name == :package + Puppet.info "Describing each %s" % type.name + + # First do a listing from the server + bucket = nil + assert_nothing_raised { + bucket = server.list(type.name) + } + + #type.clear + + count = 0 + described = {} + bucket.each do |obj| + assert_instance_of(Puppet::TransObject, obj) + break if count > 5 + described[obj.name] = server.describe(obj.type, obj.name) + count += 1 + end + + verify_described(type, described) + + count = 0 + described = {} + Puppet.info "listing again" + type.list.each do |obj| + assert_instance_of(type, obj) + + break if count > 5 + trans = nil + assert_nothing_raised do + described[obj.name] = server.describe(type.name, obj.name) + end + + count += 1 + end + + if described.empty? + Puppet.notice "Got no example objects for %s" % type.name + end + + # We separate these, in case the list operation creates objects + verify_described(type, described) + end + end + + def test_apply + server = nil + assert_nothing_raised do + server = Puppet::Network::Server::Resource.new() + end + + file = tempfile() + str = "yayness\n" + + File.open(file, "w") { |f| f.print str } + + filetrans = nil + assert_nothing_raised { + filetrans = server.describe("file", file) + } + + Puppet::Type.type(:file).clear + + bucket = Puppet::TransBucket.new + bucket.type = "file" + bucket.push filetrans + + oldbucket = bucket.dup + File.unlink(file) + assert_nothing_raised { + server.apply(bucket) + } + + assert(FileTest.exists?(file), "File did not get recreated") + + # Now try it as a "nonlocal" server + server.local = false + yaml = nil + assert_nothing_raised { + yaml = Base64.encode64(YAML::dump(bucket)) + } + + Puppet::Type.type(:file).clear + File.unlink(file) + + if Base64.decode64(yaml) =~ /(.{20}Loglevel.{20})/ + Puppet.warning "YAML is broken on this machine" + return + end + # puts Base64.decode64(yaml) + objects = nil + assert_nothing_raised("Could not reload yaml") { + YAML::load(Base64.decode64(yaml)) + } + + # The server is supposed to accept yaml and execute it. + assert_nothing_raised { + server.apply(yaml) + } + assert(FileTest.exists?(file), "File did not get recreated from YAML") + end +end + +# $Id$ diff --git a/test/network/server/rights.rb b/test/network/server/rights.rb new file mode 100755 index 000000000..cee0fb9aa --- /dev/null +++ b/test/network/server/rights.rb @@ -0,0 +1,37 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/rights' + +class TestRights < Test::Unit::TestCase + include PuppetTest + + def test_rights + store = nil + assert_nothing_raised { + store = Puppet::Network::Rights.new + } + + assert(store, "Did not create store") + + assert_raise(ArgumentError, "Did not fail on unknown right") { + store.allowed?(:write, "host.madstop.com", "0.0.0.0") + } + + assert_nothing_raised { + store.newright(:write) + } + + assert(! store.allowed?(:write, "host.madstop.com", "0.0.0.0"), + "Defaulted to allowing access") + + assert_nothing_raised { + store[:write].info "This is a log message" + } + end +end + +# $Id$ + diff --git a/test/network/server/runner.rb b/test/network/server/runner.rb new file mode 100755 index 000000000..ce782298a --- /dev/null +++ b/test/network/server/runner.rb @@ -0,0 +1,106 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppet/network/server/runner' +require 'puppettest' + +class TestServerRunner < Test::Unit::TestCase + include PuppetTest + + def mkclient(file) + master = nil + client = nil + # create our master + assert_nothing_raised() { + # this is the default server setup + master = Puppet::Network::Server::Master.new( + :Manifest => file, + :UseNodes => false, + :Local => true + ) + } + + # and our client + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Master => master + ) + } + + client + end + + def test_runner + FileUtils.mkdir_p(Puppet[:statedir]) + Puppet[:ignoreschedules] = false + # Okay, make our manifest + file = tempfile() + created = tempfile() + File.open(file, "w") do |f| + f.puts %{ + class yayness { + file { "#{created}": ensure => file, schedule => weekly } + } + + include yayness + } + end + + client = mkclient(file) + + runner = nil + assert_nothing_raised { + runner = Puppet::Network::Server::Runner.new + } + # First: tags + # Second: ignore schedules true/false + # Third: background true/false + # Fourth: whether file should exist true/false + [ + ["with no backgrounding", + nil, true, true, true], + ["in the background", + nil, true, false, true], + ["with a bad tag", + ["coolness"], true, false, false], + ["with another bad tag", + "coolness", true, false, false], + ["with a good tag", + ["coolness", "yayness"], true, false, true], + ["with another good tag", + ["yayness"], true, false, true], + ["with a third good tag", + "yayness", true, false, true], + ["with no tags", + "", true, false, true], + ["not ignoring schedules", + nil, false, false, false], + ["ignoring schedules", + nil, true, false, true], + ].each do |msg, tags, ignore, fg, shouldexist| + if FileTest.exists?(created) + File.unlink(created) + end + assert_nothing_raised { + # Try it without backgrounding + runner.run(tags, ignore, fg) + } + + unless fg + Puppet.join + end + + if shouldexist + assert(FileTest.exists?(created), "File did not get created " + + msg) + else + assert(!FileTest.exists?(created), "File got created incorrectly " + + msg) + end + end + end +end + +# $Id$ + diff --git a/test/network/server/server.rb b/test/network/server/server.rb new file mode 100755 index 000000000..3e5e7b717 --- /dev/null +++ b/test/network/server/server.rb @@ -0,0 +1,197 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/server' + +if ARGV.length > 0 and ARGV[0] == "short" + $short = true +else + $short = false +end + +class TestServer < Test::Unit::TestCase + include PuppetTest::ServerTest + + # test that we can connect to the server + # we have to use fork here, because we apparently can't use threads + # to talk to other threads + def test_connect_with_fork + Puppet[:autosign] = true + serverpid, server = mk_status_server + + # create a status client, and verify it can talk + client = mk_status_client + + retval = nil + assert_nothing_raised() { + retval = client.status + } + assert_equal(1, retval) + end + + # similar to the last test, but this time actually run getconfig + def test_getconfig_with_fork + Puppet[:autosign] = true + serverpid = nil + + file = mktestmanifest() + + server = nil + # make our server again + assert_nothing_raised() { + server = Puppet::Network::Server.new( + :Port => @@port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :Master => { + :UseNodes => false, + :Manifest => file + }, + :Status => nil + } + ) + + } + serverpid = fork { + assert_nothing_raised() { + #trap(:INT) { server.shutdown; Kernel.exit! } + trap(:INT) { server.shutdown } + server.start + } + } + @@tmppids << serverpid + + client = nil + + # and then start a masterclient + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Server => "localhost", + :Port => @@port + ) + } + retval = nil + + # and run getconfig a couple of times + assert_nothing_raised() { + retval = client.getconfig + } + + # Try it again, just for kicks + assert_nothing_raised() { + retval = client.getconfig + } + end + + def test_setpidfile_setting + Puppet[:setpidfile] = false + server = nil + assert_nothing_raised() { + server = Puppet::Network::Server.new( + :Port => @@port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :Status => nil + } + ) + + } + + assert_nothing_raised { + server.setpidfile + } + + assert(! FileTest.exists?(server.pidfile), "PID file was created") + Puppet[:setpidfile] = true + + assert_nothing_raised { + server.setpidfile + } + assert(FileTest.exists?(server.pidfile), "PID file was not created") + end + + + # Test that a client whose cert has been revoked really can't connect + def test_certificate_revocation + Puppet[:autosign] = true + + serverpid, server = mk_status_server + + client = mk_status_client + + status = nil + assert_nothing_raised() { + status = client.status + } + assert_equal(1, status) + client.shutdown + + # Revoke the client's cert + ca = Puppet::SSLCertificates::CA.new() + fqdn = client.fqdn + ca.revoke(ca.getclientcert(fqdn)[0].serial) + + # Restart the server + @@port += 1 + Puppet[:autosign] = false + kill_and_wait(serverpid, server.pidfile) + serverpid, server = mk_status_server + + client = mk_status_client + # This time the client should be denied + assert_raise(Puppet::Network::NetworkClientError) { + client.status + } + end + + def mk_status_client + client = nil + # Otherwise, the client initalization will trip over itself + # since elements created in the last run are still around + Puppet::Type::allclear + + assert_nothing_raised() { + client = Puppet::Network::Client::StatusClient.new( + :Server => "localhost", + :Port => @@port + ) + } + client + end + + def mk_status_server + server = nil + assert_nothing_raised() { + server = Puppet::Network::Server.new( + :Port => @@port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :Status => nil + } + ) + + } + pid = fork { + assert_nothing_raised() { + trap(:INT) { server.shutdown } + server.start + } + } + @@tmppids << pid + [pid, server] + end + + def kill_and_wait(pid, file) + %x{kill -INT #{pid} 2>/dev/null} + count = 0 + while count < 30 && File::exist?(file) + count += 1 + sleep(1) + end + assert(count < 30, "Killing server #{pid} failed") + end +end + +# $Id$ |
