From a216df2bcb304ad379e152f2f59ef7d942f54f3b Mon Sep 17 00:00:00 2001 From: luke Date: Thu, 8 Feb 2007 02:22:57 +0000 Subject: 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 --- lib/puppet/network/authconfig.rb | 173 ++++++ lib/puppet/network/authstore.rb | 227 +++++++ lib/puppet/network/rights.rb | 74 +++ lib/puppet/network/server.rb | 5 +- lib/puppet/network/server/authconfig.rb | 173 ------ lib/puppet/network/server/authstore.rb | 227 ------- lib/puppet/network/server/rights.rb | 74 --- test/client/client.rb | 193 ------ test/client/master.rb | 530 ---------------- test/client/networkclient.rb | 18 - test/client/resource.rb | 94 --- test/network/client/client.rb | 193 ++++++ test/network/client/master.rb | 530 ++++++++++++++++ test/network/client/networkclient.rb | 18 + test/network/client/resource.rb | 94 +++ test/network/server/authconfig.rb | 53 ++ test/network/server/authstore.rb | 211 +++++++ test/network/server/bucket.rb | 259 ++++++++ test/network/server/ca.rb | 233 +++++++ test/network/server/fileserver.rb | 1024 +++++++++++++++++++++++++++++++ test/network/server/logger.rb | 179 ++++++ test/network/server/master.rb | 346 +++++++++++ test/network/server/report.rb | 185 ++++++ test/network/server/resource.rb | 296 +++++++++ test/network/server/rights.rb | 37 ++ test/network/server/runner.rb | 106 ++++ test/network/server/server.rb | 197 ++++++ test/server/authconfig.rb | 53 -- test/server/authstore.rb | 211 ------- test/server/bucket.rb | 259 -------- test/server/ca.rb | 233 ------- test/server/fileserver.rb | 1024 ------------------------------- test/server/logger.rb | 179 ------ test/server/master.rb | 346 ----------- test/server/report.rb | 185 ------ test/server/resource.rb | 296 --------- test/server/rights.rb | 37 -- test/server/runner.rb | 106 ---- test/server/server.rb | 197 ------ 39 files changed, 4438 insertions(+), 4437 deletions(-) create mode 100644 lib/puppet/network/authconfig.rb create mode 100755 lib/puppet/network/authstore.rb create mode 100755 lib/puppet/network/rights.rb delete mode 100644 lib/puppet/network/server/authconfig.rb delete mode 100755 lib/puppet/network/server/authstore.rb delete mode 100755 lib/puppet/network/server/rights.rb delete mode 100755 test/client/client.rb delete mode 100755 test/client/master.rb delete mode 100755 test/client/networkclient.rb delete mode 100755 test/client/resource.rb create mode 100755 test/network/client/client.rb create mode 100755 test/network/client/master.rb create mode 100755 test/network/client/networkclient.rb create mode 100755 test/network/client/resource.rb create mode 100755 test/network/server/authconfig.rb create mode 100755 test/network/server/authstore.rb create mode 100755 test/network/server/bucket.rb create mode 100755 test/network/server/ca.rb create mode 100755 test/network/server/fileserver.rb create mode 100755 test/network/server/logger.rb create mode 100755 test/network/server/master.rb create mode 100755 test/network/server/report.rb create mode 100755 test/network/server/resource.rb create mode 100755 test/network/server/rights.rb create mode 100755 test/network/server/runner.rb create mode 100755 test/network/server/server.rb delete mode 100755 test/server/authconfig.rb delete mode 100755 test/server/authstore.rb delete mode 100755 test/server/bucket.rb delete mode 100755 test/server/ca.rb delete mode 100755 test/server/fileserver.rb delete mode 100755 test/server/logger.rb delete mode 100755 test/server/master.rb delete mode 100755 test/server/report.rb delete mode 100755 test/server/resource.rb delete mode 100755 test/server/rights.rb delete mode 100755 test/server/runner.rb delete mode 100755 test/server/server.rb diff --git a/lib/puppet/network/authconfig.rb b/lib/puppet/network/authconfig.rb new file mode 100644 index 000000000..bf21fb5ce --- /dev/null +++ b/lib/puppet/network/authconfig.rb @@ -0,0 +1,173 @@ +require 'puppet/util/loadedfile' +require 'puppet/network/rights' + +module Puppet + class ConfigurationError < Puppet::Error; end + class Network::AuthConfig < Puppet::Util::LoadedFile + Puppet.config.setdefaults(:puppet, + :authconfig => [ "$confdir/namespaceauth.conf", + "The configuration file that defines the rights to the different + namespaces and methods. This can be used as a coarse-grained + authorization system for both ``puppetd`` and ``puppetmasterd``." + ] + ) + + # Just proxy the setting methods to our rights stuff + [:allow, :deny].each do |method| + define_method(method) do |*args| + @rights.send(method, *args) + end + end + + # Here we add a little bit of semantics. They can set auth on a whole namespace + # or on just a single method in the namespace. + def allowed?(name, host, ip) + namespace, method = name.to_s.split(".") + unless namespace and method + raise ArgumentError, "Invalid method name %s" % name + end + + name = name.intern if name.is_a? String + namespace = namespace.intern + method = method.intern + + read() + + if @rights.include?(name) + return @rights[name].allowed?(host, ip) + elsif @rights.include?(namespace) + return @rights[namespace].allowed?(host, ip) + else + return false + end + end + + # Does the file exist? Puppetmasterd does not require it, but + # puppetd does. + def exists? + FileTest.exists?(@file) + end + + def initialize(file = nil, parsenow = true) + @file ||= Puppet[:authconfig] + + unless @file + raise Puppet::DevError, "No authconfig file defined" + end + return unless self.exists? + super(@file) + @rights = Puppet::Network::Rights.new + @configstamp = @configstatted = nil + @configtimeout = 60 + + if parsenow + read() + end + end + + # Read the configuration file. + def read + return unless FileTest.exists?(@file) + + if @configstamp + if @configtimeout and @configstatted + if Time.now - @configstatted > @configtimeout + @configstatted = Time.now + tmp = File.stat(@file).ctime + + if tmp == @configstamp + return + else + Puppet.notice "%s vs %s" % [tmp, @configstamp] + end + else + return + end + else + Puppet.notice "%s and %s" % [@configtimeout, @configstatted] + end + end + + parse() + + @configstamp = File.stat(@file).ctime + @configstatted = Time.now + end + + private + + def parse + newrights = Puppet::Network::Rights.new + begin + File.open(@file) { |f| + right = nil + count = 1 + f.each { |line| + case line + when /^\s*#/: next # skip comments + when /^\s*$/: next # skip blank lines + when /\[([\w.]+)\]/: # "namespace" or "namespace.method" + name = $1 + if newrights.include?(name) + raise FileServerError, "%s is already set at %s" % + [newrights[name], name] + end + newrights.newright(name) + right = newrights[name] + when /^\s*(\w+)\s+(.+)$/: + var = $1 + value = $2 + case var + when "allow": + value.split(/\s*,\s*/).each { |val| + begin + right.info "allowing %s access" % val + right.allow(val) + rescue AuthStoreError => detail + raise ConfigurationError, "%s at line %s of %s" % + [detail.to_s, count, @config] + end + } + when "deny": + value.split(/\s*,\s*/).each { |val| + begin + right.info "denying %s access" % val + right.deny(val) + rescue AuthStoreError => detail + raise ConfigurationError, "%s at line %s of %s" % + [detail.to_s, count, @config] + end + } + else + raise ConfigurationError, + "Invalid argument '%s' at line %s" % [var, count] + end + else + raise ConfigurationError, "Invalid line %s: %s" % [count, line] + end + count += 1 + } + } + rescue Errno::EACCES => detail + Puppet.err "Configuration error: Cannot read %s; cannot serve" % @file + #raise Puppet::Error, "Cannot read %s" % @config + rescue Errno::ENOENT => detail + Puppet.err "Configuration error: '%s' does not exit; cannot serve" % + @file + #raise Puppet::Error, "%s does not exit" % @config + #rescue FileServerError => detail + # Puppet.err "FileServer error: %s" % detail + end + + # Verify each of the rights are valid. + # We let the check raise an error, so that it can raise an error + # pointing to the specific problem. + newrights.each { |name, right| + right.valid? + } + @rights = newrights + end + end +end + +# $Id$ diff --git a/lib/puppet/network/authstore.rb b/lib/puppet/network/authstore.rb new file mode 100755 index 000000000..51ce93d46 --- /dev/null +++ b/lib/puppet/network/authstore.rb @@ -0,0 +1,227 @@ +# standard module for determining whether a given hostname or IP has access to +# the requested resource + +require 'ipaddr' + +module Puppet + class AuthStoreError < Puppet::Error; end + class AuthorizationError < Puppet::Error; end + + class Network::AuthStore + # This has to be an array, not a hash, else it loses its ordering. + ORDER = [ + [:ip, [:ip]], + [:name, [:hostname, :domain]] + ] + + Puppet::Util.logmethods(self, true) + + def allow(pattern) + # a simple way to allow anyone at all to connect + if pattern == "*" + @globalallow = true + else + store(pattern, @allow) + end + end + + def allowed?(name, ip) + if name or ip + # This is probably unnecessary, and can cause some weirdnesses in + # cases where we're operating over localhost but don't have a real + # IP defined. + unless name and ip + raise Puppet::DevError, "Name and IP must be passed to 'allowed?'" + end + # else, we're networked and such + else + # we're local + return true + end + + # yay insecure overrides + if @globalallow + return true + end + + value = nil + ORDER.each { |nametype, array| + if nametype == :ip + value = IPAddr.new(ip) + else + value = name.split(".").reverse + end + + + array.each { |type| + [[@deny, false], [@allow, true]].each { |ary| + hash, retval = ary + if hash.include?(type) + hash[type].each { |pattern| + if match?(nametype, value, pattern) + return retval + end + } + end + } + } + } + + self.info "defaulting to no access for %s" % name + # default to false + return false + end + + def deny(pattern) + store(pattern, @deny) + end + + def initialize + @globalallow = nil + @allow = Hash.new { |hash, key| + hash[key] = [] + } + @deny = Hash.new { |hash, key| + hash[key] = [] + } + end + + private + + def match?(nametype, value, pattern) + if value == pattern # simplest shortcut + return true + end + + case nametype + when :ip: matchip?(value, pattern) + when :name: matchname?(value, pattern) + else + raise Puppet::DevError, "Invalid match type %s" % nametype + end + end + + def matchip?(value, pattern) + # we're just using builtin stuff for this, thankfully + if pattern.include?(value) + return true + else + return false + end + end + + def matchname?(value, pattern) + # yay, horribly inefficient + if pattern[-1] != '*' # the pattern has no metachars and is not equal + # thus, no match + #Puppet.info "%s is not equal with no * in %s" % [value, pattern] + return false + else + # we know the last field of the pattern is '*' + # if everything up to that doesn't match, we're definitely false + if pattern[0..-2] != value[0..pattern.length-2] + #Puppet.notice "subpatterns didn't match; %s vs %s" % + # [pattern[0..-2], value[0..pattern.length-2]] + return false + end + + case value.length <=> pattern.length + when -1: # value is shorter than pattern + if pattern.length - value.length == 1 + # only ever allowed when the value is the domain of a + # splatted pattern + #Puppet.info "allowing splatted domain %s" % [value] + return true + else + return false + end + when 0: # value is the same length as pattern + if pattern[-1] == "*" + #Puppet.notice "same length with *" + return true + else + return false + end + when 1: # value is longer than pattern + # at this point we've already verified that everything up to + # the '*' in the pattern matches, so we are true + return true + end + end + end + + def store(pattern, hash) + type, value = type(pattern) + + if type and value + # this won't work once we get beyond simple stuff... + hash[type] << value + else + raise AuthStoreError, "Invalid pattern %s" % pattern + end + end + + def type(pattern) + type = value = nil + case pattern + when /^(\d+\.){3}\d+$/: + type = :ip + begin + value = IPAddr.new(pattern) + rescue ArgumentError => detail + raise AuthStoreError, "Invalid IP address pattern %s" % pattern + end + when /^(\d+\.){3}\d+\/(\d+)$/: + mask = Integer($2) + if mask < 1 or mask > 32 + raise AuthStoreError, "Invalid IP mask %s" % mask + end + type = :ip + begin + value = IPAddr.new(pattern) + rescue ArgumentError => detail + raise AuthStoreError, "Invalid IP address pattern %s" % pattern + end + when /^(\d+\.){1,3}\*$/: # an ip address with a '*' at the end + type = :ip + match = $1 + match.sub!(".", '') + ary = pattern.split(".") + + mask = case ary.index(match) + when 0: 8 + when 1: 16 + when 2: 24 + else + raise AuthStoreError, "Invalid IP pattern %s" % pattern + end + + ary.pop + while ary.length < 4 + ary.push("0") + end + + begin + value = IPAddr.new(ary.join(".") + "/" + mask.to_s) + rescue ArgumentError => detail + raise AuthStoreError, "Invalid IP address pattern %s" % pattern + end + when /^[\d.]+$/: # necessary so incomplete IP addresses can't look + # like hostnames + raise AuthStoreError, "Invalid IP address pattern %s" % pattern + when /^([a-zA-Z][-\w]*\.)+[-\w]+$/: # a full hostname + type = :hostname + value = pattern.split(".").reverse + when /^\*(\.([a-zA-Z][-\w]*)){1,}$/: + type = :domain + value = pattern.split(".").reverse + else + raise AuthStoreError, "Invalid pattern %s" % pattern + end + + return [type, value] + end + end +end + +# $Id$ diff --git a/lib/puppet/network/rights.rb b/lib/puppet/network/rights.rb new file mode 100755 index 000000000..970a7aacf --- /dev/null +++ b/lib/puppet/network/rights.rb @@ -0,0 +1,74 @@ +require 'ipaddr' +require 'puppet/network/authstore' + +# Define a set of rights and who has access to them. +class Puppet::Network::Rights < Hash + # We basically just proxy directly to our rights. Each Right stores + # its own auth abilities. + [:allow, :allowed?, :deny].each do |method| + define_method(method) do |name, *args| + name = name.intern if name.is_a? String + + if obj = right(name) + obj.send(method, *args) + else + raise ArgumentError, "Unknown right '%s'" % name + end + end + end + + def [](name) + name = name.intern if name.is_a? String + super(name) + end + + # Define a new right to which access can be provided. + def newright(name) + name = name.intern if name.is_a? String + shortname = Right.shortname(name) + if self.include? name + raise ArgumentError, "Right '%s' is already defined" % name + else + self[name] = Right.new(name, shortname) + end + end + + private + + # Retrieve a right by name. + def right(name) + name = name.intern if name.is_a? String + self[name] + end + + # A right. + class Right < Puppet::Network::AuthStore + attr_accessor :name, :shortname + + Puppet::Util.logmethods(self, true) + + def self.shortname(name) + name.to_s[0..0] + end + + def initialize(name, shortname = nil) + @name = name + @shortname = shortname + unless @shortname + @shortname = Right.shortname(name) + end + super() + end + + def to_s + "access[%s]" % @name + end + + # There's no real check to do at this point + def valid? + true + end + end +end + +# $Id$ diff --git a/lib/puppet/network/server.rb b/lib/puppet/network/server.rb index e9205d48b..3f19a88ff 100644 --- a/lib/puppet/network/server.rb +++ b/lib/puppet/network/server.rb @@ -191,8 +191,9 @@ module Puppet end end -require 'puppet/network/server/authstore' -require 'puppet/network/server/authconfig' +require 'puppet/network/authstore' +require 'puppet/network/authconfig' +require 'puppet/network/rights' require 'puppet/network/server/servlet' require 'puppet/network/server/master' require 'puppet/network/server/ca' diff --git a/lib/puppet/network/server/authconfig.rb b/lib/puppet/network/server/authconfig.rb deleted file mode 100644 index e4d31d8d8..000000000 --- a/lib/puppet/network/server/authconfig.rb +++ /dev/null @@ -1,173 +0,0 @@ -require 'puppet/util/loadedfile' -require 'puppet/network/server/rights' - -module Puppet - class ConfigurationError < Puppet::Error; end - class Network::AuthConfig < Puppet::Util::LoadedFile - Puppet.config.setdefaults(:puppet, - :authconfig => [ "$confdir/namespaceauth.conf", - "The configuration file that defines the rights to the different - namespaces and methods. This can be used as a coarse-grained - authorization system for both ``puppetd`` and ``puppetmasterd``." - ] - ) - - # Just proxy the setting methods to our rights stuff - [:allow, :deny].each do |method| - define_method(method) do |*args| - @rights.send(method, *args) - end - end - - # Here we add a little bit of semantics. They can set auth on a whole namespace - # or on just a single method in the namespace. - def allowed?(name, host, ip) - namespace, method = name.to_s.split(".") - unless namespace and method - raise ArgumentError, "Invalid method name %s" % name - end - - name = name.intern if name.is_a? String - namespace = namespace.intern - method = method.intern - - read() - - if @rights.include?(name) - return @rights[name].allowed?(host, ip) - elsif @rights.include?(namespace) - return @rights[namespace].allowed?(host, ip) - else - return false - end - end - - # Does the file exist? Puppetmasterd does not require it, but - # puppetd does. - def exists? - FileTest.exists?(@file) - end - - def initialize(file = nil, parsenow = true) - @file ||= Puppet[:authconfig] - - unless @file - raise Puppet::DevError, "No authconfig file defined" - end - return unless self.exists? - super(@file) - @rights = Puppet::Network::Rights.new - @configstamp = @configstatted = nil - @configtimeout = 60 - - if parsenow - read() - end - end - - # Read the configuration file. - def read - return unless FileTest.exists?(@file) - - if @configstamp - if @configtimeout and @configstatted - if Time.now - @configstatted > @configtimeout - @configstatted = Time.now - tmp = File.stat(@file).ctime - - if tmp == @configstamp - return - else - Puppet.notice "%s vs %s" % [tmp, @configstamp] - end - else - return - end - else - Puppet.notice "%s and %s" % [@configtimeout, @configstatted] - end - end - - parse() - - @configstamp = File.stat(@file).ctime - @configstatted = Time.now - end - - private - - def parse - newrights = Puppet::Network::Rights.new - begin - File.open(@file) { |f| - right = nil - count = 1 - f.each { |line| - case line - when /^\s*#/: next # skip comments - when /^\s*$/: next # skip blank lines - when /\[([\w.]+)\]/: # "namespace" or "namespace.method" - name = $1 - if newrights.include?(name) - raise FileServerError, "%s is already set at %s" % - [newrights[name], name] - end - newrights.newright(name) - right = newrights[name] - when /^\s*(\w+)\s+(.+)$/: - var = $1 - value = $2 - case var - when "allow": - value.split(/\s*,\s*/).each { |val| - begin - right.info "allowing %s access" % val - right.allow(val) - rescue AuthStoreError => detail - raise ConfigurationError, "%s at line %s of %s" % - [detail.to_s, count, @config] - end - } - when "deny": - value.split(/\s*,\s*/).each { |val| - begin - right.info "denying %s access" % val - right.deny(val) - rescue AuthStoreError => detail - raise ConfigurationError, "%s at line %s of %s" % - [detail.to_s, count, @config] - end - } - else - raise ConfigurationError, - "Invalid argument '%s' at line %s" % [var, count] - end - else - raise ConfigurationError, "Invalid line %s: %s" % [count, line] - end - count += 1 - } - } - rescue Errno::EACCES => detail - Puppet.err "Configuration error: Cannot read %s; cannot serve" % @file - #raise Puppet::Error, "Cannot read %s" % @config - rescue Errno::ENOENT => detail - Puppet.err "Configuration error: '%s' does not exit; cannot serve" % - @file - #raise Puppet::Error, "%s does not exit" % @config - #rescue FileServerError => detail - # Puppet.err "FileServer error: %s" % detail - end - - # Verify each of the rights are valid. - # We let the check raise an error, so that it can raise an error - # pointing to the specific problem. - newrights.each { |name, right| - right.valid? - } - @rights = newrights - end - end -end - -# $Id$ diff --git a/lib/puppet/network/server/authstore.rb b/lib/puppet/network/server/authstore.rb deleted file mode 100755 index 51ce93d46..000000000 --- a/lib/puppet/network/server/authstore.rb +++ /dev/null @@ -1,227 +0,0 @@ -# standard module for determining whether a given hostname or IP has access to -# the requested resource - -require 'ipaddr' - -module Puppet - class AuthStoreError < Puppet::Error; end - class AuthorizationError < Puppet::Error; end - - class Network::AuthStore - # This has to be an array, not a hash, else it loses its ordering. - ORDER = [ - [:ip, [:ip]], - [:name, [:hostname, :domain]] - ] - - Puppet::Util.logmethods(self, true) - - def allow(pattern) - # a simple way to allow anyone at all to connect - if pattern == "*" - @globalallow = true - else - store(pattern, @allow) - end - end - - def allowed?(name, ip) - if name or ip - # This is probably unnecessary, and can cause some weirdnesses in - # cases where we're operating over localhost but don't have a real - # IP defined. - unless name and ip - raise Puppet::DevError, "Name and IP must be passed to 'allowed?'" - end - # else, we're networked and such - else - # we're local - return true - end - - # yay insecure overrides - if @globalallow - return true - end - - value = nil - ORDER.each { |nametype, array| - if nametype == :ip - value = IPAddr.new(ip) - else - value = name.split(".").reverse - end - - - array.each { |type| - [[@deny, false], [@allow, true]].each { |ary| - hash, retval = ary - if hash.include?(type) - hash[type].each { |pattern| - if match?(nametype, value, pattern) - return retval - end - } - end - } - } - } - - self.info "defaulting to no access for %s" % name - # default to false - return false - end - - def deny(pattern) - store(pattern, @deny) - end - - def initialize - @globalallow = nil - @allow = Hash.new { |hash, key| - hash[key] = [] - } - @deny = Hash.new { |hash, key| - hash[key] = [] - } - end - - private - - def match?(nametype, value, pattern) - if value == pattern # simplest shortcut - return true - end - - case nametype - when :ip: matchip?(value, pattern) - when :name: matchname?(value, pattern) - else - raise Puppet::DevError, "Invalid match type %s" % nametype - end - end - - def matchip?(value, pattern) - # we're just using builtin stuff for this, thankfully - if pattern.include?(value) - return true - else - return false - end - end - - def matchname?(value, pattern) - # yay, horribly inefficient - if pattern[-1] != '*' # the pattern has no metachars and is not equal - # thus, no match - #Puppet.info "%s is not equal with no * in %s" % [value, pattern] - return false - else - # we know the last field of the pattern is '*' - # if everything up to that doesn't match, we're definitely false - if pattern[0..-2] != value[0..pattern.length-2] - #Puppet.notice "subpatterns didn't match; %s vs %s" % - # [pattern[0..-2], value[0..pattern.length-2]] - return false - end - - case value.length <=> pattern.length - when -1: # value is shorter than pattern - if pattern.length - value.length == 1 - # only ever allowed when the value is the domain of a - # splatted pattern - #Puppet.info "allowing splatted domain %s" % [value] - return true - else - return false - end - when 0: # value is the same length as pattern - if pattern[-1] == "*" - #Puppet.notice "same length with *" - return true - else - return false - end - when 1: # value is longer than pattern - # at this point we've already verified that everything up to - # the '*' in the pattern matches, so we are true - return true - end - end - end - - def store(pattern, hash) - type, value = type(pattern) - - if type and value - # this won't work once we get beyond simple stuff... - hash[type] << value - else - raise AuthStoreError, "Invalid pattern %s" % pattern - end - end - - def type(pattern) - type = value = nil - case pattern - when /^(\d+\.){3}\d+$/: - type = :ip - begin - value = IPAddr.new(pattern) - rescue ArgumentError => detail - raise AuthStoreError, "Invalid IP address pattern %s" % pattern - end - when /^(\d+\.){3}\d+\/(\d+)$/: - mask = Integer($2) - if mask < 1 or mask > 32 - raise AuthStoreError, "Invalid IP mask %s" % mask - end - type = :ip - begin - value = IPAddr.new(pattern) - rescue ArgumentError => detail - raise AuthStoreError, "Invalid IP address pattern %s" % pattern - end - when /^(\d+\.){1,3}\*$/: # an ip address with a '*' at the end - type = :ip - match = $1 - match.sub!(".", '') - ary = pattern.split(".") - - mask = case ary.index(match) - when 0: 8 - when 1: 16 - when 2: 24 - else - raise AuthStoreError, "Invalid IP pattern %s" % pattern - end - - ary.pop - while ary.length < 4 - ary.push("0") - end - - begin - value = IPAddr.new(ary.join(".") + "/" + mask.to_s) - rescue ArgumentError => detail - raise AuthStoreError, "Invalid IP address pattern %s" % pattern - end - when /^[\d.]+$/: # necessary so incomplete IP addresses can't look - # like hostnames - raise AuthStoreError, "Invalid IP address pattern %s" % pattern - when /^([a-zA-Z][-\w]*\.)+[-\w]+$/: # a full hostname - type = :hostname - value = pattern.split(".").reverse - when /^\*(\.([a-zA-Z][-\w]*)){1,}$/: - type = :domain - value = pattern.split(".").reverse - else - raise AuthStoreError, "Invalid pattern %s" % pattern - end - - return [type, value] - end - end -end - -# $Id$ diff --git a/lib/puppet/network/server/rights.rb b/lib/puppet/network/server/rights.rb deleted file mode 100755 index 11da3b705..000000000 --- a/lib/puppet/network/server/rights.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'ipaddr' -require 'puppet/network/server/authstore' - -# Define a set of rights and who has access to them. -class Puppet::Network::Rights < Hash - # We basically just proxy directly to our rights. Each Right stores - # its own auth abilities. - [:allow, :allowed?, :deny].each do |method| - define_method(method) do |name, *args| - name = name.intern if name.is_a? String - - if obj = right(name) - obj.send(method, *args) - else - raise ArgumentError, "Unknown right '%s'" % name - end - end - end - - def [](name) - name = name.intern if name.is_a? String - super(name) - end - - # Define a new right to which access can be provided. - def newright(name) - name = name.intern if name.is_a? String - shortname = Right.shortname(name) - if self.include? name - raise ArgumentError, "Right '%s' is already defined" % name - else - self[name] = Right.new(name, shortname) - end - end - - private - - # Retrieve a right by name. - def right(name) - name = name.intern if name.is_a? String - self[name] - end - - # A right. - class Right < Puppet::Network::AuthStore - attr_accessor :name, :shortname - - Puppet::Util.logmethods(self, true) - - def self.shortname(name) - name.to_s[0..0] - end - - def initialize(name, shortname = nil) - @name = name - @shortname = shortname - unless @shortname - @shortname = Right.shortname(name) - end - super() - end - - def to_s - "access[%s]" % @name - end - - # There's no real check to do at this point - def valid? - true - end - end -end - -# $Id$ diff --git a/test/client/client.rb b/test/client/client.rb deleted file mode 100755 index f9964f096..000000000 --- a/test/client/client.rb +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' -require 'puppet/network/client' - -class TestClient < Test::Unit::TestCase - include PuppetTest::ServerTest - # a single run through of connect, auth, etc. - def test_sslInitWithAutosigningLocalServer - # autosign everything, for simplicity - Puppet[:autosign] = true - - # create a server to which to connect - mkserver() - - # create our client - client = nil - assert_nothing_raised { - client = Puppet::Network::Client::MasterClient.new( - :Server => "localhost", - :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(".")) - - assert(File.exists?(keyfile)) - 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 - } - - # 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_failureWithUntrustedCerts - Puppet[:autosign] = true - - # create a pair of clients with no certs - nonemaster = nil - assert_nothing_raised { - nonemaster = Puppet::Network::Client::MasterClient.new( - :Server => "localhost", - :Port => @@port - ) - } - - nonebucket = nil - assert_nothing_raised { - nonebucket = Puppet::Network::Client::Dipper.new( - :Server => "localhost", - :Port => @@port - ) - } - - # create a ca so we can create a set of certs - # make a new ssldir for it - ca = nil - assert_nothing_raised { - ca = Puppet::Network::Client::CA.new( - :CA => true, :Local => true - ) - ca.requestcert - } - - # initialize our clients with this set of certs - certmaster = nil - assert_nothing_raised { - certmaster = Puppet::Network::Client::MasterClient.new( - :Server => "localhost", - :Port => @@port - ) - } - - certbucket = nil - assert_nothing_raised { - certbucket = Puppet::Network::Client::Dipper.new( - :Server => "localhost", - :Port => @@port - ) - } - - # Create a new ssl root. - confdir = tempfile() - Puppet[:ssldir] = confdir - Puppet.config.mkdir(:ssldir) - Puppet.config.clearused - Puppet.config.use(:certificates, :ca) - - mkserver - - # now verify that our client cannot do non-cert operations - # because its certs are signed by a different CA - assert_raise(Puppet::Error, - "Client was allowed to call getconfig with no certs") { - nonemaster.getconfig - } - assert_raise(Puppet::Error, - "Client was allowed to call getconfig with untrusted certs") { - certmaster.getconfig - } - - assert_raise(Puppet::Network::NetworkClientError, - "Client was allowed to call backup with no certs") { - nonebucket.backup("/etc/passwd") - } - assert_raise(Puppet::Network::NetworkClientError, - "Client was allowed to call backup with untrusted certs") { - certbucket.backup("/etc/passwd") - } - end - - def test_classfile - manifest = tempfile() - - File.open(manifest, "w") do |file| - file.puts "class yaytest {}\n class bootest {}\n include yaytest, bootest" - end - - master = client = nil - assert_nothing_raised() { - master = Puppet::Network::Server::Master.new( - :Manifest => manifest, - :UseNodes => false, - :Local => false - ) - } - assert_nothing_raised() { - client = Puppet::Network::Client::MasterClient.new( - :Master => master - ) - } - - # Fake that it's local, so it creates the class file - client.local = false - - assert_nothing_raised { - client.getconfig - } - - assert(FileTest.exists?(Puppet[:classfile]), "Class file does not exist") - - classes = File.read(Puppet[:classfile]).split("\n") - - assert_equal(%w{bootest yaytest}, classes.sort) - end - - def test_setpidfile - FileUtils.mkdir_p(Puppet[:rundir]) - $clientrun = false - newclass = Class.new(Puppet::Network::Client) do - def run - $clientrun = true - end - - def initialize - end - end - - inst = newclass.new - - assert_nothing_raised { - inst.start - } - - assert(FileTest.exists?(inst.pidfile), - "PID file was not created") - end -end - -# $Id$ diff --git a/test/client/master.rb b/test/client/master.rb deleted file mode 100755 index b03a3ffd0..000000000 --- a/test/client/master.rb +++ /dev/null @@ -1,530 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' - -class TestMasterClient < Test::Unit::TestCase - include PuppetTest::ServerTest - - class FakeTrans - def initialize - @counters = Hash.new { |h,k| h[k] = 0 } - end - [:evaluate, :report, :cleanup, :addtimes, :tags, :ignoreschedules].each do |m| - define_method(m.to_s + "=") do |*args| - @counters[m] += 1 - end - define_method(m) do |*args| - @counters[m] += 1 - end - define_method(m.to_s + "?") do - @counters[m] - end - end - end - class FakeComponent - attr_accessor :trans - def evaluate - @trans = FakeTrans.new - @trans - end - - def finalize - @finalized = true - end - - def finalized? - @finalized - end - end - - def mkmaster(file = nil) - 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 - ) - } - return master - end - - def mkclient(master = nil) - master ||= mkmaster() - client = nil - assert_nothing_raised() { - client = Puppet::Network::Client::MasterClient.new( - :Master => master - ) - } - - return client - end - - def mk_fake_client - server = Puppet::Network::Server::Master.new :Code => "" - master = Puppet::Network::Client::MasterClient.new :Server => server, :Local => true - - # Now create some objects - objects = FakeComponent.new - - master.send(:instance_variable_set, "@objects", objects) - - class << master - def report(r) - @reported ||= 0 - @reported += 1 - end - def reported - @reported ||= 0 - @reported - end - end - return master, objects - end - - def test_apply - master, objects = mk_fake_client - - check = Proc.new do |hash| - assert(objects.trans, "transaction was not created") - trans = objects.trans - hash[:yes].each do |m| - assert_equal(1, trans.send(m.to_s + "?"), "did not call #{m} enough times") - end - hash[:no].each do |m| - assert_equal(0, trans.send(m.to_s + "?"), "called #{m} too many times") - end - end - - # First try it with no arguments - assert_nothing_raised do - master.apply - end - check.call :yes => %w{evaluate cleanup addtimes}, :no => %w{report tags ignoreschedules} - assert_equal(0, master.reported, "master sent report with reports disabled") - - - # Now enable reporting and make sure the report method gets called - Puppet[:report] = true - assert_nothing_raised do - master.apply - end - check.call :yes => %w{evaluate cleanup addtimes}, :no => %w{tags ignoreschedules} - assert_equal(1, master.reported, "master did not send report") - - # Now try it with tags enabled - assert_nothing_raised do - master.apply("tags") - end - check.call :yes => %w{evaluate cleanup tags addtimes}, :no => %w{ignoreschedules} - assert_equal(2, master.reported, "master did not send report") - - # and ignoreschedules - assert_nothing_raised do - master.apply("tags", true) - end - check.call :yes => %w{evaluate cleanup tags ignoreschedules addtimes}, :no => %w{} - assert_equal(3, master.reported, "master did not send report") - end - - def test_getconfig - client = mkclient - - $methodsrun = [] - cleanup { $methodsrun = nil } - client.meta_def(:getplugins) do - $methodsrun << :getplugins - end - client.meta_def(:get_actual_config) do - $methodsrun << :get_actual_config - result = Puppet::TransBucket.new() - result.type = "testing" - result.name = "yayness" - result - end - - assert_nothing_raised do - client.getconfig - end - [:get_actual_config].each do |method| - assert($methodsrun.include?(method), "method %s was not run" % method) - end - assert(! $methodsrun.include?(:getplugins), "plugins were synced even tho disabled") - - # Now set pluginsync - Puppet[:pluginsync] = true - $methodsrun.clear - - assert_nothing_raised do - client.getconfig - end - [:getplugins, :get_actual_config].each do |method| - assert($methodsrun.include?(method), "method %s was not run" % method) - end - - objects = client.objects - assert(objects.finalized?, "objects were not finalized") - end - - def test_disable - FileUtils.mkdir_p(Puppet[:statedir]) - manifest = mktestmanifest - - master = mkmaster(manifest) - - client = mkclient(master) - - assert(! FileTest.exists?(@createdfile)) - - assert_nothing_raised { - client.disable - } - - assert_nothing_raised { - client.run - } - - assert(! FileTest.exists?(@createdfile), "Disabled client ran") - - assert_nothing_raised { - client.enable - } - - assert_nothing_raised { - client.run - } - - assert(FileTest.exists?(@createdfile), "Enabled client did not run") - end - - # Make sure we're getting the client version in our list of facts - def test_clientversionfact - facts = nil - assert_nothing_raised { - facts = Puppet::Network::Client::MasterClient.facts - } - - assert_equal(Puppet.version.to_s, facts["clientversion"]) - - end - - # Make sure non-string facts don't make things go kablooie - def test_nonstring_facts - FileUtils.mkdir_p(Puppet[:statedir]) - # Add a nonstring fact - Facter.add("nonstring") do - setcode { 1 } - end - - assert_equal(1, Facter.nonstring, "Fact was a string from facter") - - client = mkclient() - - assert(! FileTest.exists?(@createdfile)) - - assert_nothing_raised { - client.run - } - end - - # This method is supposed - def test_download - source = tempfile() - dest = tempfile() - sfile = File.join(source, "file") - dfile = File.join(dest, "file") - Dir.mkdir(source) - File.open(sfile, "w") {|f| f.puts "yay"} - - files = [] - assert_nothing_raised do - files = Puppet::Network::Client::MasterClient.download(:dest => dest, :source => source, :name => "testing") - end - - assert(FileTest.directory?(dest), "dest dir was not created") - assert(FileTest.file?(dfile), "dest file was not created") - assert_equal(File.read(sfile), File.read(dfile), "Dest file had incorrect contents") - assert_equal([dest, dfile].sort, files.sort, "Changed files were not returned correctly") - end - - def test_getplugins - Puppet[:pluginsource] = tempfile() - Dir.mkdir(Puppet[:pluginsource]) - - myplugin = File.join(Puppet[:pluginsource], "myplugin.rb") - File.open(myplugin, "w") do |f| - f.puts %{Puppet::Type.newtype(:myplugin) do - newparam(:argument) do - isnamevar - end -end -} - end - - assert_nothing_raised { - Puppet::Network::Client::MasterClient.getplugins - } - - destfile = File.join(Puppet[:plugindest], "myplugin.rb") - - assert(File.exists?(destfile), "Did not get plugin") - - obj = Puppet::Type.type(:myplugin) - - assert(obj, "Did not define type") - - assert(obj.validattr?(:argument), - "Did not get namevar") - - # Now modify the file and make sure the type is replaced - File.open(myplugin, "w") do |f| - f.puts %{Puppet::Type.newtype(:myplugin) do - newparam(:yayness) do - isnamevar - end - - newparam(:rahness) do - end -end -} - end - - assert_nothing_raised { - Puppet::Network::Client::MasterClient.getplugins - } - - destfile = File.join(Puppet[:pluginpath], "myplugin.rb") - - obj = Puppet::Type.type(:myplugin) - - assert(obj, "Did not define type") - - assert(obj.validattr?(:yayness), - "Did not get namevar") - - assert(obj.validattr?(:rahness), - "Did not get other var") - - assert(! obj.validattr?(:argument), - "Old namevar is still valid") - - # Now try it again, to make sure we don't have any objects lying around - assert_nothing_raised { - Puppet::Network::Client::MasterClient.getplugins - } - end - - def test_getfacts - Puppet[:factsource] = tempfile() - Dir.mkdir(Puppet[:factsource]) - hostname = Facter.value(:hostname) - - myfact = File.join(Puppet[:factsource], "myfact.rb") - File.open(myfact, "w") do |f| - f.puts %{Facter.add("myfact") do - setcode { "yayness" } -end -} - end - - assert_nothing_raised { - Puppet::Network::Client::MasterClient.getfacts - } - - destfile = File.join(Puppet[:factdest], "myfact.rb") - - assert(File.exists?(destfile), "Did not get fact") - - assert_equal(hostname, Facter.value(:hostname), - "Lost value to hostname") - assert_equal("yayness", Facter.value(:myfact), - "Did not get correct fact value") - - # Now modify the file and make sure the type is replaced - File.open(myfact, "w") do |f| - f.puts %{Facter.add("myfact") do - setcode { "funtest" } -end -} - end - - assert_nothing_raised { - Puppet::Network::Client::MasterClient.getfacts - } - - assert_equal("funtest", Facter.value(:myfact), - "Did not reload fact") - assert_equal(hostname, Facter.value(:hostname), - "Lost value to hostname") - - # Now run it again and make sure the fact still loads - assert_nothing_raised { - Puppet::Network::Client::MasterClient.getfacts - } - - assert_equal("funtest", Facter.value(:myfact), - "Did not reload fact") - assert_equal(hostname, Facter.value(:hostname), - "Lost value to hostname") - end - - # Make sure we load all facts on startup. - def test_loadfacts - dirs = [tempfile(), tempfile()] - count = 0 - names = [] - dirs.each do |dir| - Dir.mkdir(dir) - name = "fact%s" % count - names << name - file = File.join(dir, "%s.rb" % name) - - # Write out a plugin file - File.open(file, "w") do |f| - f.puts %{Facter.add("#{name}") do setcode { "#{name}" } end } - end - count += 1 - end - - Puppet[:factpath] = dirs.join(":") - - names.each do |name| - assert_nil(Facter.value(name), "Somehow retrieved invalid fact") - end - - assert_nothing_raised { - Puppet::Network::Client::MasterClient.loadfacts - } - - names.each do |name| - assert_equal(name, Facter.value(name), - "Did not retrieve facts") - end - end - - if Process.uid == 0 - # Testing #283. Make sure plugins et al are downloaded as the running user. - def test_download_ownership - dir = tstdir() - dest = tstdir() - file = File.join(dir, "file") - File.open(file, "w") { |f| f.puts "funtest" } - - user = nonrootuser() - group = nonrootgroup() - chowner = Puppet::Type.type(:file).create :path => dir, - :owner => user.name, :group => group.name, :recurse => true - assert_apply(chowner) - chowner.remove - - assert_equal(user.uid, File.stat(file).uid) - assert_equal(group.gid, File.stat(file).gid) - - - assert_nothing_raised { - Puppet::Network::Client::MasterClient.download(:dest => dest, :source => dir, - :name => "testing" - ) {} - } - - destfile = File.join(dest, "file") - - assert(FileTest.exists?(destfile), "Did not create destfile") - - assert_equal(Process.uid, File.stat(destfile).uid) - end - end - - # Test retrieving all of the facts. - def test_facts - facts = nil - assert_nothing_raised do - facts = Puppet::Network::Client::MasterClient.facts - end - Facter.to_hash.each do |fact, value| - assert_equal(facts[fact.downcase], value, "%s is not equal" % fact.inspect) - end - - # Make sure the puppet version got added - assert_equal(Puppet::PUPPETVERSION, facts["clientversion"], "client version did not get added") - - # And make sure the ruby version is in there - assert_equal(RUBY_VERSION, facts["rubyversion"], "ruby version did not get added") - end - - # #424 - def test_caching_of_compile_time - file = tempfile() - manifest = tempfile() - File.open(manifest, "w") { |f| f.puts "file { '#{file}': content => yay }" } - - driver = mkmaster(manifest) - driver.local = false - master = mkclient(driver) - - # We have to make everything thinks it's remote, because there's no local caching info - master.local = false - - assert(! master.fresh?, "Considered fresh with no compile at all") - - assert_nothing_raised { master.run } - assert(master.fresh?, "not considered fresh after compile") - - # Now make sure the config time is cached - assert(master.compile_time, "No stored config time") - assert_equal(master.compile_time, Puppet::Util::Storage.cache(:configuration)[:compile_time], "times did not match") - time = master.compile_time - master.clear - File.unlink(file) - Puppet::Util::Storage.store - - # Now make a new master - Puppet::Util::Storage.clear - master = mkclient(driver) - master.run - assert_equal(time, master.compile_time, "time was not retrieved from cache") - assert(FileTest.exists?(file), "file was not created on second run") - end - - def test_default_objects - # Make sure they start out missing - assert_nil(Puppet::Type.type(:filebucket)["puppet"], - "default filebucket already exists") - assert_nil(Puppet::Type.type(:schedule)["daily"], - "default schedules already exists") - - master = mkclient() - - # Now make sure they got created - assert(Puppet::Type.type(:filebucket)["puppet"], - "default filebucket not found") - assert(Puppet::Type.type(:schedule)["daily"], - "default schedules not found") - - # clear everything, and make sure we can recreate them - Puppet::Type.allclear - assert_nil(Puppet::Type.type(:filebucket)["puppet"], - "default filebucket not removed") - assert_nil(Puppet::Type.type(:schedule)["daily"], - "default schedules not removed") - assert_nothing_raised { master.mkdefault_objects } - assert(Puppet::Type.type(:filebucket)["puppet"], - "default filebucket not found") - assert(Puppet::Type.type(:schedule)["daily"], - "default schedules not found") - - - # Make sure we've got schedules - assert(Puppet::Type.type(:schedule)["hourly"], "Could not retrieve hourly schedule") - assert(Puppet::Type.type(:filebucket)["puppet"], "Could not retrieve default bucket") - end -end - -# $Id$ diff --git a/test/client/networkclient.rb b/test/client/networkclient.rb deleted file mode 100755 index f7920169f..000000000 --- a/test/client/networkclient.rb +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' -require 'puppet/network/client' - -class TestClient < Test::Unit::TestCase - def test_set_backtrace - error = Puppet::Network::NetworkClientError.new("An error") - assert_nothing_raised do - error.set_backtrace ["caller"] - end - end -end - -# $Id$ - diff --git a/test/client/resource.rb b/test/client/resource.rb deleted file mode 100755 index 357a0afbe..000000000 --- a/test/client/resource.rb +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' -require 'puppet/network/client/resource' - -class TestResourceClient < Test::Unit::TestCase - include PuppetTest::ServerTest - - def mkresourceserver - handlers = { - :CA => {}, # so that certs autogenerate - :Resource => {}, - } - - return mkserver(handlers) - end - - def mkclient - client = nil - assert_nothing_raised { - client = Puppet::Network::Client::Resource.new(:Server => "localhost", - :Port => @@port) - } - - return client - end - - def test_resources - file = tempfile() - text = "yayness\n" - File.open(file, "w") { |f| f.print text } - - mkresourceserver() - - client = mkclient() - - # Test describing - tobj = nil - assert_nothing_raised { - tobj = client.describe("file", file) - } - - assert(tobj, "Did not get response") - - assert_instance_of(Puppet::TransObject, tobj) - - obj = nil - assert_nothing_raised { - obj = tobj.to_type - } - assert_events([], obj) - File.unlink(file) - assert_events([:file_created], obj) - File.unlink(file) - - # Now test applying - result = nil - assert_nothing_raised { - result = client.apply(tobj) - } - assert(FileTest.exists?(file), "File was not created on apply") - - # Lastly, test "list" - list = nil - assert_nothing_raised { - list = client.list("user") - } - - assert_instance_of(Puppet::TransBucket, list) - - count = 0 - list.each do |tobj| - break if count > 3 - assert_instance_of(Puppet::TransObject, tobj) - - tobj2 = nil - assert_nothing_raised { - tobj2 = client.describe(tobj.type, tobj.name) - } - - obj = nil - assert_nothing_raised { - obj = tobj2.to_type - } - assert_events([], obj) - - count += 1 - end - end -end - -# $Id$ diff --git a/test/network/client/client.rb b/test/network/client/client.rb new file mode 100755 index 000000000..7fd2afb71 --- /dev/null +++ b/test/network/client/client.rb @@ -0,0 +1,193 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/client' + +class TestClient < Test::Unit::TestCase + include PuppetTest::ServerTest + # a single run through of connect, auth, etc. + def test_sslInitWithAutosigningLocalServer + # autosign everything, for simplicity + Puppet[:autosign] = true + + # create a server to which to connect + mkserver() + + # create our client + client = nil + assert_nothing_raised { + client = Puppet::Network::Client::MasterClient.new( + :Server => "localhost", + :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(".")) + + assert(File.exists?(keyfile)) + 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 + } + + # 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_failureWithUntrustedCerts + Puppet[:autosign] = true + + # create a pair of clients with no certs + nonemaster = nil + assert_nothing_raised { + nonemaster = Puppet::Network::Client::MasterClient.new( + :Server => "localhost", + :Port => @@port + ) + } + + nonebucket = nil + assert_nothing_raised { + nonebucket = Puppet::Network::Client::Dipper.new( + :Server => "localhost", + :Port => @@port + ) + } + + # create a ca so we can create a set of certs + # make a new ssldir for it + ca = nil + assert_nothing_raised { + ca = Puppet::Network::Client::CA.new( + :CA => true, :Local => true + ) + ca.requestcert + } + + # initialize our clients with this set of certs + certmaster = nil + assert_nothing_raised { + certmaster = Puppet::Network::Client::MasterClient.new( + :Server => "localhost", + :Port => @@port + ) + } + + certbucket = nil + assert_nothing_raised { + certbucket = Puppet::Network::Client::Dipper.new( + :Server => "localhost", + :Port => @@port + ) + } + + # Create a new ssl root. + confdir = tempfile() + Puppet[:ssldir] = confdir + Puppet.config.mkdir(:ssldir) + Puppet.config.clearused + Puppet.config.use(:certificates, :ca) + + mkserver + + # now verify that our client cannot do non-cert operations + # because its certs are signed by a different CA + assert_raise(Puppet::Error, + "Client was allowed to call getconfig with no certs") { + nonemaster.getconfig + } + assert_raise(Puppet::Error, + "Client was allowed to call getconfig with untrusted certs") { + certmaster.getconfig + } + + assert_raise(Puppet::Network::NetworkClientError, + "Client was allowed to call backup with no certs") { + nonebucket.backup("/etc/passwd") + } + assert_raise(Puppet::Network::NetworkClientError, + "Client was allowed to call backup with untrusted certs") { + certbucket.backup("/etc/passwd") + } + end + + def test_classfile + manifest = tempfile() + + File.open(manifest, "w") do |file| + file.puts "class yaytest {}\n class bootest {}\n include yaytest, bootest" + end + + master = client = nil + assert_nothing_raised() { + master = Puppet::Network::Server::Master.new( + :Manifest => manifest, + :UseNodes => false, + :Local => false + ) + } + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Master => master + ) + } + + # Fake that it's local, so it creates the class file + client.local = false + + assert_nothing_raised { + client.getconfig + } + + assert(FileTest.exists?(Puppet[:classfile]), "Class file does not exist") + + classes = File.read(Puppet[:classfile]).split("\n") + + assert_equal(%w{bootest yaytest}, classes.sort) + end + + def test_setpidfile + FileUtils.mkdir_p(Puppet[:rundir]) + $clientrun = false + newclass = Class.new(Puppet::Network::Client) do + def run + $clientrun = true + end + + def initialize + end + end + + inst = newclass.new + + assert_nothing_raised { + inst.start + } + + assert(FileTest.exists?(inst.pidfile), + "PID file was not created") + end +end + +# $Id$ diff --git a/test/network/client/master.rb b/test/network/client/master.rb new file mode 100755 index 000000000..de94cd93a --- /dev/null +++ b/test/network/client/master.rb @@ -0,0 +1,530 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' + +class TestMasterClient < Test::Unit::TestCase + include PuppetTest::ServerTest + + class FakeTrans + def initialize + @counters = Hash.new { |h,k| h[k] = 0 } + end + [:evaluate, :report, :cleanup, :addtimes, :tags, :ignoreschedules].each do |m| + define_method(m.to_s + "=") do |*args| + @counters[m] += 1 + end + define_method(m) do |*args| + @counters[m] += 1 + end + define_method(m.to_s + "?") do + @counters[m] + end + end + end + class FakeComponent + attr_accessor :trans + def evaluate + @trans = FakeTrans.new + @trans + end + + def finalize + @finalized = true + end + + def finalized? + @finalized + end + end + + def mkmaster(file = nil) + 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 + ) + } + return master + end + + def mkclient(master = nil) + master ||= mkmaster() + client = nil + assert_nothing_raised() { + client = Puppet::Network::Client::MasterClient.new( + :Master => master + ) + } + + return client + end + + def mk_fake_client + server = Puppet::Network::Server::Master.new :Code => "" + master = Puppet::Network::Client::MasterClient.new :Server => server, :Local => true + + # Now create some objects + objects = FakeComponent.new + + master.send(:instance_variable_set, "@objects", objects) + + class << master + def report(r) + @reported ||= 0 + @reported += 1 + end + def reported + @reported ||= 0 + @reported + end + end + return master, objects + end + + def test_apply + master, objects = mk_fake_client + + check = Proc.new do |hash| + assert(objects.trans, "transaction was not created") + trans = objects.trans + hash[:yes].each do |m| + assert_equal(1, trans.send(m.to_s + "?"), "did not call #{m} enough times") + end + hash[:no].each do |m| + assert_equal(0, trans.send(m.to_s + "?"), "called #{m} too many times") + end + end + + # First try it with no arguments + assert_nothing_raised do + master.apply + end + check.call :yes => %w{evaluate cleanup addtimes}, :no => %w{report tags ignoreschedules} + assert_equal(0, master.reported, "master sent report with reports disabled") + + + # Now enable reporting and make sure the report method gets called + Puppet[:report] = true + assert_nothing_raised do + master.apply + end + check.call :yes => %w{evaluate cleanup addtimes}, :no => %w{tags ignoreschedules} + assert_equal(1, master.reported, "master did not send report") + + # Now try it with tags enabled + assert_nothing_raised do + master.apply("tags") + end + check.call :yes => %w{evaluate cleanup tags addtimes}, :no => %w{ignoreschedules} + assert_equal(2, master.reported, "master did not send report") + + # and ignoreschedules + assert_nothing_raised do + master.apply("tags", true) + end + check.call :yes => %w{evaluate cleanup tags ignoreschedules addtimes}, :no => %w{} + assert_equal(3, master.reported, "master did not send report") + end + + def test_getconfig + client = mkclient + + $methodsrun = [] + cleanup { $methodsrun = nil } + client.meta_def(:getplugins) do + $methodsrun << :getplugins + end + client.meta_def(:get_actual_config) do + $methodsrun << :get_actual_config + result = Puppet::TransBucket.new() + result.type = "testing" + result.name = "yayness" + result + end + + assert_nothing_raised do + client.getconfig + end + [:get_actual_config].each do |method| + assert($methodsrun.include?(method), "method %s was not run" % method) + end + assert(! $methodsrun.include?(:getplugins), "plugins were synced even tho disabled") + + # Now set pluginsync + Puppet[:pluginsync] = true + $methodsrun.clear + + assert_nothing_raised do + client.getconfig + end + [:getplugins, :get_actual_config].each do |method| + assert($methodsrun.include?(method), "method %s was not run" % method) + end + + objects = client.objects + assert(objects.finalized?, "objects were not finalized") + end + + def test_disable + FileUtils.mkdir_p(Puppet[:statedir]) + manifest = mktestmanifest + + master = mkmaster(manifest) + + client = mkclient(master) + + assert(! FileTest.exists?(@createdfile)) + + assert_nothing_raised { + client.disable + } + + assert_nothing_raised { + client.run + } + + assert(! FileTest.exists?(@createdfile), "Disabled client ran") + + assert_nothing_raised { + client.enable + } + + assert_nothing_raised { + client.run + } + + assert(FileTest.exists?(@createdfile), "Enabled client did not run") + end + + # Make sure we're getting the client version in our list of facts + def test_clientversionfact + facts = nil + assert_nothing_raised { + facts = Puppet::Network::Client::MasterClient.facts + } + + assert_equal(Puppet.version.to_s, facts["clientversion"]) + + end + + # Make sure non-string facts don't make things go kablooie + def test_nonstring_facts + FileUtils.mkdir_p(Puppet[:statedir]) + # Add a nonstring fact + Facter.add("nonstring") do + setcode { 1 } + end + + assert_equal(1, Facter.nonstring, "Fact was a string from facter") + + client = mkclient() + + assert(! FileTest.exists?(@createdfile)) + + assert_nothing_raised { + client.run + } + end + + # This method is supposed + def test_download + source = tempfile() + dest = tempfile() + sfile = File.join(source, "file") + dfile = File.join(dest, "file") + Dir.mkdir(source) + File.open(sfile, "w") {|f| f.puts "yay"} + + files = [] + assert_nothing_raised do + files = Puppet::Network::Client::MasterClient.download(:dest => dest, :source => source, :name => "testing") + end + + assert(FileTest.directory?(dest), "dest dir was not created") + assert(FileTest.file?(dfile), "dest file was not created") + assert_equal(File.read(sfile), File.read(dfile), "Dest file had incorrect contents") + assert_equal([dest, dfile].sort, files.sort, "Changed files were not returned correctly") + end + + def test_getplugins + Puppet[:pluginsource] = tempfile() + Dir.mkdir(Puppet[:pluginsource]) + + myplugin = File.join(Puppet[:pluginsource], "myplugin.rb") + File.open(myplugin, "w") do |f| + f.puts %{Puppet::Type.newtype(:myplugin) do + newparam(:argument) do + isnamevar + end +end +} + end + + assert_nothing_raised { + Puppet::Network::Client::MasterClient.getplugins + } + + destfile = File.join(Puppet[:plugindest], "myplugin.rb") + + assert(File.exists?(destfile), "Did not get plugin") + + obj = Puppet::Type.type(:myplugin) + + assert(obj, "Did not define type") + + assert(obj.validattr?(:argument), + "Did not get namevar") + + # Now modify the file and make sure the type is replaced + File.open(myplugin, "w") do |f| + f.puts %{Puppet::Type.newtype(:myplugin) do + newparam(:yayness) do + isnamevar + end + + newparam(:rahness) do + end +end +} + end + + assert_nothing_raised { + Puppet::Network::Client::MasterClient.getplugins + } + + destfile = File.join(Puppet[:pluginpath], "myplugin.rb") + + obj = Puppet::Type.type(:myplugin) + + assert(obj, "Did not define type") + + assert(obj.validattr?(:yayness), + "Did not get namevar") + + assert(obj.validattr?(:rahness), + "Did not get other var") + + assert(! obj.validattr?(:argument), + "Old namevar is still valid") + + # Now try it again, to make sure we don't have any objects lying around + assert_nothing_raised { + Puppet::Network::Client::MasterClient.getplugins + } + end + + def test_getfacts + Puppet[:factsource] = tempfile() + Dir.mkdir(Puppet[:factsource]) + hostname = Facter.value(:hostname) + + myfact = File.join(Puppet[:factsource], "myfact.rb") + File.open(myfact, "w") do |f| + f.puts %{Facter.add("myfact") do + setcode { "yayness" } +end +} + end + + assert_nothing_raised { + Puppet::Network::Client::MasterClient.getfacts + } + + destfile = File.join(Puppet[:factdest], "myfact.rb") + + assert(File.exists?(destfile), "Did not get fact") + + assert_equal(hostname, Facter.value(:hostname), + "Lost value to hostname") + assert_equal("yayness", Facter.value(:myfact), + "Did not get correct fact value") + + # Now modify the file and make sure the type is replaced + File.open(myfact, "w") do |f| + f.puts %{Facter.add("myfact") do + setcode { "funtest" } +end +} + end + + assert_nothing_raised { + Puppet::Network::Client::MasterClient.getfacts + } + + assert_equal("funtest", Facter.value(:myfact), + "Did not reload fact") + assert_equal(hostname, Facter.value(:hostname), + "Lost value to hostname") + + # Now run it again and make sure the fact still loads + assert_nothing_raised { + Puppet::Network::Client::MasterClient.getfacts + } + + assert_equal("funtest", Facter.value(:myfact), + "Did not reload fact") + assert_equal(hostname, Facter.value(:hostname), + "Lost value to hostname") + end + + # Make sure we load all facts on startup. + def test_loadfacts + dirs = [tempfile(), tempfile()] + count = 0 + names = [] + dirs.each do |dir| + Dir.mkdir(dir) + name = "fact%s" % count + names << name + file = File.join(dir, "%s.rb" % name) + + # Write out a plugin file + File.open(file, "w") do |f| + f.puts %{Facter.add("#{name}") do setcode { "#{name}" } end } + end + count += 1 + end + + Puppet[:factpath] = dirs.join(":") + + names.each do |name| + assert_nil(Facter.value(name), "Somehow retrieved invalid fact") + end + + assert_nothing_raised { + Puppet::Network::Client::MasterClient.loadfacts + } + + names.each do |name| + assert_equal(name, Facter.value(name), + "Did not retrieve facts") + end + end + + if Process.uid == 0 + # Testing #283. Make sure plugins et al are downloaded as the running user. + def test_download_ownership + dir = tstdir() + dest = tstdir() + file = File.join(dir, "file") + File.open(file, "w") { |f| f.puts "funtest" } + + user = nonrootuser() + group = nonrootgroup() + chowner = Puppet::Type.type(:file).create :path => dir, + :owner => user.name, :group => group.name, :recurse => true + assert_apply(chowner) + chowner.remove + + assert_equal(user.uid, File.stat(file).uid) + assert_equal(group.gid, File.stat(file).gid) + + + assert_nothing_raised { + Puppet::Network::Client::MasterClient.download(:dest => dest, :source => dir, + :name => "testing" + ) {} + } + + destfile = File.join(dest, "file") + + assert(FileTest.exists?(destfile), "Did not create destfile") + + assert_equal(Process.uid, File.stat(destfile).uid) + end + end + + # Test retrieving all of the facts. + def test_facts + facts = nil + assert_nothing_raised do + facts = Puppet::Network::Client::MasterClient.facts + end + Facter.to_hash.each do |fact, value| + assert_equal(facts[fact.downcase], value, "%s is not equal" % fact.inspect) + end + + # Make sure the puppet version got added + assert_equal(Puppet::PUPPETVERSION, facts["clientversion"], "client version did not get added") + + # And make sure the ruby version is in there + assert_equal(RUBY_VERSION, facts["rubyversion"], "ruby version did not get added") + end + + # #424 + def test_caching_of_compile_time + file = tempfile() + manifest = tempfile() + File.open(manifest, "w") { |f| f.puts "file { '#{file}': content => yay }" } + + driver = mkmaster(manifest) + driver.local = false + master = mkclient(driver) + + # We have to make everything thinks it's remote, because there's no local caching info + master.local = false + + assert(! master.fresh?, "Considered fresh with no compile at all") + + assert_nothing_raised { master.run } + assert(master.fresh?, "not considered fresh after compile") + + # Now make sure the config time is cached + assert(master.compile_time, "No stored config time") + assert_equal(master.compile_time, Puppet::Util::Storage.cache(:configuration)[:compile_time], "times did not match") + time = master.compile_time + master.clear + File.unlink(file) + Puppet::Util::Storage.store + + # Now make a new master + Puppet::Util::Storage.clear + master = mkclient(driver) + master.run + assert_equal(time, master.compile_time, "time was not retrieved from cache") + assert(FileTest.exists?(file), "file was not created on second run") + end + + def test_default_objects + # Make sure they start out missing + assert_nil(Puppet::Type.type(:filebucket)["puppet"], + "default filebucket already exists") + assert_nil(Puppet::Type.type(:schedule)["daily"], + "default schedules already exists") + + master = mkclient() + + # Now make sure they got created + assert(Puppet::Type.type(:filebucket)["puppet"], + "default filebucket not found") + assert(Puppet::Type.type(:schedule)["daily"], + "default schedules not found") + + # clear everything, and make sure we can recreate them + Puppet::Type.allclear + assert_nil(Puppet::Type.type(:filebucket)["puppet"], + "default filebucket not removed") + assert_nil(Puppet::Type.type(:schedule)["daily"], + "default schedules not removed") + assert_nothing_raised { master.mkdefault_objects } + assert(Puppet::Type.type(:filebucket)["puppet"], + "default filebucket not found") + assert(Puppet::Type.type(:schedule)["daily"], + "default schedules not found") + + + # Make sure we've got schedules + assert(Puppet::Type.type(:schedule)["hourly"], "Could not retrieve hourly schedule") + assert(Puppet::Type.type(:filebucket)["puppet"], "Could not retrieve default bucket") + end +end + +# $Id$ diff --git a/test/network/client/networkclient.rb b/test/network/client/networkclient.rb new file mode 100755 index 000000000..957a1ceda --- /dev/null +++ b/test/network/client/networkclient.rb @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/client' + +class TestClient < Test::Unit::TestCase + def test_set_backtrace + error = Puppet::Network::NetworkClientError.new("An error") + assert_nothing_raised do + error.set_backtrace ["caller"] + end + end +end + +# $Id$ + diff --git a/test/network/client/resource.rb b/test/network/client/resource.rb new file mode 100755 index 000000000..fcbb367ca --- /dev/null +++ b/test/network/client/resource.rb @@ -0,0 +1,94 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/client/resource' + +class TestResourceClient < Test::Unit::TestCase + include PuppetTest::ServerTest + + def mkresourceserver + handlers = { + :CA => {}, # so that certs autogenerate + :Resource => {}, + } + + return mkserver(handlers) + end + + def mkclient + client = nil + assert_nothing_raised { + client = Puppet::Network::Client::Resource.new(:Server => "localhost", + :Port => @@port) + } + + return client + end + + def test_resources + file = tempfile() + text = "yayness\n" + File.open(file, "w") { |f| f.print text } + + mkresourceserver() + + client = mkclient() + + # Test describing + tobj = nil + assert_nothing_raised { + tobj = client.describe("file", file) + } + + assert(tobj, "Did not get response") + + assert_instance_of(Puppet::TransObject, tobj) + + obj = nil + assert_nothing_raised { + obj = tobj.to_type + } + assert_events([], obj) + File.unlink(file) + assert_events([:file_created], obj) + File.unlink(file) + + # Now test applying + result = nil + assert_nothing_raised { + result = client.apply(tobj) + } + assert(FileTest.exists?(file), "File was not created on apply") + + # Lastly, test "list" + list = nil + assert_nothing_raised { + list = client.list("user") + } + + assert_instance_of(Puppet::TransBucket, list) + + count = 0 + list.each do |tobj| + break if count > 3 + assert_instance_of(Puppet::TransObject, tobj) + + tobj2 = nil + assert_nothing_raised { + tobj2 = client.describe(tobj.type, tobj.name) + } + + obj = nil + assert_nothing_raised { + obj = tobj2.to_type + } + assert_events([], obj) + + count += 1 + end + end +end + +# $Id$ 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$ diff --git a/test/server/authconfig.rb b/test/server/authconfig.rb deleted file mode 100755 index cc7d6cdfd..000000000 --- a/test/server/authconfig.rb +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' - -require 'puppet/network/server/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/server/authstore.rb b/test/server/authstore.rb deleted file mode 100755 index d9df9a441..000000000 --- a/test/server/authstore.rb +++ /dev/null @@ -1,211 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' - -require 'puppet/network/server/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/server/bucket.rb b/test/server/bucket.rb deleted file mode 100755 index 938db748e..000000000 --- a/test/server/bucket.rb +++ /dev/null @@ -1,259 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/ca.rb b/test/server/ca.rb deleted file mode 100755 index e9cc89cde..000000000 --- a/test/server/ca.rb +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/fileserver.rb b/test/server/fileserver.rb deleted file mode 100755 index 25c72a5fb..000000000 --- a/test/server/fileserver.rb +++ /dev/null @@ -1,1024 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/logger.rb b/test/server/logger.rb deleted file mode 100755 index 83e834365..000000000 --- a/test/server/logger.rb +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/master.rb b/test/server/master.rb deleted file mode 100755 index ba52908d3..000000000 --- a/test/server/master.rb +++ /dev/null @@ -1,346 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/report.rb b/test/server/report.rb deleted file mode 100755 index bf652feaf..000000000 --- a/test/server/report.rb +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/resource.rb b/test/server/resource.rb deleted file mode 100755 index 8e6581083..000000000 --- a/test/server/resource.rb +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/rights.rb b/test/server/rights.rb deleted file mode 100755 index e5c65babe..000000000 --- a/test/server/rights.rb +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' -require 'puppet/network/server/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/server/runner.rb b/test/server/runner.rb deleted file mode 100755 index 9d4cf41be..000000000 --- a/test/server/runner.rb +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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/server/server.rb b/test/server/server.rb deleted file mode 100755 index 4e79e00b7..000000000 --- a/test/server/server.rb +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").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$ -- cgit