diff options
| author | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-09-23 20:42:08 +0000 |
|---|---|---|
| committer | luke <luke@980ebf18-57e1-0310-9a29-db15c13687c0> | 2005-09-23 20:42:08 +0000 |
| commit | 8211df036e1d2d24e1084616fc3fc4891b06cfdd (patch) | |
| tree | 597f8b999cf5210a7ceff5ef1e1977f1de08c241 | |
| parent | d20ac8e0b564e5413d571f2059de559e0783b72d (diff) | |
| download | puppet-8211df036e1d2d24e1084616fc3fc4891b06cfdd.tar.gz puppet-8211df036e1d2d24e1084616fc3fc4891b06cfdd.tar.xz puppet-8211df036e1d2d24e1084616fc3fc4891b06cfdd.zip | |
Many, many changes toward a completely functional system. The only current problems with my home config are that apache's stupid init script does not do status and that packages are not working as non-root users (which makes sense).
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@703 980ebf18-57e1-0310-9a29-db15c13687c0
| -rwxr-xr-x | bin/puppet | 23 | ||||
| -rwxr-xr-x | bin/puppetd | 7 | ||||
| -rwxr-xr-x | bin/puppetmasterd | 10 | ||||
| -rw-r--r-- | lib/puppet/client.rb | 37 | ||||
| -rw-r--r-- | lib/puppet/parser/ast.rb | 8 | ||||
| -rw-r--r-- | lib/puppet/parser/grammar.ra | 37 | ||||
| -rw-r--r-- | lib/puppet/parser/interpreter.rb | 30 | ||||
| -rw-r--r-- | lib/puppet/parser/parser.rb | 41 | ||||
| -rw-r--r-- | lib/puppet/parser/scope.rb | 17 | ||||
| -rw-r--r-- | lib/puppet/server.rb | 2 | ||||
| -rwxr-xr-x | lib/puppet/server/fileserver.rb | 73 | ||||
| -rw-r--r-- | lib/puppet/server/master.rb | 4 | ||||
| -rw-r--r-- | lib/puppet/server/servlet.rb | 51 | ||||
| -rw-r--r-- | lib/puppet/statechange.rb | 18 | ||||
| -rw-r--r-- | lib/puppet/type.rb | 7 | ||||
| -rw-r--r-- | lib/puppet/type/package.rb | 12 | ||||
| -rw-r--r-- | lib/puppet/type/pfile.rb | 149 | ||||
| -rw-r--r-- | lib/puppet/type/state.rb | 9 | ||||
| -rwxr-xr-x | test/language/tc_snippets.rb | 3 | ||||
| -rw-r--r-- | test/parser/tc_parser.rb | 116 | ||||
| -rwxr-xr-x | test/server/tc_fileserver.rb | 98 | ||||
| -rw-r--r-- | test/types/tc_fileignoresource.rb | 4 | ||||
| -rwxr-xr-x | test/types/tc_filesources.rb | 106 | ||||
| -rw-r--r-- | test/types/tc_type.rb | 4 |
24 files changed, 679 insertions, 187 deletions
diff --git a/bin/puppet b/bin/puppet index d3eead009..25807ee1a 100755 --- a/bin/puppet +++ b/bin/puppet @@ -18,6 +18,10 @@ # # = Options # +# confdir:: +# The configuration root directory, where +puppetmasterd+ defaults to looking +# for all of its configuration files. Defaults to +/etc/puppet+. +# # debug:: # Enable full debugging. # @@ -61,11 +65,13 @@ rescue LoadError end result = GetoptLong.new( + [ "--confdir", "-c", GetoptLong::REQUIRED_ARGUMENT ], [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ], [ "--logdest", "-l", GetoptLong::REQUIRED_ARGUMENT ], [ "--verbose", "-v", GetoptLong::NO_ARGUMENT ], [ "--noop", "-n", GetoptLong::NO_ARGUMENT ], + [ "--use-nodes", GetoptLong::NO_ARGUMENT ], [ "--parse-only", "-p", GetoptLong::NO_ARGUMENT ], [ "--version", "-V", GetoptLong::NO_ARGUMENT ] ) @@ -76,9 +82,15 @@ noop = false logfile = false parseonly = false +master = { + :Local => true +} + begin result.each { |opt,arg| case opt + when "--confdir" + Puppet[:puppetconf] = arg when "--version" puts "%s" % Puppet.version exit @@ -90,7 +102,9 @@ begin exit end when "--noop" - noop = true + Puppet[:noop] = true + when "--use-nodes" + master[:UseNodes] = true when "--verbose" verbose = true when "--parse-only" @@ -121,11 +135,10 @@ elsif verbose Puppet[:loglevel] = :info end +master[:File] = ARGV.shift + begin - server = Puppet::Server::Master.new( - :File => ARGV.shift, - :Local => true - ) + server = Puppet::Server::Master.new(master) rescue => detail $stderr.puts detail exit(1) diff --git a/bin/puppetd b/bin/puppetd index e66083d3c..c7ab08304 100755 --- a/bin/puppetd +++ b/bin/puppetd @@ -28,6 +28,10 @@ # # = Options # +# confdir:: +# The configuration root directory, where +puppetmasterd+ defaults to looking +# for all of its configuration files. Defaults to +/etc/puppet+. +# # debug:: # Enable full debugging. # @@ -91,6 +95,7 @@ rescue LoadError end result = GetoptLong.new( + [ "--confdir", "-c", GetoptLong::REQUIRED_ARGUMENT ], [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--fqdn", "-f", GetoptLong::REQUIRED_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ], @@ -113,6 +118,8 @@ waitforcert = false begin result.each { |opt,arg| case opt + when "--confdir" + Puppet[:puppetconf] = arg when "--help" if $haveusage RDoc::usage && exit diff --git a/bin/puppetmasterd b/bin/puppetmasterd index 055892004..33b3d1c8f 100755 --- a/bin/puppetmasterd +++ b/bin/puppetmasterd @@ -25,6 +25,10 @@ # refers to the autosign configuration file at /etc/puppet/autosign.conf to # determine which hosts should have their certificates signed. # +# confdir:: +# The configuration root directory, where +puppetmasterd+ defaults to looking +# for all of its configuration files. Defaults to +/etc/puppet+. +# # debug:: # Enable full debugging. Causes the daemon not to go into the background. # @@ -90,6 +94,7 @@ require 'puppet/server' result = GetoptLong.new( [ "--autosign", "-a", GetoptLong::NO_ARGUMENT ], + [ "--confdir", "-c", GetoptLong::REQUIRED_ARGUMENT ], [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--fsconfig", "-f", GetoptLong::REQUIRED_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ], @@ -126,6 +131,8 @@ begin case opt when "--autosign" ca[:autosign] = Puppet[:autosign] + when "--confdir" + Puppet[:puppetconf] = arg when "--debug" Puppet[:debug] = true when "--fsconfig" @@ -209,6 +216,9 @@ end unless fs.include?(:Config) if File.exists?(Puppet[:fileserverconfig]) fs[:Config] = Puppet[:fileserverconfig] + else + Puppet.notice "File server config %s does not exist; skipping file serving" % + Puppet[:fileserverconfig] end end diff --git a/lib/puppet/client.rb b/lib/puppet/client.rb index cbb7dbedc..9bc46717b 100644 --- a/lib/puppet/client.rb +++ b/lib/puppet/client.rb @@ -1,5 +1,3 @@ -#!/usr/local/bin/ruby -w - # the available clients require 'puppet' @@ -43,20 +41,26 @@ module Puppet method = ary[0] Puppet.info "Defining %s.%s" % [namespace, method] self.send(:define_method,method) { |*args| + Puppet.info "Calling %s" % method #Puppet.info "peer cert is %s" % @http.peer_cert #Puppet.info "cert is %s" % @http.cert begin call("%s.%s" % [namespace, method.to_s],*args) rescue OpenSSL::SSL::SSLError => detail - Puppet.err "Could not call %s.%s: Untrusted certificates" % - [namespace, method] + #Puppet.err "Could not call %s.%s: Untrusted certificates" % + # [namespace, method] raise NetworkClientError, "Certificates were not trusted" rescue XMLRPC::FaultException => detail - Puppet.err "Could not call %s.%s: %s" % - [namespace, method, detail.faultString] - raise NetworkClientError, - "XMLRPC Error: %s" % detail.faultString + #Puppet.err "Could not call %s.%s: %s" % + # [namespace, method, detail.faultString] + #raise NetworkClientError, + # "XMLRPC Error: %s" % detail.faultString + raise NetworkClientError, detail.faultString + rescue Errno::ECONNREFUSED => detail + msg = "Could not connect to %s on port %s" % [@host, @port] + #Puppet.err msg + raise NetworkClientError, msg #rescue => detail # Puppet.err "Could not call %s.%s: %s" % # [namespace, method, detail.inspect] @@ -78,7 +82,7 @@ module Puppet end def cert=(cert) - Puppet.info "Adding certificate" + Puppet.debug "Adding certificate" @http.cert = cert @http.verify_mode = OpenSSL::SSL::VERIFY_PEER end @@ -216,7 +220,7 @@ module Puppet def self.facts facts = {} Facter.each { |name,fact| - facts[name] = fact + facts[name] = fact.downcase } facts @@ -341,8 +345,8 @@ module Puppet if objects.is_a?(Puppet::TransBucket) @objects = objects else - Puppet.warning objects.inspect - raise NetworkClientError.new(objects.class) + raise NetworkClientError, + "Invalid returned objects of type %s" % objects.class end end end @@ -426,10 +430,11 @@ module Puppet begin @driver.send(method, *args) rescue XMLRPC::FaultException => detail - Puppet.err "Could not call %s.%s: %s" % - [namespace, method, detail.faultString] - raise NetworkClientError, - "XMLRPC Error: %s" % detail.faultString + #Puppet.err "Could not call %s.%s: %s" % + # [namespace, method, detail.faultString] + #raise NetworkClientError, + # "XMLRPC Error: %s" % detail.faultString + raise NetworkClientError, detail.faultString end } } diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb index 7fa1a156d..602067436 100644 --- a/lib/puppet/parser/ast.rb +++ b/lib/puppet/parser/ast.rb @@ -239,6 +239,10 @@ module Puppet # meant completely different things. class ObjectInst < ASTArray; end + # Another simple container class to make sure we can correctly arrayfy + # things. + class CompArgument < ASTArray; end + # The base class for all of the leaves of the parse trees. These # basically just have types and values. Both of these parameters # are simple values, not AST objects. @@ -1289,8 +1293,10 @@ module Puppet # arguments... self.args.each { |arg, default| unless hash.include?(arg) - if defined? default + if defined? default and ! default.nil? hash[arg] = default + Puppet.debug "Got default %s for %s in %s" % + [default.inspect, arg.inspect, objname.inspect] else error = Puppet::ParseError.new( "Must pass %s to %s of type %s" % diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra index 78fb9aa47..5fe801e15 100644 --- a/lib/puppet/parser/grammar.ra +++ b/lib/puppet/parser/grammar.ra @@ -25,18 +25,18 @@ program: statements { # this is mainly so we can test the parser separately from the # interpreter - if Puppet[:parseonly] - begin - if Puppet[:debug] - puts result.tree(0) - end - rescue NoMethodError => detail - Puppet.err detail - #exit(78) - end - #require 'puppet/parser/interpreter' - #result = Puppet::Server.new(result) - end +# if Puppet[:parseonly] +# begin +# if Puppet[:debug] +# puts result.tree(0) +# end +# rescue NoMethodError => detail +# Puppet.err detail +# #exit(78) +# end +# #require 'puppet/parser/interpreter' +# #result = Puppet::Server.new(result) +# end } statements: statement @@ -447,7 +447,7 @@ import: IMPORT QTEXT { Dir.chdir(dir) { Dir.glob(val[1]).each { |file| parser = Puppet::Parser::Parser.new() - parser.stack = self.stack + parser.files = self.files Puppet.debug("importing '%s'" % file) begin parser.file = file @@ -554,7 +554,7 @@ argumentlist: nothing arguments: argument | arguments COMMA argument { - if val[0].is_a?(AST::ASTArray) + if val[0].instance_of?(AST::ASTArray) val[0].push(val[2]) result = val[0] else @@ -567,14 +567,14 @@ arguments: argument } argument: name EQUALS rvalue { - result = AST::ASTArray.new( + result = AST::CompArgument.new( :line => @lexer.line, :file => @lexer.file, :children => [val[0],val[2]] ) } | name { - result = AST::ASTArray.new( + result = AST::CompArgument.new( :line => @lexer.line, :file => @lexer.file, :children => [val[0]] @@ -635,14 +635,15 @@ Puppet[:typecheck] = true Puppet[:paramcheck] = true ---- inner ---- -attr_reader :file, :files +attr_reader :file +attr_accessor :files # Create an AST array out of all of the args def aryfy(*args) if args[0].is_a?(AST::ASTArray) result = args.shift args.each { |arg| - args.push arg + result.push arg } else result = AST::ASTArray.new( diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb index cd7ac46d6..e076bc1ca 100644 --- a/lib/puppet/parser/interpreter.rb +++ b/lib/puppet/parser/interpreter.rb @@ -45,15 +45,19 @@ module Puppet if @usenodes unless client raise Puppet::Error, - "Cannot evaluate no nodes with a nil client" + "Cannot evaluate nodes with a nil client" end # We've already evaluated the AST, in this case - @scope.evalnode(names, facts) + retval = @scope.evalnode(names, facts) + return retval else + # We've already evaluated the AST, in this case @scope = Puppet::Parser::Scope.new() # no parent scope @scope.interp = self - @scope.evaluate(@ast, facts) + @scope.type = "puppet" + @scope.name = "top" + return @scope.evaluate(@ast, facts) end #@ast.evaluate(@scope) rescue Puppet::DevError, Puppet::Error, Puppet::ParseError => except @@ -82,14 +86,14 @@ module Puppet # to pass to the client # this will be heirarchical, and will (at this point) contain # only TransObjects and TransSettings - @scope.name = "top" - @scope.type = "puppet" - begin - topbucket = @scope.to_trans - rescue => detail - Puppet.warning detail - raise - end + #@scope.name = "top" + #@scope.type = "puppet" + #begin + # topbucket = @scope.to_trans + #rescue => detail + # Puppet.warning detail + # raise + #end # add our settings to the front of the array # at least, for now @@ -104,7 +108,7 @@ module Puppet #retlist = TransObject.list #Puppet.debug "retobject length is %s" % retlist.length #TransObject.clear - return topbucket + #return topbucket end def scope @@ -120,6 +124,8 @@ module Puppet if @usenodes @scope = Puppet::Parser::Scope.new() # no parent scope + @scope.name = "top" + @scope.type = "puppet" @scope.interp = self Puppet.debug "Nodes defined" @ast.safeevaluate(@scope) diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb index df92e9c2e..733de138c 100644 --- a/lib/puppet/parser/parser.rb +++ b/lib/puppet/parser/parser.rb @@ -32,15 +32,16 @@ module Puppet class Parser < Racc::Parser -module_eval <<'..end grammar.ra modeval..id4705e629f1', 'grammar.ra', 638 -attr_reader :file, :files +module_eval <<'..end grammar.ra modeval..idb211ea7fd3', 'grammar.ra', 638 +attr_reader :file +attr_accessor :files # Create an AST array out of all of the args def aryfy(*args) if args[0].is_a?(AST::ASTArray) result = args.shift args.each { |arg| - args.push arg + result.push arg } else result = AST::ASTArray.new( @@ -144,7 +145,7 @@ end def string=(string) @lexer.string = string end -..end grammar.ra modeval..id4705e629f1 +..end grammar.ra modeval..idb211ea7fd3 ##### racc 1.4.4 generates ### @@ -561,18 +562,18 @@ module_eval <<'.,.,', 'grammar.ra', 40 # this is mainly so we can test the parser separately from the # interpreter - if Puppet[:parseonly] - begin - if Puppet[:debug] - puts result.tree(0) - end - rescue NoMethodError => detail - Puppet.err detail - #exit(78) - end - #require 'puppet/parser/interpreter' - #result = Puppet::Server.new(result) - end +# if Puppet[:parseonly] +# begin +# if Puppet[:debug] +# puts result.tree(0) +# end +# rescue NoMethodError => detail +# Puppet.err detail +# #exit(78) +# end +# #require 'puppet/parser/interpreter' +# #result = Puppet::Server.new(result) +# end result end .,., @@ -1118,7 +1119,7 @@ module_eval <<'.,.,', 'grammar.ra', 469 Dir.chdir(dir) { Dir.glob(val[1]).each { |file| parser = Puppet::Parser::Parser.new() - parser.stack = self.stack + parser.files = self.files Puppet.debug("importing '%s'" % file) begin parser.file = file @@ -1252,7 +1253,7 @@ module_eval <<'.,.,', 'grammar.ra', 553 module_eval <<'.,.,', 'grammar.ra', 567 def _reduce_80( val, _values, result ) - if val[0].is_a?(AST::ASTArray) + if val[0].instance_of?(AST::ASTArray) val[0].push(val[2]) result = val[0] else @@ -1268,7 +1269,7 @@ module_eval <<'.,.,', 'grammar.ra', 567 module_eval <<'.,.,', 'grammar.ra', 575 def _reduce_81( val, _values, result ) - result = AST::ASTArray.new( + result = AST::CompArgument.new( :line => @lexer.line, :file => @lexer.file, :children => [val[0],val[2]] @@ -1279,7 +1280,7 @@ module_eval <<'.,.,', 'grammar.ra', 575 module_eval <<'.,.,', 'grammar.ra', 582 def _reduce_82( val, _values, result ) - result = AST::ASTArray.new( + result = AST::CompArgument.new( :line => @lexer.line, :file => @lexer.file, :children => [val[0]] diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb index 3730af606..054a0e7b7 100644 --- a/lib/puppet/parser/scope.rb +++ b/lib/puppet/parser/scope.rb @@ -128,6 +128,7 @@ module Puppet # it will be removed during translation. # And now return the whole thing + #return self.to_trans return self.to_trans end @@ -485,8 +486,8 @@ module Puppet # Convert our scope to a list of Transportable objects. def to_trans - Puppet.debug "Translating scope %s at level %s" % - [self.object_id,self.level] + #Puppet.debug "Translating scope %s at level %s" % + # [self.object_id,self.level] results = [] @@ -494,8 +495,8 @@ module Puppet @children.each { |child| if child.is_a?(Scope) cresult = child.to_trans - Puppet.debug "Got %s from scope %s" % - [cresult.class,child.object_id] + #Puppet.debug "Got %s from scope %s" % + # [cresult.class,child.object_id] # Scopes normally result in a TransBucket, but they could # also result in a normal array; if that happens, get rid @@ -553,8 +554,10 @@ module Puppet error.stack = caller raise error end - Puppet.debug "TransBucket with name %s and type %s in scope %s" % - [@name,@type,self.object_id] + #Puppet.debug( + # "TransBucket with name %s and type %s in scope %s" % + # [@name,@type,self.object_id] + #) # now find metaparams @symtable.each { |var,value| @@ -569,7 +572,7 @@ module Puppet # [bucket.name,self.object_id] return bucket else - #Puppet.debug "nameless scope; just returning a list" + Puppet.debug "nameless scope; just returning a list" return results end end diff --git a/lib/puppet/server.rb b/lib/puppet/server.rb index 15b27f849..6737b2664 100644 --- a/lib/puppet/server.rb +++ b/lib/puppet/server.rb @@ -81,6 +81,8 @@ module Puppet super(hash) + Puppet.info "Listening on port %s" % hash[:Port] + # this creates a new servlet for every connection, # but all servlets have the same list of handlers # thus, the servlets can have their own state -- passing diff --git a/lib/puppet/server/fileserver.rb b/lib/puppet/server/fileserver.rb index 519d4aa0c..f792c7cd3 100755 --- a/lib/puppet/server/fileserver.rb +++ b/lib/puppet/server/fileserver.rb @@ -205,8 +205,7 @@ class Server end end - @mounts.clear - + newmounts = {} begin File.open(@config) { |f| mount = nil @@ -217,24 +216,24 @@ class Server when /^\s*$/: next # skip blank lines when /\[(\w+)\]/: name = $1 - if mount - unless mount.path - raise Puppet::Error, "Mount %s has no path specified" % - mount.name - end - end - if @mounts.include?(name) + if newmounts.include?(name) raise FileServerError, "%s is already mounted at %s" % - [@mounts[name], name] + [newmounts[name], name] end mount = Mount.new(name) - @mounts[name] = mount - when /\s*(\w+)\s+(.+)$/: + newmounts[name] = mount + when /^\s*(\w+)\s+(.+)$/: var = $1 value = $2 case var when "path": - mount.path = value + begin + mount.path = value + rescue FileServerError => detail + Puppet.err "Removing mount %s: %s" % + [mount.name, detail] + newmounts.delete(mount.name) + end when "allow": value.split(/\s*,\s*/).each { |val| begin @@ -242,7 +241,7 @@ class Server [val, mount.name] mount.allow(val) rescue AuthStoreError => detail - raise Puppet::Error, "%s at line %s of %s" % + raise FileServerError, "%s at line %s of %s" % [detail.to_s, count, @config] end } @@ -253,27 +252,39 @@ class Server [val, mount.name] mount.deny(val) rescue AuthStoreError => detail - raise Puppet::Error, "%s at line %s of %s" % + raise FileServerError, "%s at line %s of %s" % [detail.to_s, count, @config] end } else - raise Puppet::Error, - "Invalid argument %s at line %s" % [var, count] + raise FileServerError, + "Invalid argument '%s' at line %s" % [var, count] end else - raise Puppet::Error, - "Invalid line %s: %s" % [count, line] + raise FileServerError, "Invalid line %s: %s" % [count, line] end count += 1 } } rescue Errno::EACCES => detail - raise Puppet::Error, "Cannot read %s" % @config + Puppet.err "FileServer error: Cannot read %s; cannot serve" % @config + #raise Puppet::Error, "Cannot read %s" % @config rescue Errno::ENOENT => detail - raise Puppet::Error, "%s does not exit" % @config + Puppet.err "FileServer error: '%s' does not exit; cannot serve" % + @config + #raise Puppet::Error, "%s does not exit" % @config + #rescue FileServerError => detail + # Puppet.err "FileServer error: %s" % detail end + # Verify each of the mounts are valid. + # We let the check raise an error, so that it can raise an error + # pointing to the specific problem. + newmounts.each { |name, mount| + mount.valid? + } + @mounts = newmounts + @configstamp = File.stat(@config).ctime @configstatted = Time.now end @@ -283,7 +294,8 @@ class Server mount, path = splitpath(file) unless (@mounts.include?(mount)) - raise Puppet::Server::FileServerError, "%s not mounted" % mount + raise Puppet::Server::FileServerError, + "FileServer module '%s' not mounted" % mount end unless @mounts[mount].allowed?(client, clientip) @@ -370,14 +382,15 @@ class Server path = dir.sub(%r{/#{mount}/?}, '') unless @mounts.include?(mount) - raise FileServerError, "%s not mounted" % mount + raise FileServerError, "Fileserver module '%s' not mounted" % mount end unless @mounts[mount].path - raise FileServerError, "Mount %s does not have a path set" % mount + raise FileServerError, + "Fileserver error: Mount '%s' does not have a path set" % mount end else - raise FileServerError, "Invalid path '%s'" % dir + raise FileServerError, "Fileserver error: Invalid path '%s'" % dir end if path == "" @@ -410,6 +423,8 @@ class Server if path self.path = path + else + @path = nil end super() @@ -425,6 +440,14 @@ class Server def to_s @path end + + # Verify our configuration is valid. This should really check to + # make sure at least someone will be allowed, but, eh. + def valid? + unless @path + raise FileServerError, "No path specified" + end + end end end end diff --git a/lib/puppet/server/master.rb b/lib/puppet/server/master.rb index 08706bea7..03ff7c6ac 100644 --- a/lib/puppet/server/master.rb +++ b/lib/puppet/server/master.rb @@ -70,6 +70,10 @@ class Server end end + unless client + client = facts["hostname"] + clientip = facts["ipaddress"] + end Puppet.debug("Running interpreter") begin retobjects = @interpreter.run(client, facts) diff --git a/lib/puppet/server/servlet.rb b/lib/puppet/server/servlet.rb index 2bc2dffc1..e35a1d518 100644 --- a/lib/puppet/server/servlet.rb +++ b/lib/puppet/server/servlet.rb @@ -14,23 +14,46 @@ class Server self.new(server, *options) end + def add_handler(interface, handler) + @loadedhandlers << interface.prefix + super + end + + # Verify that our client has access. We allow untrusted access to + # puppetca methods but none others. def authorize(request, method) + namespace = method.sub(/\..+/, '') + client = request.peeraddr[2] + ip = request.peeraddr[3] if request.client_cert Puppet.info "Allowing %s(%s) trusted access to %s" % - [request.peeraddr[2], request.peeraddr[3], method] + [client, ip, method] return true else if method =~ /^puppetca\./ Puppet.notice "Allowing %s(%s) untrusted access to CA methods" % - [request.peeraddr[2], request.peeraddr[3]] + [client, ip] else Puppet.err "Unauthenticated client %s(%s) cannot call %s" % - [request.peeraddr[2], request.peeraddr[3], method] + [client, ip, method] return false end end end + def available?(method) + namespace = method.sub(/\..+/, '') + client = request.peeraddr[2] + ip = request.peeraddr[3] + if @loadedhandlers.include?(namespace) + return true + else + Puppet.warning "Client %s(%s) requested unavailable functionality %s" % + [client, ip, namespace] + return false + end + end + def initialize(server, handlers) #Puppet.info server.inspect @@ -41,6 +64,7 @@ class Server # and we can consume them all ourselves super() + @loadedhandlers = [] handlers.each { |handler| Puppet.debug "adding handler for %s" % handler.class self.add_handler(handler.class.interface, handler) @@ -58,22 +82,22 @@ class Server begin obj.call(*args) rescue Puppet::Server::AuthorizationError => detail - Puppet.warning obj.inspect - Puppet.warning args.inspect + #Puppet.warning obj.inspect + #Puppet.warning args.inspect Puppet.err "Permission denied: %s" % detail.to_s raise XMLRPC::FaultException.new( 1, detail.to_s ) rescue Puppet::Error => detail - Puppet.warning obj.inspect - Puppet.warning args.inspect - Puppet.err "Puppet error: %s" % detail.to_s + #Puppet.warning obj.inspect + #Puppet.warning args.inspect + Puppet.err detail.to_s raise XMLRPC::FaultException.new( 1, detail.to_s ) rescue => detail - Puppet.warning obj.inspect - Puppet.warning args.inspect + #Puppet.warning obj.inspect + #Puppet.warning args.inspect Puppet.err "Could not call: %s" % detail.to_s raise error end @@ -118,6 +142,13 @@ class Server def dispatch(methodname, *args) if defined? @request and @request + unless self.available?(methodname) + raise XMLRPC::FaultException.new( + ERR_UNAUTHORIZED, + "Functionality %s not available" % + methodname.sub(/\..+/, '') + ) + end unless self.authorize(@request, methodname) raise XMLRPC::FaultException.new( ERR_UNAUTHORIZED, diff --git a/lib/puppet/statechange.rb b/lib/puppet/statechange.rb index 0c817e909..7e670e975 100644 --- a/lib/puppet/statechange.rb +++ b/lib/puppet/statechange.rb @@ -29,17 +29,21 @@ module Puppet #--------------------------------------------------------------- def go - if @state.noop - #Puppet.debug "%s is noop" % @state - return nil - end - if @state.is == @state.should Puppet.info "%s.%s is already in sync" % [@state.parent.name, @state.name] return nil end + if @state.noop + @state.parent.log "%s should be %s" % + [@state, @should] + #Puppet.debug "%s is noop" % @state + return nil + else + Puppet.notice "Noop is %s" % @state.noop + end + begin events = @state.sync if events.nil? @@ -68,7 +72,7 @@ module Puppet #:state => @state, #:object => @state.parent, # FIXME this is where loglevel stuff should go - Puppet.notice @state.change_to_s + @state.parent.log @state.change_to_s Puppet::Event.new( :event => event, :change => self, @@ -87,7 +91,7 @@ module Puppet # pname = pname.id2name #end #:state => @state, - Puppet.notice "Failed: " + @state.change_to_s + @state.parent.log "Failed: " + @state.change_to_s return Puppet::Event.new( :event => pname + "_failed", :change => self, diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 88f3ff613..9e2d9f78c 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -787,7 +787,7 @@ class Type < Puppet::Element # set defalts @noop = false - @metaparams[:loglevel] = :info + @metaparams[:loglevel] = :notice # keeping stats for the total number of changes, and how many were # completely sync'ed # this isn't really sufficient either, because it adds lots of special cases @@ -812,6 +812,11 @@ class Type < Puppet::Element order.flatten.each { |name| if hash.include?(name) begin + if name == "owner" or name == :owner + if hash[name].nil? + puts caller + end + end self[name] = hash[name] rescue => detail raise Puppet::DevError.new( diff --git a/lib/puppet/type/package.rb b/lib/puppet/type/package.rb index a04346201..42aff1777 100644 --- a/lib/puppet/type/package.rb +++ b/lib/puppet/type/package.rb @@ -534,6 +534,7 @@ module Puppet def addis(state,value) if stateklass = self.class.validstate?(state) @states[state] = stateklass.new(:parent => self) + Puppet.debug "Adding is for %s as %s" % [state, value] @states[state].is = value elsif self.class.validparameter?(state) self[state] = value @@ -577,15 +578,23 @@ module Puppet [self.name, error.to_s] @states.delete(:install) + return end - if hash.nil? + if hash.nil? and @states.include?(:install) + Puppet.info "Removing install" @states[:install].is = nil + #return end hash.each { |name,value| if self.class.validstate?(name) if @states.include?(name) + unless @states[name] + raise Puppet::DevError, + "State %s on package %s is %s" % + [name, @name, @states[name]] + end @states[name].is = value else # silently ignore any returned states @@ -622,6 +631,7 @@ module Puppet end end # Puppet::Type::Package end + # this is how we retrieve packages class PackageSource attr_accessor :uri diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb index 8e5048662..8dbdcc541 100644 --- a/lib/puppet/type/pfile.rb +++ b/lib/puppet/type/pfile.rb @@ -28,7 +28,7 @@ module Puppet if stat = @parent.stat(true) @is = stat.ftype else - @is = -1 + @is = :notfound end # so this state is never marked out of sync @@ -57,9 +57,9 @@ module Puppet @should = "file" when "directory", /^d/: @should = "directory" - when "-1", -1: + when :notfound: # this is where a creation is being rolled back - @should = -1 + @should = :notfound else error = Puppet::Error.new "Cannot create files of type %s" % value @@ -71,7 +71,7 @@ module Puppet if stat = @parent.stat(true) @is = stat.ftype else - @is = -1 + @is = :notfound end #Puppet.debug "'exists' state is %s" % self.is @@ -105,7 +105,7 @@ module Puppet Dir.mkdir(@parent.name) end event = :directory_created - when -1: + when :notfound: # this is where the file should be deleted... unless FileTest.size(@parent.name) == 0 raise Puppet::Error.new( @@ -151,8 +151,8 @@ module Puppet @should = -2 end else - # We can't use -1 here, because then it'll match on non-existent - # files + # We can't use :notfound here, because then it'll match on + # non-existent files @should = -2 end end @@ -164,7 +164,7 @@ module Puppet unless FileTest.exists?(@parent.name) Puppet.err "File %s does not exist" % @parent.name - self.is = -1 + self.is = :notfound return end @@ -238,7 +238,7 @@ module Puppet raise error end - if @is == -1 + if @is == :notfound self.retrieve if @is == @should @@ -250,7 +250,7 @@ module Puppet # if we still can't retrieve a checksum, it means that # the file still doesn't exist - if @is == -1 + if @is == :notfound # if they're copying, then we won't worry about the file # not existing yet unless @parent.state(:source) @@ -283,11 +283,11 @@ module Puppet state[@parent.name] = Hash.new end - if @is == -1 + if @is == :notfound error = Puppet::Error.new("%s has invalid checksum" % @parent.name) raise error - #elsif @should == -1 + #elsif @should == :notfound # error = Puppet::Error.new("%s has invalid 'should' checksum" % # @parent.name) # raise error @@ -328,36 +328,38 @@ module Puppet # @parent.delete(self.name) # @should = nil # @is = nil -# unless defined? @@notified +# unless defined? @@notifieduid # Puppet.notice "Cannot manage ownership unless running as root" -# @@notified = true +# @@notifieduid = true # return # end # end unless stat = @parent.stat(true) - @is = -1 + @is = :notfound return end self.is = stat.uid end + # If we're not root, we can check the values but we cannot change them def should=(value) unless Process.uid == 0 @should = nil @is = nil - unless defined? @@notified + unless defined? @@notifieduid Puppet.notice "Cannot manage ownership unless running as root" #@parent.delete(self.name) - @@notified = true + @@notifieduid = true end - if @parent.state(:owner) - @parent.delete(:owner) - end - raise Puppet::Error.new( - "Cannot manage ownership unless running as root" - ) + return + #if @parent.state(:owner) + # @parent.delete(:owner) + #end + #raise Puppet::Error.new( + # "Cannot manage ownership unless running as root" + #) end if value.is_a?(Integer) # verify the user is a valid user @@ -404,14 +406,19 @@ module Puppet def sync unless Process.uid == 0 + unless defined? @@notifieduid + Puppet.notice "Cannot manage ownership unless running as root" + #@parent.delete(self.name) + @@notifieduid = true + end # there's a possibility that we never got retrieve() called # e.g., if the file didn't exist # thus, just delete ourselves now and don't do any work - @parent.delete(self.name) + #@parent.delete(self.name) return nil end - if @is == -1 + if @is == :notfound @parent.stat(true) self.retrieve #Puppet.debug "%s: after refresh, is '%s'" % [self.class.name,@is] @@ -424,11 +431,10 @@ module Puppet end begin - File.chown(self.should,-1,@parent[:path]) + File.chown(self.should,nil,@parent[:path]) rescue => detail - error = Puppet::Error.new("failed to chown '%s' to '%s': %s" % - [@parent[:path],self.should,detail]) - raise error + raise Puppet::Error, "Failed to set owner of '%s' to '%s': %s" % + [@parent[:path],self.should,detail] end return :inode_changed @@ -496,23 +502,22 @@ module Puppet end end else - self.is = -1 + self.is = :notfound end #Puppet.debug "chmod state is %o" % self.is end def sync - if @is == -1 + if @is == :notfound @parent.stat(true) self.retrieve #Puppet.debug "%s: after refresh, is '%s'" % [self.class.name,@is] - end - - unless @parent.stat - Puppet.err "File '%s' does not exist; cannot chmod" % - @parent[:path] - return nil + if @is == :notfound + @parent.log "%s does not exist; cannot set mode" % + @parent.name + return nil + end end unless defined? @fixed @@ -556,6 +561,16 @@ module Puppet gid = nil gname = nil + unless Process.uid == 0 + unless defined? @@notifiedgroup + Puppet.notice( + "Cannot manage group unless running as root" + ) + @@notifiedgroup = true + end + return + end + if value.is_a?(Integer) method = :getgrgid else @@ -610,8 +625,18 @@ module Puppet end def sync + unless Process.uid == 0 + unless defined? @@notifiedgroup + Puppet.notice( + "Cannot manage group ownership unless running as root" + ) + @@notifiedgroup = true + end + return nil + end + Puppet.debug "setting chgrp state to %s" % self.should - if @is == -1 + if @is == :notfound @parent.stat(true) self.retrieve #Puppet.debug "%s: after refresh, is '%s'" % [self.class.name,@is] @@ -649,7 +674,13 @@ module Puppet sourceobj, path = @parent.uri2obj(source) server = sourceobj.server - desc = server.describe(path) + begin + desc = server.describe(path) + rescue NetworkClientError => detail + Puppet.err "Could not describe %s: %s" % + [path, detail] + return nil + end args = {} Puppet::Type::PFile::PINPARAMS.zip( @@ -666,13 +697,17 @@ module Puppet args.delete(:owner) end + Puppet.notice "returning describe args %s" % args.inspect return args end def retrieve sum = nil - @stats = self.describe + unless @stats = self.describe + @is = :notdescribed + return nil + end @stats.each { |stat, value| next if stat == :checksum @@ -692,15 +727,15 @@ module Puppet when "file": if sum = @parent.state(:checksum) if sum.is - if sum.is == -1 + if sum.is == :notfound sum.retrieve end @is = sum.is else - @is = -1 + @is = :notfound end else - @is = -1 + @is = :notfound end @should = @stats[:checksum] @@ -742,8 +777,13 @@ module Puppet end def sync - if @is == -1 + Puppet.notice "syncing %s" % @parent.name + if @is == :notdescribed self.retrieve # try again + if @is == :notdescribed + @parent.log "Could not retreive information on %s" % @parent.name + return nil + end if @is == @should return nil end @@ -756,7 +796,15 @@ module Puppet sourceobj, path = @parent.uri2obj(@source) - contents = sourceobj.server.retrieve(path) + begin + contents = sourceobj.server.retrieve(path) + rescue NetworkClientError => detail + Puppet.err "Could not retrieve %s: %s" % + [path, detail] + return nil + end + + Puppet.notice "retrieved %s" % path unless sourceobj.server.local contents = CGI.unescape(contents) @@ -778,8 +826,8 @@ module Puppet # try to create it with the correct modes to start # we should also be changing our effective uid/gid, but... - if @parent[:mode] - args.push @parent[:mode] + if @parent.should(:mode) and @parent.should(:mode) != :notfound + args.push @parent.should(:mode) end # FIXME we should also change our effective user and group id @@ -1091,8 +1139,8 @@ module Puppet if child = klass[path] unless @children.include?(child) raise Puppet::Error, - "Planned child file %s already exists with parent %s" % - [path, child.parent] + "Planned child file %s of %s already exists with parent %s" % + [path, self.name, child.parent] end args.each { |var,value| next if var == :path @@ -1253,7 +1301,7 @@ module Puppet unless stat = self.stat(true) Puppet.debug "File %s does not exist" % self.name @states.each { |name,state| - state.is = -1 + state.is = :notfound } return end @@ -1309,6 +1357,7 @@ module Puppet if uri.port args[:Port] = uri.port end + # FIXME We should cache a copy of this server #sourceobj.server = Puppet::NetworkClient.new(args) sourceobj.server = Puppet::Client::FileClient.new(args) diff --git a/lib/puppet/type/state.rb b/lib/puppet/type/state.rb index a4ec29a68..0d5d84b6f 100644 --- a/lib/puppet/type/state.rb +++ b/lib/puppet/type/state.rb @@ -77,13 +77,14 @@ class State < Puppet::Element end #--------------------------------------------------------------- - #--------------------------------------------------------------- - # we aren't actually comparing the states themselves, we're only - # comparing the "should" value with the "is" value + # Determine whether the state is in-sync or not. If @should is + # not defined or is set to a non-true value, then we do not have + # a valid value for it and thus consider the state to be in-sync + # since we cannot fix it. def insync? #debug "%s value is '%s', should be '%s'" % # [self,self.is.inspect,self.should.inspect] - unless defined? @should + unless defined? @should and @should return true end self.is == self.should diff --git a/test/language/tc_snippets.rb b/test/language/tc_snippets.rb index bb736b37e..c04b3ae5d 100755 --- a/test/language/tc_snippets.rb +++ b/test/language/tc_snippets.rb @@ -244,7 +244,8 @@ class TestSnippets < TestPuppet def snippet_argumentdefaults(trans) file1 = "/tmp/argumenttest1" file2 = "/tmp/argumenttest2" - #@@tmpfiles << file + @@tmpfiles << file1 + @@tmpfiles << file2 assert(FileTest.exists?(file1)) assert(File.stat(file1).mode & 007777 == 0755) diff --git a/test/parser/tc_parser.rb b/test/parser/tc_parser.rb index de2d75ddc..4e3d83a63 100644 --- a/test/parser/tc_parser.rb +++ b/test/parser/tc_parser.rb @@ -58,6 +58,122 @@ class TestParser < TestPuppet ret = parser.parse } end + + def mkmanifest(file) + name = File.join(tmpdir, "file%s" % rand(100)) + @@tmpfiles << name + + File.open(file, "w") { |f| + f.puts "file { \"%s\": create => true, mode => 755 }\n" % + name + } + end + + def test_importglobbing + basedir = File.join(tmpdir(), "importesting") + @@tmpfiles << basedir + Dir.mkdir(basedir) + + subdir = "subdir" + Dir.mkdir(File.join(basedir, subdir)) + manifest = File.join(basedir, "manifest") + File.open(manifest, "w") { |f| + f.puts "import \"%s/*\"" % subdir + } + + 4.times { |i| + path = File.join(basedir, subdir, "subfile%s" % i) + mkmanifest(path) + } + + assert_nothing_raised("Could not parse multiple files") { + parser = Puppet::Parser::Parser.new() + parser.file = manifest + parser.parse + } + end + + def test_zdefaults + basedir = File.join(tmpdir(), "defaulttesting") + @@tmpfiles << basedir + Dir.mkdir(basedir) + + defs1 = { + "testing" => "value" + } + + defs2 = { + "one" => "two", + "three" => "four", + "five" => false, + "seven" => "eight", + "nine" => true, + "eleven" => "twelve" + } + + mkdef = proc { |hash| + hash.collect { |arg, value| + "%s = %s" % [arg, value] + }.join(", ") + } + manifest = File.join(basedir, "manifest") + File.open(manifest, "w") { |f| + f.puts " + define method(#{mkdef.call(defs1)}, other) { + $variable = $testing + } + + define othermethod(#{mkdef.call(defs2)}, goodness) { + $more = less + } + + method { + other => yayness + } + + othermethod { + goodness => rahness + } +" + } + + ast = nil + assert_nothing_raised("Could not parse multiple files") { + parser = Puppet::Parser::Parser.new() + parser.file = manifest + ast = parser.parse + } + + assert(ast, "Did not receive AST while parsing defaults") + + scope = nil + assert_nothing_raised("Could not evaluate defaults parse tree") { + scope = Puppet::Parser::Scope.new() + objects = scope.evaluate(ast) + } + + method = nil + othermethod = nil + assert_nothing_raised { + method = scope.find { |child| + child.is_a?(Puppet::Parser::Scope) and child.type == "method" + } + defs1.each { |var, value| + curval = method.lookupvar(var) + assert_equal(value, curval, "Did not get default") + } + } + + assert_nothing_raised { + method = scope.find { |child| + child.is_a?(Puppet::Parser::Scope) and child.type == "othermethod" + } + defs2.each { |var, value| + curval = method.lookupvar(var) + assert_equal(value, curval, "Did not get default") + } + } + end end # $Id$ diff --git a/test/server/tc_fileserver.rb b/test/server/tc_fileserver.rb index 4235a725c..17003a6fe 100755 --- a/test/server/tc_fileserver.rb +++ b/test/server/tc_fileserver.rb @@ -416,6 +416,23 @@ class TestFileServer < TestPuppet 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::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 @@ -424,9 +441,6 @@ class TestFileServer < TestPuppet basedir = File.join(tmpdir, "fileserverconfigfiletesting") @@tmpfiles << basedir - conftext = "# a test config file\n \n" - - # make some dirs for mounting Dir.mkdir(basedir) mounts = {} @@ -541,6 +555,72 @@ class TestFileServer < TestPuppet 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::Server::FileServer.new( + :Local => true, + :Config => conffile + ) + } + + assert_raise(Puppet::Server::FileServerError, + "Invalid mount was mounted") { + server.list(mount) + } + } + + 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::Server::FileServerError, + "Invalid config %s did not raise error" % i) { + server = Puppet::Server::FileServer.new( + :Local => true, + :Config => conffile + ) + } + } + end + # verify we reread the config file when it changes def test_filereread server = nil @@ -572,12 +652,14 @@ class TestFileServer < TestPuppet list = nil assert_nothing_raised { - list = server.list("/thing/", false, false, "test1.domain.com", "127.0.0.1") + list = server.list("/thing/", false, false, + "test1.domain.com", "127.0.0.1") } assert(list != "", "List returned nothing in rereard test") assert_raise(Puppet::Server::AuthorizationError, "List allowed invalid host") { - list = server.list("/thing/", false, false, "test2.domain.com", "127.0.0.1") + list = server.list("/thing/", false, false, + "test2.domain.com", "127.0.0.1") } sleep 1 @@ -591,11 +673,13 @@ class TestFileServer < TestPuppet } assert_raise(Puppet::Server::AuthorizationError, "List allowed invalid host") { - list = server.list("/thing/", false, false, "test1.domain.com", "127.0.0.1") + list = server.list("/thing/", false, false, + "test1.domain.com", "127.0.0.1") } assert_nothing_raised { - list = server.list("/thing/", false, false, "test2.domain.com", "127.0.0.1") + list = server.list("/thing/", false, false, + "test2.domain.com", "127.0.0.1") } assert(list != "", "List returned nothing in rereard test") diff --git a/test/types/tc_fileignoresource.rb b/test/types/tc_fileignoresource.rb index c67a48618..40013e6de 100644 --- a/test/types/tc_fileignoresource.rb +++ b/test/types/tc_fileignoresource.rb @@ -237,7 +237,7 @@ class TestFileIgnoreSources < FileTesting #makes Puppet file Object assert_nothing_raised { - tofile = Puppet::Type::PFile.new( + tofile = Puppet::Type::PFile.create( :name => topath, :source => frompath, :recurse => true, @@ -247,7 +247,7 @@ class TestFileIgnoreSources < FileTesting } #make a component and adds the file - comp = Puppet::Type::Component.new( + comp = Puppet::Type::Component.create( :name => "component" ) comp.push tofile diff --git a/test/types/tc_filesources.rb b/test/types/tc_filesources.rb index c4a35682c..0de4157bc 100755 --- a/test/types/tc_filesources.rb +++ b/test/types/tc_filesources.rb @@ -39,6 +39,11 @@ class TestFileSources < FileTesting rescue system("rm -rf %s" % Puppet[:checksumfile]) end + if defined? @port + @port += 1 + else + @port = 8800 + end super end @@ -440,4 +445,105 @@ class TestFileSources < FileTesting system("kill -INT %s" % serverpid) } end + + def test_networkSourcesWithoutService + server = nil + + Puppet[:autosign] = true + Puppet[:masterport] = 8765 + + serverpid = nil + assert_nothing_raised() { + server = Puppet::Server.new( + :Handlers => { + :CA => {}, # so that certs autogenerate + } + ) + + } + serverpid = fork { + assert_nothing_raised() { + #trap(:INT) { server.shutdown; Kernel.exit! } + trap(:INT) { server.shutdown } + server.start + } + } + @@tmppids << serverpid + + sleep(1) + + name = File.join(tmpdir(), "nosourcefile") + file = Puppet::Type::PFile.create( + :source => "puppet://localhost/dist/file", + :name => name + ) + + assert_nothing_raised { + file.retrieve + } + + comp = newcomp("nosource", file) + + assert_nothing_raised { + comp.evaluate + } + + assert(!FileTest.exists?(name), "File with no source exists anyway") + end + + def test_unmountedNetworkSources + server = nil + mounts = { + "/" => "root", + "/noexistokay" => "noexist" + } + + fileserverconf = mkfileserverconf(mounts) + + Puppet[:autosign] = true + Puppet[:masterport] = @port + + serverpid = nil + assert_nothing_raised() { + server = Puppet::Server.new( + :Port => @port, + :Handlers => { + :CA => {}, # so that certs autogenerate + :FileServer => { + :Config => fileserverconf + } + } + ) + + } + + serverpid = fork { + assert_nothing_raised() { + #trap(:INT) { server.shutdown; Kernel.exit! } + trap(:INT) { server.shutdown } + server.start + } + } + @@tmppids << serverpid + + sleep(1) + + name = File.join(tmpdir(), "nosourcefile") + file = Puppet::Type::PFile.create( + :source => "puppet://localhost/noexist/file", + :name => name + ) + + assert_nothing_raised { + file.retrieve + } + + comp = newcomp("nosource", file) + + assert_nothing_raised { + comp.evaluate + } + + assert(!FileTest.exists?(name), "File with no source exists anyway") + end end diff --git a/test/types/tc_type.rb b/test/types/tc_type.rb index f746f287b..16c0644b1 100644 --- a/test/types/tc_type.rb +++ b/test/types/tc_type.rb @@ -110,4 +110,8 @@ class TestType < TestPuppet assert_equal("testing", group.name, "Could not retrieve name") end + + # Test that global noop works + def test_zglobalnoop + end end |
