diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-09-15 20:16:21 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-09-15 20:16:21 +0000 |
| commit | bf701dcb819bf06449557b2ef6b2adf207a78586 (patch) | |
| tree | 7f6ed24c4f0653e9b8bf49494d1414dab9f3d5de | |
| parent | 0c97bb13d4b1aefda9768c000c542b3ddfc92b04 (diff) | |
| download | puppet-bf701dcb819bf06449557b2ef6b2adf207a78586.tar.gz puppet-bf701dcb819bf06449557b2ef6b2adf207a78586.tar.xz puppet-bf701dcb819bf06449557b2ef6b2adf207a78586.zip | |
adding extra checks to make sure networking is secure, and refactoring a heckuva lot of test
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@671 980ebf18-57e1-0310-9a29-db15c13687c0
| -rwxr-xr-x | bin/puppetd | 6 | ||||
| -rw-r--r-- | examples/code/snippets/failmissingexecpath.pp (renamed from examples/code/snippets/missingexecpath.pp) | 0 | ||||
| -rw-r--r-- | lib/puppet.rb | 4 | ||||
| -rw-r--r-- | lib/puppet/client.rb | 132 | ||||
| -rw-r--r-- | lib/puppet/parser/ast.rb | 6 | ||||
| -rw-r--r-- | lib/puppet/server.rb | 2 | ||||
| -rw-r--r-- | lib/puppet/server/servlet.rb | 27 | ||||
| -rw-r--r-- | lib/puppet/type/pfile.rb | 3 | ||||
| -rw-r--r-- | test/client/tc_client.rb | 139 | ||||
| -rwxr-xr-x | test/executables/tc_puppetbin.rb | 26 | ||||
| -rwxr-xr-x | test/executables/tc_puppetca.rb | 15 | ||||
| -rwxr-xr-x | test/executables/tc_puppetd.rb | 91 | ||||
| -rwxr-xr-x | test/executables/tc_puppetmasterd.rb | 115 | ||||
| -rwxr-xr-x | test/language/tc_snippets.rb | 2 | ||||
| -rw-r--r-- | test/puppettest.rb | 197 | ||||
| -rw-r--r-- | test/server/tc_bucket.rb | 273 | ||||
| -rw-r--r-- | test/server/tc_ca.rb | 114 | ||||
| -rwxr-xr-x | test/server/tc_fileserver.rb | 172 | ||||
| -rw-r--r-- | test/server/tc_master.rb | 72 | ||||
| -rw-r--r-- | test/server/tc_server.rb | 272 | ||||
| -rwxr-xr-x | test/types/tc_filesources.rb | 15 |
21 files changed, 781 insertions, 902 deletions
diff --git a/bin/puppetd b/bin/puppetd index 90ffbe816..e66083d3c 100755 --- a/bin/puppetd +++ b/bin/puppetd @@ -196,7 +196,11 @@ if bg end client.daemonize end -#client.start + +# now set up the network client with the certs, now that we have them +client.setcerts + +# and then retrieve and apply our configuration client.getconfig client.apply diff --git a/examples/code/snippets/missingexecpath.pp b/examples/code/snippets/failmissingexecpath.pp index 3f43be325..3f43be325 100644 --- a/examples/code/snippets/missingexecpath.pp +++ b/examples/code/snippets/failmissingexecpath.pp diff --git a/lib/puppet.rb b/lib/puppet.rb index 0c5adfdcd..7cd1212fa 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -101,6 +101,10 @@ module Puppet @defaults[:puppetvar] = File.expand_path("~/.puppet/var") end + def self.clear + @@config = Hash.new(false) + end + # configuration parameter access and stuff def self.[](param) if param.is_a?(String) diff --git a/lib/puppet/client.rb b/lib/puppet/client.rb index 38b9fa7fa..679db2c51 100644 --- a/lib/puppet/client.rb +++ b/lib/puppet/client.rb @@ -47,6 +47,11 @@ module Puppet #Puppet.info "cert is %s" % @http.cert begin call("%s.%s" % [namespace, method.to_s],*args) + rescue OpenSSL::SSL::SSLError => detail + Puppet.err "Could not call %s.%s: Untrusted certificates" % + [namespace, method] + raise NetworkClientError, + "Certificates were not trusted" rescue XMLRPC::FaultException => detail Puppet.err "Could not call %s.%s: %s" % [namespace, method, detail.faultString] @@ -61,16 +66,26 @@ module Puppet } } - [:key, :cert, :ca_file].each { |method| - setmethod = method.to_s + "=" - #self.send(:define_method, method) { - # @http.send(method) - #} - self.send(:define_method, setmethod) { |*args| - Puppet.debug "Setting %s" % method - @http.send(setmethod, *args) - } - } + def ca_file=(cafile) + @http.ca_file = cafile + store = OpenSSL::X509::Store.new + cacert = OpenSSL::X509::Certificate.new( + File.read(cafile) + ) + store.add_cert(cacert) + store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT + @http.cert_store = store + end + + def cert=(cert) + Puppet.info "Adding certificate" + @http.cert = cert + @http.verify_mode = OpenSSL::SSL::VERIFY_PEER + end + + def key=(key) + @http.key = key + end def initialize(hash) hash[:Path] ||= "/RPC2" @@ -89,23 +104,17 @@ module Puppet ) if hash[:Certificate] - @http.cert = hash[:Certificate] + self.cert = hash[:Certificate] + else + Puppet.err "No certificate; running with reduced functionality." end if hash[:Key] - @http.key = hash[:Key] + self.key = hash[:Key] end if hash[:CAFile] - @http.ca_file = hash[:CAFile] - store = OpenSSL::X509::Store.new - cacert = OpenSSL::X509::Certificate.new( - File.read(hash[:CAFile]) - ) - store.add_cert(cacert) - store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT - @http.cert_store = store - @http.verify_mode = OpenSSL::SSL::VERIFY_NONE + self.ca_file = hash[:CAFile] end # from here, i need to add the key, cert, and ca cert @@ -141,14 +150,13 @@ module Puppet end end + # unless we have a driver, we're a local client and we can't add + # certs anyway, so it doesn't matter unless @driver return true end - Puppet.info "setting cert and key and such" - @driver.cert = @cert - @driver.key = @key - @driver.ca_file = @cacertfile + self.setcerts end def initialize(hash) @@ -196,6 +204,12 @@ module Puppet end end + def setcerts + @driver.cert = @cert + @driver.key = @key + @driver.ca_file = @cacertfile + end + class MasterClient < Puppet::Client @drivername = :Master @@ -217,8 +231,6 @@ module Puppet raise Puppet::Error, "Cannot apply; objects not defined" end - # XXX this is kind of a problem; if the user changes the state file - # after this, then we have to reload the file and everything... begin Puppet::Storage.init Puppet::Storage.load @@ -398,6 +410,72 @@ module Puppet end end + # unlike the other client classes (again, this design sucks) this class + # is basically just a proxy class -- it calls its methods on the driver + # and that's about it + class ProxyClient < Puppet::Client + def self.mkmethods + interface = @handler.interface + namespace = interface.prefix + + interface.methods.each { |ary| + method = ary[0] + Puppet.debug "%s: defining %s.%s" % [self, namespace, method] + self.send(:define_method,method) { |*args| + begin + @driver.send(method, *args) + rescue XMLRPC::FaultException => detail + Puppet.err "Could not call %s.%s: %s" % + [namespace, method, detail.faultString] + raise NetworkClientError, + "XMLRPC Error: %s" % detail.faultString + end + } + } + end + end + + class FileClient < Puppet::Client::ProxyClient + @drivername = :FileServer + + # set up the appropriate interface methods + @handler = Puppet::Server::FileServer + + self.mkmethods + + def initialize(hash = {}) + if hash.include?(:FileServer) + unless hash[:FileServer].is_a?(Puppet::Server::FileServer) + raise Puppet::DevError, "Must pass an actual FS object" + end + end + + super(hash) + end + end + + class CAClient < Puppet::Client::ProxyClient + @drivername = :CA + + # set up the appropriate interface methods + @handler = Puppet::Server::CA + self.mkmethods + + def initialize(hash = {}) + if hash.include?(:CA) + hash[:CA] = Puppet::Server::CA.new() + end + + super(hash) + end + end + + class StatusClient < Puppet::Client::ProxyClient + # set up the appropriate interface methods + @handler = Puppet::Server::ServerStatus + self.mkmethods + end + end #--------------------------------------------------------------- end diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb index 4c2f699c0..1918f60e9 100644 --- a/lib/puppet/parser/ast.rb +++ b/lib/puppet/parser/ast.rb @@ -11,6 +11,8 @@ module Puppet class ASTError < RuntimeError; end #--------------------------------------------------------------- class AST + Puppet.setdefault(:typecheck, true) + Puppet.setdefault(:paramcheck, true) attr_accessor :line, :file, :parent @@pink = "[0;31m" @@ -482,6 +484,8 @@ module Puppet # for types objtype = @type.value + # This will basically always be on, but I wanted to make it at + # least simple to turn off if it came to that if Puppet[:typecheck] builtin = false begin @@ -492,6 +496,8 @@ module Puppet if builtin # we're a builtin type #Puppet.debug "%s is a builtin type" % objtype + # like :typecheck, this always defaults to on, but + # at least it's easy to turn off if necessary if Puppet[:paramcheck] @params.each { |param| #p self.name diff --git a/lib/puppet/server.rb b/lib/puppet/server.rb index 6c9dbf37b..15b27f849 100644 --- a/lib/puppet/server.rb +++ b/lib/puppet/server.rb @@ -76,7 +76,7 @@ module Puppet hash[:SSLStartImmediately] = true hash[:SSLEnable] = true hash[:SSLCACertificateFile] = @cacertfile - hash[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_NONE + hash[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER hash[:SSLCertName] = nil super(hash) diff --git a/lib/puppet/server/servlet.rb b/lib/puppet/server/servlet.rb index 4c45ebc62..2bc2dffc1 100644 --- a/lib/puppet/server/servlet.rb +++ b/lib/puppet/server/servlet.rb @@ -15,7 +15,20 @@ class Server end def authorize(request, method) - true + if request.client_cert + Puppet.info "Allowing %s(%s) trusted access to %s" % + [request.peeraddr[2], request.peeraddr[3], method] + return true + else + if method =~ /^puppetca\./ + Puppet.notice "Allowing %s(%s) untrusted access to CA methods" % + [request.peeraddr[2], request.peeraddr[3]] + else + Puppet.err "Unauthenticated client %s(%s) cannot call %s" % + [request.peeraddr[2], request.peeraddr[3], method] + return false + end + end end def initialize(server, handlers) @@ -79,12 +92,12 @@ class Server ) end - if request.client_cert - Puppet.info "client cert is %s" % request.client_cert - end - if request.server_cert - #Puppet.info "server cert is %s" % @request.server_cert - end + #if request.client_cert + # Puppet.info "client cert is %s" % request.client_cert + #end + #if request.server_cert + # Puppet.info "server cert is %s" % @request.server_cert + #end #p @request begin super diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb index 4ae9cb97a..df22c59b2 100644 --- a/lib/puppet/type/pfile.rb +++ b/lib/puppet/type/pfile.rb @@ -1305,7 +1305,8 @@ module Puppet if uri.port args[:Port] = uri.port end - sourceobj.server = Puppet::NetworkClient.new(args) + #sourceobj.server = Puppet::NetworkClient.new(args) + sourceobj.server = Puppet::Client::FileClient.new(args) tmp = uri.path if tmp =~ %r{^/(\w+)} diff --git a/test/client/tc_client.rb b/test/client/tc_client.rb index 2c67c35c8..feaa24184 100644 --- a/test/client/tc_client.rb +++ b/test/client/tc_client.rb @@ -12,71 +12,30 @@ require 'puppettest.rb' # $Id$ -class TestClient < Test::Unit::TestCase - def setup - Puppet[:loglevel] = :debug if __FILE__ == $0 - @@tmpfiles = [] - @@tmppids = [] - end - - def teardown - Puppet::Type.allclear - @@tmpfiles.each { |f| - if FileTest.exists?(f) - system("rm -rf %s" % f) - end - } - - @@tmppids.each { |pid| - %x{kill -INT #{pid} 2>/dev/null} - } - end - +class TestClient < ServerTest + # a single run through of connect, auth, etc. def test_sslInitWithAutosigningLocalServer + # autosign everything, for simplicity Puppet[:autosign] = true - Puppet[:ssldir] = "/tmp/puppetclientcertests" - @@tmpfiles.push Puppet[:ssldir] - @@tmpfiles.push "/tmp/puppetclienttesting" - file = "/tmp/testingmanifest.pp" - File.open(file, "w") { |f| - f.puts ' -file { "/tmp/puppetclienttesting": create => true, mode => 755 } -' - } - @@tmpfiles << file - port = 8085 + # create a server to which to connect + mkserver() - server = nil - assert_nothing_raised { - server = Puppet::Server.new( - :Port => port, - :Handlers => { - :CA => {}, # so that certs autogenerate - :Master => { - :File => file, - }, - } - ) - } - - spid = fork { - trap(:INT) { server.shutdown } - server.start - } - - @@tmppids << spid + # create our client client = nil assert_nothing_raised { client = Puppet::Client::MasterClient.new( :Server => "localhost", - :Port => port + :Port => @@port ) } + + # get our certs assert_nothing_raised { client.initcerts } + # make sure all of our cert files exist certfile = File.join(Puppet[:certdir], [client.fqdn, "pem"].join(".")) keyfile = File.join(Puppet[:privatekeydir], [client.fqdn, "pem"].join(".")) publickeyfile = File.join(Puppet[:publickeydir], [client.fqdn, "pem"].join(".")) @@ -85,18 +44,94 @@ file { "/tmp/puppetclienttesting": create => true, mode => 755 } assert(File.exists?(certfile)) assert(File.exists?(publickeyfile)) + # verify we can retrieve the configuration assert_nothing_raised("Client could not retrieve configuration") { client.getconfig } + # and apply it assert_nothing_raised("Client could not apply configuration") { client.apply } - assert(FileTest.exists?("/tmp/puppetclienttesting"), + # and verify that it did what it was supposed to + assert(FileTest.exists?(@createdfile), "Applied file does not exist") end + + # here we create two servers; we + def test_zzfailureWithUntrustedCerts + Puppet[:autosign] = true + + # create a pair of clients with no certs + nonemaster = nil + assert_nothing_raised { + nonemaster = Puppet::Client::MasterClient.new( + :Server => "localhost", + :Port => @@port + ) + } + + nonebucket = nil + assert_nothing_raised { + nonebucket = Puppet::Client::Dipper.new( + :Server => "localhost", + :Port => @@port + ) + } + + # create a ca so we can create a set of certs + ca = nil + assert_nothing_raised { + ca = Puppet::Client::CAClient.new(:CA => true, :Local => true) + ca.requestcert + } + + # initialize our clients with this set of certs + certmaster = nil + assert_nothing_raised { + certmaster = Puppet::Client::MasterClient.new( + :Server => "localhost", + :Port => @@port + ) + } + + certbucket = nil + assert_nothing_raised { + certbucket = Puppet::Client::Dipper.new( + :Server => "localhost", + :Port => @@port + ) + } + + # clean up the existing certs, so the server creates a new CA + system("rm -rf %s" % Puppet[:ssldir]) + + # start our server + mkserver + + # now verify that our client cannot do non-cert operations + # because its certs are signed by a different CA + assert_raise(Puppet::NetworkClientError, + "Client was allowed to call getconfig with no certs") { + nonemaster.getconfig + } + assert_raise(Puppet::NetworkClientError, + "Client was allowed to call getconfig with untrusted certs") { + certmaster.getconfig + } + + assert_raise(Puppet::NetworkClientError, + "Client was allowed to call backup with no certs") { + nonebucket.backup("/etc/passwd") + } + assert_raise(Puppet::NetworkClientError, + "Client was allowed to call backup with untrusted certs") { + certbucket.backup("/etc/passwd") + } + end + # disabled because the server needs to have its certs in place # in order to start at all # i don't think this test makes much sense anyway diff --git a/test/executables/tc_puppetbin.rb b/test/executables/tc_puppetbin.rb index decb46e9b..158666f47 100755 --- a/test/executables/tc_puppetbin.rb +++ b/test/executables/tc_puppetbin.rb @@ -21,19 +21,7 @@ libdirs = $:.find_all { |dir| } ENV["RUBYLIB"] = libdirs.join(":") -class TestPuppetBin < Test::Unit::TestCase - def setup - @@tmpfiles = [] - end - - def teardown - @@tmpfiles.each { |f| - if FileTest.exists?(f) - system("rm -rf %s" % f) - end - } - end - +class TestPuppetBin < ServerTest def test_version output = nil assert_nothing_raised { @@ -43,14 +31,7 @@ class TestPuppetBin < Test::Unit::TestCase end def test_execution - file = "/tmp/puppetbintestingmanifest.pp" - File.open(file, "w") { |f| - f.puts ' -file { "/tmp/puppetbintesting": create => true, mode => 755 } -' - } - - @@tmpfiles << file + file = mktestmanifest() @@tmpfiles << "/tmp/puppetbintesting" output = nil @@ -59,7 +40,6 @@ file { "/tmp/puppetbintesting": create => true, mode => 755 } } assert($? == 0, "Puppet exited with code %s" % $?.to_i) - assert(FileTest.exists?("/tmp/puppetbintesting"), - "Failed to create config'ed file") + assert(FileTest.exists?(@createdfile), "Failed to create config'ed file") end end diff --git a/test/executables/tc_puppetca.rb b/test/executables/tc_puppetca.rb index 6f799c670..1ef3203e1 100755 --- a/test/executables/tc_puppetca.rb +++ b/test/executables/tc_puppetca.rb @@ -21,20 +21,7 @@ libdirs = $:.find_all { |dir| } ENV["RUBYLIB"] = libdirs.join(":") -class TestPuppetCA < Test::Unit::TestCase - def setup - Puppet[:loglevel] = :debug if __FILE__ == $0 - @@tmpfiles = [] - end - - def teardown - @@tmpfiles.flatten.each { |file| - if File.exists? file - system("rm -rf %s" % file) - end - } - end - +class TestPuppetCA < ServerTest def mkcert(hostname) cert = nil assert_nothing_raised { diff --git a/test/executables/tc_puppetd.rb b/test/executables/tc_puppetd.rb index 238133856..bc78e6896 100755 --- a/test/executables/tc_puppetd.rb +++ b/test/executables/tc_puppetd.rb @@ -22,96 +22,49 @@ libdirs = $:.find_all { |dir| } ENV["RUBYLIB"] = libdirs.join(":") -class TestPuppetDExe < Test::Unit::TestCase - def setup - Puppet[:loglevel] = :debug if __FILE__ == $0 - @@tmpfiles = [] - @@tmppids = [] - end - - def teardown - @@tmpfiles.flatten.each { |file| - if File.exists? file - system("rm -rf %s" % file) - end - } - - @@tmppids.each { |pid| - %x{kill #{pid} 2>/dev/null} - } - stopmaster - end - - def startmaster(file, port) - output = nil - ssldir = "/tmp/puppetmasterdpuppetdssldirtesting" - @@tmpfiles << ssldir - assert_nothing_raised { - output = %x{puppetmasterd --port #{port} -a --ssldir #{ssldir} --manifest #{file}}.chomp - } - assert($? == 0, "Puppetmasterd return status was %s" % $?) - @@tmppids << $?.pid - assert_equal("", output) - end +class TestPuppetDExe < ExeTest + def test_normalstart + # start the master + file = startmasterd - def stopmaster - ps = Facter["ps"].value || "ps -ef" + # create the client + client = Puppet::Client.new(:Server => "localhost", :Port => @@port) - pid = nil - %x{#{ps}}.chomp.split(/\n/).each { |line| - if line =~ /puppetmasterd/ - ary = line.split(" ") - pid = ary[1].to_i - end - } - if pid - assert_nothing_raised { - Process.kill("-TERM", pid) - } - end - end + # make a new fqdn + fqdn = client.fqdn.sub(/^\w+\./, "testing.") - def test_normalstart - file = "/tmp/testingmanifest.pp" - mkfile = "/tmp/puppetdtesting" - File.open(file, "w") { |f| - f.puts %{ -file { "#{mkfile}": create => true, mode => 755 } -} - } + cmd = "puppetd" + cmd += " --verbose" + cmd += " --fqdn %s" % fqdn + cmd += " --port %s" % @@port + cmd += " --ssldir %s" % Puppet[:ssldir] + cmd += " --server localhost" - @@tmpfiles << file - @@tmpfiles << mkfile - port = 8235 - startmaster(file, port) - output = nil - ssldir = "/tmp/puppetdssldirtesting" - @@tmpfiles << ssldir - client = Puppet::Client.new(:Server => "localhost") - fqdn = client.fqdn.sub(/^\w+\./, "testing.") + # and verify our daemon runs assert_nothing_raised { - output = %x{puppetd --verbose --fqdn #{fqdn} --port #{port} --ssldir #{ssldir} --server localhost}.chomp + output = %x{#{cmd}}.chomp } sleep 1 assert($? == 0, "Puppetd exited with code %s" % $?) #puts output #assert_equal("", output, "Puppetd produced output %s" % output) - assert(FileTest.exists?(mkfile), + assert(FileTest.exists?(@createdfile), "Failed to create config'ed file") # now verify that --noop works - File.unlink(mkfile) + File.unlink(@createdfile) + cmd += " --noop" assert_nothing_raised { - output = %x{puppetd --noop --fqdn #{fqdn} --port #{port} --ssldir #{ssldir} --server localhost}.chomp + output = %x{#{cmd}}.chomp } sleep 1 assert($? == 0, "Puppetd exited with code %s" % $?) - assert(! FileTest.exists?(mkfile), + assert(! FileTest.exists?(@createdfile), "Noop created config'ed file") - stopmaster + stopmasterd end end diff --git a/test/executables/tc_puppetmasterd.rb b/test/executables/tc_puppetmasterd.rb index 6d4a58b7b..9367cce80 100755 --- a/test/executables/tc_puppetmasterd.rb +++ b/test/executables/tc_puppetmasterd.rb @@ -14,16 +14,7 @@ require 'facter' # $Id$ -# ok, we have to add the bin directory to our search path -ENV["PATH"] += ":" + File.join($puppetbase, "bin") - -# and then the library directories -libdirs = $:.find_all { |dir| - dir =~ /puppet/ or dir =~ /\.\./ -} -ENV["RUBYLIB"] = libdirs.join(":") - -class TestPuppetMasterD < Test::Unit::TestCase +class TestPuppetMasterD < ExeTest def getcerts include Puppet::Daemon if self.readcerts @@ -33,102 +24,68 @@ class TestPuppetMasterD < Test::Unit::TestCase end end - def setup - if __FILE__ == $0 - Puppet[:loglevel] = :debug - end - @@tmpfiles = [] - @port = 8320 - end + # start the daemon and verify it responds and such + def test_normalstart + startmasterd - def startmasterd(args) - output = nil - cmd = "puppetmasterd %s" % args - #if Puppet[:debug] - # Puppet.debug "turning daemon debugging on" - # cmd += " --debug" - #end assert_nothing_raised { - output = %x{puppetmasterd --port #{@port} #{args}}.chomp + socket = TCPSocket.new("127.0.0.1", @@port) + socket.close } - assert($? == 0, "Puppetmasterd exit status was %s" % $?) - assert_equal("", output, "Puppetmasterd produced output %s" % output) - end - def stopmasterd(running = true) - ps = Facter["ps"].value || "ps -ef" - - pid = nil - %x{#{ps}}.chomp.split(/\n/).each { |line| - if line =~ /ruby.+puppetmasterd/ - next if line =~ /tc_/ # skip the test script itself - ary = line.split(" ") - pid = ary[1].to_i - end + client = nil + assert_nothing_raised() { + client = Puppet::Client::StatusClient.new( + :Server => "localhost", + :Port => @@port + ) } - # we default to mandating that it's running, but teardown - # doesn't require that - if running or pid - assert(pid) + # set our client up to auto-sign + assert(Puppet[:autosign] =~ /^#{File::SEPARATOR}/, + "Autosign is set to %s, not a file" % Puppet[:autosign]) - assert_nothing_raised { - Process.kill("-INT", pid) - } - end - end - - def teardown - @@tmpfiles.flatten.each { |file| - if File.exists?(file) - system("rm -rf %s" % file) - end + FileUtils.mkdir_p(File.dirname(Puppet[:autosign])) + File.open(Puppet[:autosign], "w") { |f| + f.puts client.fqdn } - stopmasterd(false) - end - - def test_normalstart - file = File.join($puppetbase, "examples", "code", "head") - startmasterd("--manifest #{file}") - - assert_nothing_raised { - socket = TCPSocket.new("127.0.0.1", @port) - socket.close - } + retval = nil - client = nil + # init the client certs assert_nothing_raised() { - client = XMLRPC::Client.new("localhost", "/RPC2", @port, - nil, nil, nil, nil, true, 5) + client.initcerts } - retval = nil + # call status assert_nothing_raised() { - retval = client.call("status.status", "") + retval = client.status } assert_equal(1, retval, "Status.status return value was %s" % retval) - facts = {} - Facter.each { |p,v| - facts[p] = v + + # this client shoulduse the same certs + assert_nothing_raised() { + client = Puppet::Client::MasterClient.new( + :Server => "localhost", + :Port => @@port + ) } - textfacts = CGI.escape(Marshal::dump(facts)) assert_nothing_raised() { #Puppet.notice "calling status" #retval = client.call("status.status", "") - retval = client.call("puppetmaster.getconfig", textfacts) + retval = client.getconfig } objects = nil - assert_nothing_raised { - Marshal::load(CGI.unescape(retval)) - } + assert_instance_of(Puppet::TransBucket, retval, + "Retrieved non-transportable object") stopmasterd end + # verify that we can run puppetmasterd in parse-only mode def test_parseonly - file = File.join($puppetbase, "examples", "code", "head") - startmasterd("--parseonly --manifest #{file}") + startmasterd("--parseonly") + sleep(1) pid = nil ps = Facter["ps"].value || "ps -ef" diff --git a/test/language/tc_snippets.rb b/test/language/tc_snippets.rb index a37404844..deb5392cf 100755 --- a/test/language/tc_snippets.rb +++ b/test/language/tc_snippets.rb @@ -327,7 +327,7 @@ class TestSnippets < TestPuppet "File %s is not 755" % file) end - def snippet_missingexecpath(trans) + def snippet_failmissingexecpath(trans) file = "/tmp/exectesting1" execfile = "/tmp/execdisttesting" @@tmpfiles << file diff --git a/test/puppettest.rb b/test/puppettest.rb index 3eb2c22b9..3b48a860f 100644 --- a/test/puppettest.rb +++ b/test/puppettest.rb @@ -1,8 +1,6 @@ # $Id$ require 'test/unit' -$VERBOSE = 1 - class TestPuppet < Test::Unit::TestCase def newcomp(name,*ary) comp = Puppet::Type::Component.new( @@ -16,42 +14,88 @@ class TestPuppet < Test::Unit::TestCase def setup if $0 =~ /tc_.+\.rb/ Puppet[:loglevel] = :debug + $VERBOSE = 1 else Puppet[:logdest] = "/dev/null" Puppet[:httplog] = "/dev/null" end @configpath = File.join(tmpdir, self.class.to_s + "configdir") - @oldconf = Puppet[:puppetconf] Puppet[:puppetconf] = @configpath - @oldvar = Puppet[:puppetvar] Puppet[:puppetvar] = @configpath + unless File.exists?(@configpath) + Dir.mkdir(@configpath) + end + @@tmpfiles = [@configpath] + @@tmppids = [] + end + + + def spin + if Puppet[:debug] + return + end + @modes = %w{| / - \\} + unless defined? @mode + @mode = 0 + end + + $stderr.print "%s" % @modes[@mode] + if @mode == @modes.length - 1 + @mode = 0 + else + @mode += 1 + end + $stderr.flush + end + + # stop any services that might be hanging around + def stopservices + if stype = Puppet::Type.type(:service) + stype.each { |service| + service[:running] = false + service.sync + } + end end def teardown + stopservices @@tmpfiles.each { |file| if FileTest.exists?(file) system("chmod -R 755 %s" % file) system("rm -rf %s" % file) - Puppet.err "Removing %s" % file - else - Puppet.err "%s does not exist" % file end } @@tmpfiles.clear + + @@tmppids.each { |pid| + %x{kill -INT #{pid} 2>/dev/null} + } + @@tmppids.clear Puppet::Type.allclear + Puppet.clear end def tempfile - File.join(self.tmpdir(), "puppetestfile%s" % rand(100)) + f = File.join(self.tmpdir(), self.class.to_s + "testfile" + rand(1000).to_s) + @@tmpfiles << f + return f + end + + def testdir + d = File.join(self.tmpdir(), self.class.to_s + "testdir" + rand(1000).to_s) + @@tmpfiles << d + return d end def tmpdir unless defined? @tmpdir and @tmpdir @tmpdir = case Facter["operatingsystem"].value when "Darwin": "/private/tmp" + when "SunOS": "/var/tmp" else "/tmp" end @@ -97,6 +141,132 @@ class TestPuppet < Test::Unit::TestCase end end + +class ServerTest < TestPuppet + def setup + if defined? @@port + @@port += 1 + else + @@port = 8085 + end + + super + end + + # create a simple manifest that just creates a file + def mktestmanifest + file = File.join(Puppet[:puppetconf], "%ssite.pp" % (self.class.to_s + "test")) + @createdfile = File.join(tmpdir(), self.class.to_s + "servermanifesttesting") + + File.open(file, "w") { |f| + f.puts "file { \"%s\": create => true, mode => 755 }\n" % @createdfile + } + + @@tmpfiles << @createdfile + @@tmpfiles << file + + return file + end + + # create a server, forked into the background + def mkserver(handlers = nil) + # our default handlers + unless handlers + handlers = { + :CA => {}, # so that certs autogenerate + :Master => { + :File => mktestmanifest(), + }, + } + end + + # then create the actual server + server = nil + assert_nothing_raised { + server = Puppet::Server.new( + :Port => @@port, + :Handlers => handlers + ) + } + + # fork it + spid = fork { + trap(:INT) { server.shutdown } + server.start + } + + # and store its pid for killing + @@tmppids << spid + + # give the server a chance to do its thing + sleep 1 + return spid + end + +end + +class ExeTest < ServerTest + unless ENV["PATH"] =~ /puppet/ + # ok, we have to add the bin directory to our search path + ENV["PATH"] += ":" + File.join($puppetbase, "bin") + + # and then the library directories + libdirs = $:.find_all { |dir| + dir =~ /puppet/ or dir =~ /\.\./ + } + ENV["RUBYLIB"] = libdirs.join(":") + end + + def startmasterd(args = "") + output = nil + + manifest = mktestmanifest() + args += " --manifest %s" % manifest + args += " --ssldir %s" % Puppet[:ssldir] + args += " --port %s" % @@port + args += " --autosign" + + cmd = "puppetmasterd %s" % args + + + assert_nothing_raised { + output = %x{#{cmd}}.chomp + } + assert($? == 0, "Puppetmasterd exit status was %s" % $?) + assert_equal("", output, "Puppetmasterd produced output %s" % output) + + return manifest + end + + def stopmasterd(running = true) + ps = Facter["ps"].value || "ps -ef" + + pid = nil + %x{#{ps}}.chomp.split(/\n/).each { |line| + if line =~ /ruby.+puppetmasterd/ + next if line =~ /tc_/ # skip the test script itself + ary = line.split(" ") + pid = ary[1].to_i + end + } + + # we default to mandating that it's running, but teardown + # doesn't require that + if running or pid + assert(pid) + + assert_nothing_raised { + Process.kill("-INT", pid) + } + end + end + + def teardown + stopmasterd(false) + super + end +end + unless defined? PuppetTestSuite $:.unshift File.join(Dir.getwd, '../lib') @@ -131,10 +301,14 @@ unless defined? PuppetTestSuite end end + # a list of files that we can parse for testing def textfiles - textdir = File.join($puppetbase,"examples","code") - # only parse this one file now - yield File.join(textdir,"head") + textdir = File.join($puppetbase,"examples","code", "snippets") + Dir.entries(textdir).reject { |f| + f =~ /^\./ or f =~ /fail/ + }.each { |f| + yield File.join(textdir, f) + } end def failers @@ -384,5 +558,4 @@ unless defined? PuppetTestSuite end end - end diff --git a/test/server/tc_bucket.rb b/test/server/tc_bucket.rb index 813ea7a61..264a8da13 100644 --- a/test/server/tc_bucket.rb +++ b/test/server/tc_bucket.rb @@ -12,19 +12,94 @@ require 'test/unit' require 'puppettest.rb' require 'base64' -# $Id$ -class TestBucket < Test::Unit::TestCase +class TestBucket < ServerTest + # run through all of the files and exercise the filebucket methods + def checkfiles(client) + files = filelist() + + # iterate across all of the files + files.each { |file| + spin + name = File.basename(file) + tmppath = File.join(tmpdir,name) + + # copy the files to our tmp directory so we can modify them... + File.open(tmppath,File::WRONLY|File::TRUNC|File::CREAT) { |wf| + File.open(file) { |rf| + wf.print(rf.read) + } + } + + # make sure the copy worked + assert(FileTest.exists?(tmppath)) + + # backup both the orig file and the tmp file + osum = nil + tsum = nil + nsum = nil + spin + assert_nothing_raised { + osum = client.backup(file) + } + spin + assert_nothing_raised { + tsum = client.backup(tmppath) + } + + # verify you got the same sum back for both + assert(tsum == osum) + + # modify our tmp file + File.open(tmppath,File::WRONLY|File::TRUNC) { |wf| + wf.print "This is some test text\n" + } + + # back it up + spin + assert_nothing_raised { + #STDERR.puts("backing up %s" % tmppath) if $debug + nsum = client.backup(tmppath) + } + + # and verify the sum changed + assert(tsum != nsum) + + # restore the orig + spin + assert_nothing_raised { + nsum = client.restore(tmppath,tsum) + } + + # and verify it actually got restored + spin + contents = File.open(tmppath) { |rf| + #STDERR.puts("reading %s" % tmppath) if $debug + rf.read + } + csum = Digest::MD5.hexdigest(contents) + assert(tsum == csum) + } + end + + # a list of files that should be on the system + # just something to test moving files around def filelist - files = [] - #/etc/passwd /etc/syslog.conf /etc/hosts + if defined? @files + return @files + else + @files = [] + end + %w{ - who /tmp/bigfile sh uname /etc/passwd /etc/syslog.conf /etc/hosts + who bash vim 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 + @files.push file end else + # else if it's unqualified, look for it in our path begin path = %x{which #{file}} rescue => detail @@ -33,79 +108,66 @@ class TestBucket < Test::Unit::TestCase end if path != "" - files.push path.chomp + @files.push path.chomp end end } - return files + return @files end def setup - if __FILE__ == $0 - Puppet[:loglevel] = :debug - end - - @bucket = File::SEPARATOR + File.join("tmp","filebuckettesting") - - @@tmppids = [] - @@tmpfiles = [@bucket] - - @oldconf = Puppet[:puppetconf] - Puppet[:puppetconf] = "/tmp/buckettesting" - @oldvar = Puppet[:puppetvar] - Puppet[:puppetvar] = "/tmp/buckettesting" - - @@tmpfiles << "/tmp/buckettesting" - end - - def teardown - @@tmpfiles.each { |file| - if FileTest.exists?(file) - system("rm -rf %s" % file) - end - } - @@tmppids.each { |pid| - system("kill -INT %s" % pid) - } + super + @bucket = File.join(Puppet[:puppetconf], "buckettesting") - Puppet[:puppetconf] = @oldconf - Puppet[:puppetvar] = @oldvar + @@tmpfiles << @bucket 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 + server = nil assert_nothing_raised { server = Puppet::Server::FileBucket.new( :Bucket => @bucket ) } + + # iterate across them... files.each { |file| + spin 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() - tmpdir = File.join(@bucket,"tmpfiledir") - Puppet.recmkdir(tmpdir) + tmpdir = File.join(tmpdir(),"tmpfiledir") + FileUtils.mkdir_p(tmpdir) bucket = nil client = nil @@ -122,151 +184,38 @@ class TestBucket < Test::Unit::TestCase :Bucket => bucket ) } - files.each { |file| - name = File.basename(file) - tmppath = File.join(tmpdir,name) - - # copy the files to our tmp directory so we can modify them... - #STDERR.puts("copying %s" % file) if $debug - File.open(tmppath,File::WRONLY|File::TRUNC|File::CREAT) { |wf| - File.open(file) { |rf| - wf.print(rf.read) - } - } - - assert(FileTest.exists?(tmppath)) - - osum = nil - tsum = nil - nsum = nil - assert_nothing_raised { - #STDERR.puts("backing up %s" % file) if $debug - osum = client.backup(file) - } - assert_nothing_raised { - #STDERR.puts("backing up %s" % tmppath) if $debug - tsum = client.backup(tmppath) - } - - assert(tsum == osum) - File.open(tmppath,File::WRONLY|File::TRUNC) { |wf| - wf.print "This is some test text\n" - } - assert_nothing_raised { - #STDERR.puts("backing up %s" % tmppath) if $debug - nsum = client.backup(tmppath) - } - - assert(tsum != nsum) - - assert_nothing_raised { - #STDERR.puts("restoring %s" % tmppath) if $debug - nsum = client.restore(tmppath,tsum) - } + checkfiles(client) - contents = File.open(tmppath) { |rf| - #STDERR.puts("reading %s" % tmppath) if $debug - rf.read - } - csum = Digest::MD5.hexdigest(contents) - assert(tsum == csum) - } end + # test that things work over the wire def test_webxmlmix files = filelist() - tmpdir = File.join(@bucket,"tmpfiledir") - Puppet.recmkdir(tmpdir) + tmpdir = File.join(tmpdir(),"tmpfiledir") + FileUtils.mkdir_p(tmpdir) - asign = Puppet[:autosign] Puppet[:autosign] = true - server = nil client = nil port = Puppet[:masterport] - serverthread = nil - pid = fork { - server = Puppet::Server.new( - :Port => port, - :Handlers => { - :CA => {}, # so that certs autogenerate - :FileBucket => { - :Bucket => @bucket, - } - } - ) - trap(:INT) { server.shutdown } - trap(:TERM) { server.shutdown } - server.start - } - @@tmppids << pid - sleep 3 + + pid = mkserver(:CA => nil, :FileBucket => { :Bucket => @bucket}) assert_nothing_raised { client = Puppet::Client::Dipper.new( :Server => "localhost", - :Port => port + :Port => @@port ) } - files.each { |file| - name = File.basename(file) - tmppath = File.join(tmpdir,name) - - # copy the files to our tmp directory so we can modify them... - #STDERR.puts("copying %s" % file) if $debug - File.open(tmppath,File::WRONLY|File::TRUNC|File::CREAT) { |wf| - File.open(file) { |rf| - wf.print(rf.read) - } - } - - assert(FileTest.exists?(tmppath)) - - osum = nil - tsum = nil - nsum = nil - assert_nothing_raised { - #STDERR.puts("backing up %s" % file) if $debug - osum = client.backup(file) - } - assert_nothing_raised { - #STDERR.puts("backing up %s" % tmppath) if $debug - tsum = client.backup(tmppath) - } - - assert(tsum == osum) - - File.open(tmppath,File::WRONLY|File::TRUNC) { |wf| - wf.print "This is some test text\n" - } - assert_nothing_raised { - #STDERR.puts("backing up %s" % tmppath) if $debug - nsum = client.backup(tmppath) - } - assert(tsum != nsum) - - assert_nothing_raised { - #STDERR.puts("restoring %s" % tmppath) if $debug - nsum = client.restore(tmppath,tsum) - } - - assert_equal(tsum, nsum) - - contents = File.open(tmppath) { |rf| - #STDERR.puts("reading %s" % tmppath) if $debug - rf.read - } - csum = Digest::MD5.hexdigest(contents) - assert(tsum == csum) - } + checkfiles(client) unless pid raise "Uh, we don't have a child pid" end system("kill %s" % pid) - - Puppet[:autosign] = asign end end + +# $Id$ diff --git a/test/server/tc_ca.rb b/test/server/tc_ca.rb index de1ed0963..a7050b38d 100644 --- a/test/server/tc_ca.rb +++ b/test/server/tc_ca.rb @@ -19,43 +19,23 @@ else $short = false end -class TestCA < Test::Unit::TestCase - def setup - if __FILE__ == $0 - Puppet[:loglevel] = :debug - #paths = Puppet::Type.type(:service).searchpath - #paths.push "%s/examples/root/etc/init.d" % $puppetbase - #Puppet::Type.type(:service).setpath(paths) - end - - @@tmpfiles = [] - end - +class TestCA < ServerTest def teardown - Puppet::Type.allclear + super print "\n\n" if Puppet[:debug] - - @@tmpfiles.each { |file| - if FileTest.exists?(file) - system("rm -rf %s" % file) - end - } end - def test_autocertgeneration - ssldir = "/tmp/testcertdir" - @@tmpfiles.push ssldir - assert_nothing_raised { - Puppet[:autosign] = true - Puppet[:ssldir] = ssldir - } - file = File.join($puppetbase, "examples", "code", "head") + # verify that we're autosigning + def test_zautocertgeneration + Puppet[:autosign] = true ca = nil + # create our ca assert_nothing_raised { ca = Puppet::Server::CA.new() } + # create a cert with a fake name key = nil csr = nil cert = nil @@ -65,21 +45,26 @@ class TestCA < Test::Unit::TestCase :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) - x509 = nil + + # and they should both be valid certs assert_nothing_raised { - x509 = OpenSSL::X509::Certificate.new(certtext) + OpenSSL::X509::Certificate.new(certtext) } assert_nothing_raised { OpenSSL::X509::Certificate.new(cacerttext) @@ -94,23 +79,25 @@ class TestCA < Test::Unit::TestCase assert_equal(certtext,newtext) end + # this time don't use autosign def test_storeAndSign - ssldir = "/tmp/testcertdir" - @@tmpfiles.push ssldir assert_nothing_raised { - Puppet[:ssldir] = ssldir Puppet[:autosign] = false } - file = File.join($puppetbase, "examples", "code", "head") ca = nil caserv = nil + + # make our CA server assert_nothing_raised { caserv = Puppet::Server::CA.new() } + + # retrieve the actual ca object assert_nothing_raised { ca = caserv.ca } + # make our test cert again key = nil csr = nil cert = nil @@ -120,21 +107,27 @@ class TestCA < Test::Unit::TestCase :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) } + # 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 @@ -142,65 +135,22 @@ class TestCA < Test::Unit::TestCase 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) - end - - def cycleautosign - ssldir = "/tmp/testcertdir" - autosign = "/tmp/autosign" - @@tmpfiles.push ssldir - @@tmpfiles.push autosign - assert_nothing_raised { - Puppet[:ssldir] = ssldir - } - file = File.join($puppetbase, "examples", "code", "head") - caserv = nil - - assert_nothing_raised { - caserv = Puppet::Server::CA.new() - } - - key = nil - csr = nil - cert = nil - hostname = "test.domain.com" - assert_nothing_raised { - cert = Puppet::SSLCertificates::Certificate.new( - :name => "test.domain.com" - ) - } - assert_nothing_raised { - cert.mkcsr - } - - certtext = nil assert_nothing_raised { - certtext = caserv.getcert(cert.csr.to_s) + OpenSSL::X509::Certificate.new(newtext) } - - x509 = nil - assert_nothing_raised { - x509 = OpenSSL::X509::Certificate.new(certtext) - } - - assert(File.exists?(cert.certfile)) - - newtext = nil - assert_nothing_raised { - newtext = caserv.getcert(cert.csr.to_s) - } - - assert_equal(certtext,newtext) end + # and now test the autosign file def test_autosign - autosign = "/tmp/autosign" - Puppet[:autosign] = "/tmp/autosign" + autosign = File.join(tmpdir, "autosigntesting") + Puppet[:autosign] = autosign @@tmpfiles << autosign File.open(autosign, "w") { |f| f.puts "hostmatch.domain.com" @@ -208,11 +158,11 @@ class TestCA < Test::Unit::TestCase } caserv = nil - file = File.join($puppetbase, "examples", "code", "head") assert_nothing_raised { caserv = Puppet::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")) diff --git a/test/server/tc_fileserver.rb b/test/server/tc_fileserver.rb index 39c286ccd..4235a725c 100755 --- a/test/server/tc_fileserver.rb +++ b/test/server/tc_fileserver.rb @@ -14,22 +14,25 @@ require 'test/unit' require 'puppettest.rb' class TestFileServer < TestPuppet - def setup - if __FILE__ == $0 - Puppet[:loglevel] = :debug - end - - @@tmppids = [] - super - end + # make a simple file source + def mktestdir + testdir = File.join(tmpdir(), "remotefilecopytesting") + @@tmpfiles << testdir - def teardown - super - @@tmppids.each { |pid| - system("kill -INT %s" % pid) + # 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 { @@ -48,6 +51,17 @@ class TestFileServer < TestPuppet } 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 { @@ -74,21 +88,15 @@ class TestFileServer < TestPuppet } end + # verify that listing the root behaves as expected def test_listroot server = nil - testdir = "/tmp/remotefilecopying" - tmpfile = File.join(testdir, "tmpfile") - assert_nothing_raised { - Dir.mkdir(testdir) - File.open(tmpfile, "w") { |f| - 3.times { f.puts rand(100) } - } - @@tmpfiles << testdir - } + testdir, pattern, tmpfile = mktestdir() file = nil checks = Puppet::Server::FileServer::CHECKPARAMS + # and make our fileserver assert_nothing_raised { server = Puppet::Server::FileServer.new( :Local => true, @@ -96,39 +104,30 @@ class TestFileServer < TestPuppet ) } + # 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/", true, false) } - assert(list =~ /tmpfile/) + assert(list =~ pattern) assert_nothing_raised { list = server.list("/test", true, false) } - assert(list =~ /tmpfile/) + assert(list =~ pattern) end + # test listing individual files def test_getfilelist server = nil - testdir = "/tmp/remotefilecopying" - #subdir = "testingyo" - #subpath = File.join(testdir, "testingyo") - #dir = File.join(testdir, subdir) - tmpfile = File.join(testdir, "tmpfile") - assert_nothing_raised { - Dir.mkdir(testdir) - #Dir.mkdir(subpath) - File.open(tmpfile, "w") { |f| - 3.times { f.puts rand(100) } - } - @@tmpfiles << testdir - } + testdir, pattern, tmpfile = mktestdir() file = nil @@ -143,6 +142,7 @@ class TestFileServer < TestPuppet server.mount(testdir, "test") } + # get our listing list = nil sfile = "/test/tmpfile" assert_nothing_raised { @@ -155,12 +155,18 @@ class TestFileServer < TestPuppet 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 @@ -171,19 +177,15 @@ class TestFileServer < TestPuppet assert_equal(contents, ret) end + # check that the fileserver is seeing newly created files def test_seenewfiles server = nil - testdir = "/tmp/remotefilecopying" - oldfile = File.join(testdir, "oldfile") + testdir, pattern, tmpfile = mktestdir() + + newfile = File.join(testdir, "newfile") - assert_nothing_raised { - Dir.mkdir(testdir) - File.open(oldfile, "w") { |f| - 3.times { f.puts rand(100) } - } - @@tmpfiles << testdir - } + # go through the whole schtick again... file = nil checks = Puppet::Server::FileServer::CHECKPARAMS @@ -204,6 +206,7 @@ class TestFileServer < TestPuppet list = server.list(sfile, true, false) } + # create the new file File.open(newfile, "w") { |f| 3.times { f.puts rand(100) } } @@ -213,11 +216,15 @@ class TestFileServer < TestPuppet newlist = server.list(sfile, 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_mountroot server = nil assert_nothing_raised { @@ -231,24 +238,17 @@ class TestFileServer < TestPuppet server.mount("/", "root") } - testdir = "/tmp/remotefilecopying" - oldfile = File.join(testdir, "oldfile") - assert_nothing_raised { - Dir.mkdir(testdir) - File.open(oldfile, "w") { |f| - 3.times { f.puts rand(100) } - } - @@tmpfiles << testdir - } + testdir, pattern, tmpfile = mktestdir() list = nil assert_nothing_raised { list = server.list("/root/" + testdir, true, false) } - assert(list =~ /oldfile/) + assert(list =~ pattern) end + # verify that we're correctly recursing the right number of levels def test_recursionlevels server = nil assert_nothing_raised { @@ -258,7 +258,8 @@ class TestFileServer < TestPuppet ) } - basedir = "/tmp/remotefilecopying" + # 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 { @@ -273,20 +274,22 @@ class TestFileServer < TestPuppet server.mount(basedir, "test") } + # get our list list = nil assert_nothing_raised { list = server.list("/test/with", 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", num, false) } count = 0 - #p list while list =~ /\n/ list.sub!(/\n/, '') count += 1 @@ -295,6 +298,8 @@ class TestFileServer < TestPuppet } 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 { @@ -304,6 +309,8 @@ class TestFileServer < TestPuppet ) } + + # create a deep dir basedir = "/tmp/remotefilecopying" testdir = "%s/with/some/sub/directories/for/testing" % basedir oldfile = File.join(testdir, "oldfile") @@ -315,11 +322,13 @@ class TestFileServer < TestPuppet @@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", false, false) } @@ -333,6 +342,7 @@ class TestFileServer < TestPuppet assert(list !~ /sub/) end + # test many dirs, not necessarily very deep def test_widelists server = nil assert_nothing_raised { @@ -366,6 +376,7 @@ class TestFileServer < TestPuppet assert_equal(dirs.length + 1, list.length) end + # verify that 'describe' works as advertised def test_describe server = nil testdir = "/tmp/remotefilecopying" @@ -385,12 +396,14 @@ class TestFileServer < TestPuppet server.mount(testdir, "test") } + # get our list list = nil sfile = "/test/" assert_nothing_raised { list = server.list(sfile, true, false) } + # and describe each file in the list assert_nothing_raised { list.split("\n").each { |line| file, type = line.split("\t") @@ -399,37 +412,32 @@ class TestFileServer < TestPuppet } } + # and then make sure we can describe everything that we know is there files.each { |file| - file = File.basename(file) - assert_nothing_raised { - desc = server.describe(sfile + 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) - } + assert_describe(sfile, file, server) } end + # test that our config file is parsing and working as planned def test_configfile server = nil - basedir = "/tmp/configfiletesting" + basedir = File.join(tmpdir, "fileserverconfigfiletesting") + @@tmpfiles << basedir conftext = "# a test config file\n \n" - @@tmpfiles << basedir + # make some dirs for mounting Dir.mkdir(basedir) mounts = {} %w{thing thus these those}.each { |dir| path = File.join(basedir, dir) - conftext << "[#{dir}] - path #{path} -" mounts[dir] = mktestfiles(path) } - conffile = "/tmp/fileservertestingfile" + # create an example file with each of them + conffile = tempfile @@tmpfiles << conffile File.open(conffile, "w") { |f| @@ -454,6 +462,7 @@ class TestFileServer < TestPuppet } + # create a server with the file assert_nothing_raised { server = Puppet::Server::FileServer.new( :Local => true, @@ -478,15 +487,12 @@ class TestFileServer < TestPuppet } files.each { |f| - file = File.basename(f) - desc = server.describe(mount + file) - assert(desc, "Got no description for %s" % f) - assert(desc != "", "Got no description for %s" % f) - assert_match(/^\d+/, desc, "Got invalid description %s" % 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 => [ @@ -511,6 +517,7 @@ class TestFileServer < TestPuppet }.each { |mount, hash| mount = "/#{mount}/" + # run through the map hash.each { |type, ary| ary.each { |sub| host, ip = sub @@ -534,28 +541,27 @@ class TestFileServer < TestPuppet end + # verify we reread the config file when it changes def test_filereread server = nil - testdir = "/tmp/filerereadtesting" - @@tmpfiles << testdir + dir = testdir() - #Dir.mkdir(testdir) - files = mktestfiles(testdir) + files = mktestfiles(dir) - conffile = "/tmp/fileservertestingfile" - @@tmpfiles << conffile + conffile = tempfile() File.open(conffile, "w") { |f| f.print "# a test config file [thing] - path #{testdir} + path #{dir} allow test1.domain.com " } + # start our server with a fast timeout assert_nothing_raised { server = Puppet::Server::FileServer.new( :Local => true, @@ -579,7 +585,7 @@ class TestFileServer < TestPuppet f.print "# a test config file [thing] - path #{testdir} + path #{dir} allow test2.domain.com " } diff --git a/test/server/tc_master.rb b/test/server/tc_master.rb index 90fd3b3c0..29a10662b 100644 --- a/test/server/tc_master.rb +++ b/test/server/tc_master.rb @@ -14,46 +14,22 @@ require 'puppet/client' require 'test/unit' require 'puppettest.rb' -class TestMaster < Test::Unit::TestCase - def setup - if __FILE__ == $0 - Puppet[:loglevel] = :debug - end - - @@tmpfiles = [] - end - - def stopservices - if stype = Puppet::Type.type(:service) - stype.each { |service| - service[:running] = false - service.sync - } - end - end - +class TestMaster < ServerTest def teardown - Puppet::Type.allclear + super print "\n\n\n\n" if Puppet[:debug] - - @@tmpfiles.each { |file| - if FileTest.exists?(file) - system("rm -rf %s" % file) - end - } end + # run through all of the existing test files and make sure everything + # works def test_files - Puppet[:debug] = true if __FILE__ == $0 - Puppet[:puppetconf] = "/tmp/servertestingdir" - @@tmpfiles << Puppet[:puppetconf] + count = 0 textfiles { |file| Puppet.debug("parsing %s" % file) - server = nil client = nil - threads = [] - port = 8080 master = nil + + # create our master assert_nothing_raised() { # this is the default server setup master = Puppet::Server::Master.new( @@ -61,13 +37,15 @@ class TestMaster < Test::Unit::TestCase :Local => true ) } + + # and our client assert_nothing_raised() { client = Puppet::Client::MasterClient.new( :Master => master ) } - # pull our configuration + # pull our configuration a few times assert_nothing_raised() { client.getconfig stopservices @@ -83,13 +61,15 @@ class TestMaster < Test::Unit::TestCase stopservices Puppet::Type.allclear } + # only test three files; that's plenty + if count > 3 + break + end + count += 1 } end def test_defaultmanifest - Puppet[:debug] = true if __FILE__ == $0 - Puppet[:puppetconf] = "/tmp/servertestingdir" - @@tmpfiles << Puppet[:puppetconf] textfiles { |file| Puppet[:manifest] = file client = nil @@ -118,22 +98,11 @@ class TestMaster < Test::Unit::TestCase } end - def test_zfilereread - Puppet[:debug] = true if __FILE__ == $0 - Puppet[:puppetconf] = "/tmp/masterfilereread" - Puppet[:puppetvar] = "/tmp/masterfilereread" - @@tmpfiles << Puppet[:puppetconf] + def test_filereread + manifest = mktestmanifest() - manifest = "/tmp/masterfilerereadmanifest.pp" - @@tmpfiles << manifest = "/tmp/masterfilerereadmanifest.pp" - file1 = "/tmp/masterfilecreationrearead" - file2 = "/tmp/masterfilecreationrearead2" - @@tmpfiles << file1 - @@tmpfiles << file2 + file2 = @createdfile + "2" - File.open(manifest, "w") { |f| - f.puts %{file { "/tmp/masterfilecreationrearead": create => true } } - } client = master = nil assert_nothing_raised() { # this is the default server setup @@ -154,12 +123,13 @@ class TestMaster < Test::Unit::TestCase client.apply } - assert(FileTest.exists?(file1), "First file %s does not exist" % file1) + assert(FileTest.exists?(@createdfile), + "Created file %s does not exist" % @createdfile) sleep 1 Puppet::Type.allclear File.open(manifest, "w") { |f| - f.puts %{file { "/tmp/masterfilecreationrearead2": create => true } } + f.puts "file { \"%s\": create => true }\n" % file2 } assert_nothing_raised { client.getconfig diff --git a/test/server/tc_server.rb b/test/server/tc_server.rb index 3854f848c..988a1e17a 100644 --- a/test/server/tc_server.rb +++ b/test/server/tc_server.rb @@ -21,60 +21,25 @@ else $short = false end -class TestServer < Test::Unit::TestCase - def setup - if __FILE__ == $0 - Puppet[:loglevel] = :debug - #paths = Puppet::Type.type(:service).searchpath - #paths.push "%s/examples/root/etc/init.d" % $puppetbase - #Puppet::Type.type(:service).setpath(paths) - end - - @oldconf = Puppet[:puppetconf] - Puppet[:puppetconf] = "/tmp/servertesting" - @oldvar = Puppet[:puppetvar] - Puppet[:puppetvar] = "/tmp/servertesting" - - @@tmpfiles = ["/tmp/servertesting"] - @@tmppids = [] - end - - def stopservices - if stype = Puppet::Type.type(:service) - stype.each { |service| - service[:running] = false - service.sync - } - end - end - +class TestServer < ServerTest def teardown - Puppet::Type.allclear + super print "\n\n\n\n" if Puppet[:debug] - - @@tmpfiles.each { |file| - if FileTest.exists?(file) - system("rm -rf %s" % file) - end - } - @@tmppids.each { |pid| - system("kill -INT %s" % pid) - } - - Puppet[:puppetconf] = @oldconf - Puppet[:puppetvar] = @oldvar end + # just do a simple start test def test_start - server = nil - Puppet[:ssldir] = "/tmp/serverstarttesting" Puppet[:autosign] = true - @@tmpfiles << "/tmp/serverstarttesting" - port = 8081 - file = File.join($puppetbase, "examples", "code", "head") + server = nil + # make a test manifest + file = mktestmanifest() + + # create a simple server + # we can use threading here because we're not talking to the server, + # just starting and stopping it assert_nothing_raised() { server = Puppet::Server.new( - :Port => port, + :Port => @@port, :Handlers => { :CA => {}, # so that certs autogenerate :Master => { @@ -85,6 +50,8 @@ class TestServer < Test::Unit::TestCase ) } + + # start it sthread = nil assert_nothing_raised() { trap(:INT) { server.shutdown } @@ -92,82 +59,29 @@ class TestServer < Test::Unit::TestCase server.start } } - sleep 1 + + # and stop it assert_nothing_raised { server.shutdown } + + # and then wait assert_nothing_raised { sthread.join } end - # disabled because i can't find a good way to test client connecting - # i'll have to test the external executables - def disabled_test_connect_with_threading - server = nil - Puppet[:ssldir] = "/tmp/serverconnecttesting" - Puppet[:autosign] = true - @@tmpfiles << "/tmp/serverconnecttesting" - threads = [] - port = 8080 - server = nil - Thread.abort_on_exception = true - assert_nothing_raised() { - server = Puppet::Server.new( - :Port => port, - :Handlers => { - :CA => {}, # so that certs autogenerate - :Status => nil - } - ) - - } - sthread = Thread.new { - assert_nothing_raised() { - #trap(:INT) { server.shutdown; Kernel.exit! } - trap(:INT) { server.shutdown } - server.start - } - } - - sleep(3) - client = nil - assert_nothing_raised() { - client = XMLRPC::Client.new("localhost", "/RPC2", port, nil, nil, - nil, nil, true, 3) - } - retval = nil - - clthread = Thread.new { - assert_nothing_raised() { - retval = client.call("status.status", "") - } - } - assert_not_nil(clthread.join(5)) - - assert_equal(1, retval) - assert_nothing_raised { - #system("kill -INT %s" % serverpid) - server.shutdown - } - - assert_not_nil(sthread.join(5)) - - #Process.wait - end - - # disabled because i can't find a good way to test client connecting - # i'll have to test the external executables + # 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 server = nil - Puppet[:ssldir] = "/tmp/serverconnecttesting" Puppet[:autosign] = true - @@tmpfiles << "/tmp/serverconnecttesting" - serverpid = nil - port = 8080 + + # create a server just serving status assert_nothing_raised() { server = Puppet::Server.new( - :Port => port, + :Port => @@port, :Handlers => { :CA => {}, # so that certs autogenerate :Status => nil @@ -175,49 +89,45 @@ class TestServer < Test::Unit::TestCase ) } + + # and fork serverpid = fork { assert_nothing_raised() { - #trap(:INT) { server.shutdown; Kernel.exit! } trap(:INT) { server.shutdown } server.start } } @@tmppids << serverpid - sleep(3) + # create a status client, and verify it can talk client = nil assert_nothing_raised() { - client = XMLRPC::Client.new("localhost", "/RPC2", port, nil, nil, - nil, nil, true, 3) + client = Puppet::Client::StatusClient.new( + :Server => "localhost", + :Port => @@port + ) } retval = nil assert_nothing_raised() { - retval = client.call("status.status") + retval = client.status } assert_equal(1, retval) - #assert_nothing_raised { - # system("kill -INT %s" % serverpid) - # #server.shutdown - #} - - #Process.wait end - # disabled because i can't find a good way to test client connecting - # i'll have to test the external executables - def test_zzgetconfig_with_fork - server = nil - Puppet[:ssldir] = "/tmp/serverconfigtesting" + # similar to the last test, but this time actually run getconfig + def test_getconfig_with_fork Puppet[:autosign] = true - @@tmpfiles << "/tmp/serverconfigtesting" serverpid = nil - port = 8082 - file = File.join($puppetbase, "examples", "code", "head") + + file = mktestmanifest() + + server = nil + # make our server again assert_nothing_raised() { server = Puppet::Server.new( - :Port => port, + :Port => @@port, :Handlers => { :CA => {}, # so that certs autogenerate :Master => { @@ -237,118 +147,26 @@ class TestServer < Test::Unit::TestCase } @@tmppids << serverpid - sleep(3) client = nil - # first use a puppet client object + # and then start a masterclient assert_nothing_raised() { client = Puppet::Client::MasterClient.new( :Server => "localhost", - :Port => port + :Port => @@port ) } retval = nil + # and run getconfig a couple of times assert_nothing_raised() { retval = client.getconfig } + assert_instance_of(Puppet::TransBucket, retval, + "Server returned something other than a TransBucket") - # then use a raw rpc client assert_nothing_raised() { - client = XMLRPC::Client.new("localhost", "/RPC2", port, nil, nil, - nil, nil, true, 3) - } - retval = nil - - facts = CGI.escape(Marshal.dump(Puppet::Client::MasterClient.facts)) - assert_nothing_raised() { - retval = client.call("puppetmaster.getconfig", facts) - } - - #assert_equal(1, retval) - end - - # disabled because clients can't seem to connect from in the same process - def disabled_test_files - Puppet[:debug] = true if __FILE__ == $0 - Puppet[:puppetconf] = "/tmp/servertestingdir" - Puppet[:autosign] = true - @@tmpfiles << Puppet[:puppetconf] - textfiles { |file| - Puppet.debug("parsing %s" % file) - server = nil - client = nil - threads = [] - port = 8080 - assert_nothing_raised() { - # this is the default server setup - server = Puppet::Server.new( - :Port => port, - :Handlers => { - :CA => {}, # so that certs autogenerate - :Master => { - :File => file, - }, - } - ) - } - assert_nothing_raised() { - client = Puppet::Client.new( - :Server => "localhost", - :Port => port - ) - } - - # start the server - assert_nothing_raised() { - trap(:INT) { server.shutdown } - threads << Thread.new { - server.start - } - } - - # start the client - #assert_nothing_raised() { - # threads << Thread.new { - # client.start - # } - #} - - sleep(1) - # pull our configuration - 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 - } - - # and shut them both down - assert_nothing_raised() { - [server].each { |thing| - thing.shutdown - } - } - - # make sure everything's complete before we stop - assert_nothing_raised() { - threads.each { |thr| - thr.join - } - } - assert_nothing_raised() { - stopservices - } - Puppet::Type.allclear + retval = client.getconfig } end end diff --git a/test/types/tc_filesources.rb b/test/types/tc_filesources.rb index b0f419697..226b147f1 100755 --- a/test/types/tc_filesources.rb +++ b/test/types/tc_filesources.rb @@ -40,16 +40,12 @@ class TestFileSources < TestPuppet rescue system("rm -rf %s" % Puppet[:checksumfile]) end - @@tmppids = [] super end def teardown clearstorage super - @@tmppids.each { |pid| - system("kill -INT %s" % pid) - } end def initstorage @@ -129,8 +125,6 @@ class TestFileSources < TestPuppet from = File.open(frompath) { |o| o.read } to = File.open(topath) { |o| o.read } assert_equal(from,to) - clearstorage - Puppet::Type.allclear @@tmpfiles.push path end @@ -159,8 +153,6 @@ class TestFileSources < TestPuppet } assert(FileTest.exists?(todir)) - - clearstorage Puppet::Type.allclear end @@ -311,7 +303,10 @@ class TestFileSources < TestPuppet return file end - def test_zSimpleNetworkSources + # test raw xmlrpc calls + # this test is disabled because it requires way too much setup to get + # the certificates correct + def disabled_test_SimpleNetworkSources server = nil basedir = "/tmp/simplenetworksourcetesting" @@tmpfiles << basedir @@ -393,7 +388,7 @@ class TestFileSources < TestPuppet } end - def test_zNetworkSources + def test_NetworkSources server = nil basedir = "/tmp/networksourcetesting" @@tmpfiles << basedir |
