diff options
54 files changed, 900 insertions, 627 deletions
diff --git a/bin/puppet b/bin/puppet index 3148cbd50..9421e30f5 100755 --- a/bin/puppet +++ b/bin/puppet @@ -64,14 +64,6 @@ require 'puppet/server' require 'puppet/client' require 'getoptlong' -$haveusage = true - -begin - require 'rdoc/usage' -rescue Exception - $haveusage = false -end - options = [ [ "--debug", "-d", GetoptLong::NO_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ], @@ -108,7 +100,7 @@ begin puts "%s" % Puppet.version exit when "--help" - if $haveusage + if Puppet.feature.usage? RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" @@ -137,9 +129,6 @@ begin } rescue GetoptLong::InvalidOption => detail $stderr.puts "Try '#{$0} --help'" - #if $haveusage - # RDoc::usage(1,'usage') - #end exit(1) end diff --git a/bin/puppetca b/bin/puppetca index 34286f853..d1a47a7b1 100755 --- a/bin/puppetca +++ b/bin/puppetca @@ -87,14 +87,6 @@ require 'puppet' require 'puppet/sslcertificates' require 'getoptlong' -$haveusage = true - -begin - require 'rdoc/usage' -rescue Exception - $haveusage = false -end - options = [ [ "--all", "-a", GetoptLong::NO_ARGUMENT ], [ "--clean", "-c", GetoptLong::NO_ARGUMENT ], @@ -129,7 +121,7 @@ begin generate = arg mode = :generate when "--help" - if $haveusage + if Puppet.feature.usage? RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" @@ -149,9 +141,6 @@ begin } rescue GetoptLong::InvalidOption => detail $stderr.puts "Try '#{$0} --help'" - #if $haveusage - # RDoc::usage_no_exit('usage') - #end exit(1) end diff --git a/bin/puppetd b/bin/puppetd index cf63f53a6..dc3576f2c 100755 --- a/bin/puppetd +++ b/bin/puppetd @@ -154,13 +154,6 @@ require 'puppet/server' require 'puppet/client' require 'getoptlong' -$haveusage = true -begin - require 'rdoc/usage' -rescue Exception - $haveusage = false -end - options = [ [ "--centrallogging", GetoptLong::NO_ARGUMENT ], [ "--daemonize", "-D", GetoptLong::NO_ARGUMENT ], @@ -223,7 +216,7 @@ begin when "--centrallogging" options[:centrallogs] = true when "--help" - if $haveusage + if Puppet.feature.usage? RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" @@ -262,10 +255,6 @@ begin rescue GetoptLong::InvalidOption => detail $stderr.puts detail $stderr.puts "Try '#{$0} --help'" - # FIXME RDoc::usage doesn't seem to work - #if $haveusage - # RDoc::usage(1,'usage') - #end exit(1) end diff --git a/bin/puppetdoc b/bin/puppetdoc index c857f6c49..9929edee5 100755 --- a/bin/puppetdoc +++ b/bin/puppetdoc @@ -44,14 +44,6 @@ require 'puppet' require 'getoptlong' -$haveusage = true - -begin - require 'rdoc/usage' -rescue Exception - $haveusage = false -end - result = GetoptLong.new( [ "--arguments", "-a", GetoptLong::NO_ARGUMENT ], [ "--types", "-t", GetoptLong::NO_ARGUMENT ], @@ -72,7 +64,7 @@ begin when "--types" mode = :types when "--help" - if $haveusage + if Puppet.feature.usage? RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" @@ -82,9 +74,6 @@ begin } rescue GetoptLong::InvalidOption => detail $stderr.puts "Try '#{$0} --help'" - #if $haveusage - # RDoc::usage_no_exit('usage') - #end exit(1) end diff --git a/bin/puppetmasterd b/bin/puppetmasterd index 2bf018b55..ec47075f8 100755 --- a/bin/puppetmasterd +++ b/bin/puppetmasterd @@ -103,14 +103,6 @@ Puppet.config.addargs(options) result = GetoptLong.new(*options) -$haveusage = true - -begin - require 'rdoc/usage' -rescue Exception - $haveusage = false -end - master = {} ca = {} report = {} @@ -136,7 +128,7 @@ begin when "--debug" options[:debug] = true when "--help" - if $haveusage + if Puppet.feature.usage? RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" @@ -174,10 +166,6 @@ begin rescue GetoptLong::InvalidOption => detail $stderr.puts "Try '#{$0} --help'" #$stderr.puts detail - # FIXME RDoc::usage doesn't seem to work - #if $haveusage - # RDoc::usage(1,'usage') - #end exit(1) end diff --git a/bin/puppetrun b/bin/puppetrun index d4af0abb6..30f1a043f 100755 --- a/bin/puppetrun +++ b/bin/puppetrun @@ -170,14 +170,6 @@ def setupldap end end -$haveusage = true - -begin - require 'rdoc/usage' -rescue Exception - $haveusage = false -end - flags = [ [ "--all", "-a", GetoptLong::NO_ARGUMENT ], [ "--class", "-c", GetoptLong::REQUIRED_ARGUMENT ], @@ -234,7 +226,7 @@ begin when "--host" hosts << arg when "--help" - if $haveusage + if Puppet.feature.usage? RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" @@ -257,9 +249,6 @@ begin } rescue GetoptLong::InvalidOption => detail $stderr.puts "Try '#{$0} --help'" - #if $haveusage - # RDoc::usage(1,'usage') - #end exit(1) end diff --git a/lib/puppet.rb b/lib/puppet.rb index b385d86d0..fda428360 100644 --- a/lib/puppet.rb +++ b/lib/puppet.rb @@ -5,7 +5,9 @@ require 'puppet/error' require 'puppet/event-loop' require 'puppet/util' require 'puppet/log' +require 'puppet/autoload' require 'puppet/config' +require 'puppet/feature' require 'puppet/suidmanager' #------------------------------------------------------------ @@ -17,7 +19,7 @@ require 'puppet/suidmanager' # it's also a place to find top-level commands like 'debug' module Puppet - PUPPETVERSION = '0.20.0' + PUPPETVERSION = '0.20.0svn' def Puppet.version return PUPPETVERSION @@ -32,6 +34,7 @@ module Puppet # To keep a copy of arguments. Set within Config#addargs, because I'm # lazy. attr_accessor :args + attr_reader :features end @@ -66,6 +69,10 @@ module Puppet # I keep wanting to use Puppet.error # XXX this isn't actually working right now alias :error :err + + # The feature collection + @features = Puppet::Feature.new('puppet/feature') + @features.load # Store a new default value. def self.setdefaults(section, hash) diff --git a/lib/puppet/configuration.rb b/lib/puppet/configuration.rb index cfcda7120..074e656e0 100644 --- a/lib/puppet/configuration.rb +++ b/lib/puppet/configuration.rb @@ -80,7 +80,10 @@ module Puppet exits. Comma-separate multiple values. For a list of all values, specify 'all'. This feature is only available in Puppet versions higher than 0.18.4."], - :color => [true, "Whether to use ANSI colors when logging to the console."], + :color => ["ansi", "Whether to use colors when logging to the console. + Valid values are ``ansi`` (equivalent to ``true``), ``html`` (mostly + used during testing with TextMate), and ``false``, which produces + no color."], :mkusers => [false, "Whether to create the necessary user and group that puppetd will run as."], diff --git a/lib/puppet/element.rb b/lib/puppet/element.rb index 934fafeb9..a3cefaf94 100644 --- a/lib/puppet/element.rb +++ b/lib/puppet/element.rb @@ -42,31 +42,38 @@ class Puppet::Element # some classes (e.g., FileTypeRecords) will have to override this def path unless defined? @path - if defined? @parent and @parent - if self.is_a?(Puppet.type(:component)) - @path = [@parent.path, self.name] - else - @path = [@parent.path, self.class.name.to_s + "=" + self.name] - end + @path = pathbuilder + end + + #puts "%s[%s]: %s" % [self.class.name, self.title, @path] + + return @path.join("/") + end + + def pathbuilder + tmp = if defined? @parent and @parent + if self.is_a?(Puppet.type(:component)) + [@parent.path, self.name] + else + [@parent.path, self.class.name.to_s + "=" + self.name] + end + else + # The top-level name is always main[top], so we don't bother with + # that. And we don't add the hostname here, it gets added + # in the log server thingy. + if self.name == "main[top]" + ["/"] else - # The top-level name is always main[top], so we don't bother with - # that. And we don't add the hostname here, it gets added - # in the log server thingy. - if self.name == "main[top]" - @path = ["/"] + if self.is_a?(Puppet.type(:component)) + [self.name] else - if self.is_a?(Puppet.type(:component)) - @path = [self.name] - else - @path = [self.class.name.to_s + "=" + self.name.to_s] - end + [self.class.name.to_s + "=" + self.name.to_s] end end end - return @path.join("/") + return tmp end - end # $Id$ diff --git a/lib/puppet/feature.rb b/lib/puppet/feature.rb new file mode 100644 index 000000000..55fab5d3c --- /dev/null +++ b/lib/puppet/feature.rb @@ -0,0 +1,64 @@ +# Created by Luke Kanies on 2006-11-07. +# Copyright (c) 2006. All rights reserved. + +class Puppet::Feature + # Create a new feature test. You have to pass the feature name, + # and it must be unique. You can either provide a block that + # will get executed immediately to determine if the feature + # is present, or you can pass an option to determine it. + # Currently, the only supported option is 'libs' (must be + # passed as a symbol), which will make sure that each lib loads + # successfully. + def add(name, options = {}) + method = name.to_s + "?" + if self.class.respond_to?(method) + raise ArgumentError, "Feature %s is already defined" % name + end + + result = true + if block_given? + begin + result = yield + rescue => detail + if Puppet[:trace] + puts detail.backtrace + Puppet.err "Failed to load %s: %s" % [name, detail] + end + result = false + end + end + + if ary = options[:libs] + ary = [ary] unless ary.is_a?(Array) + + ary.each do |lib| + unless lib.is_a?(String) + raise ArgumentError, "Libraries must be passed as strings not %s" % lib.class + end + + begin + require lib + rescue Exception + Puppet.debug "Failed to load library '%s' for feature '%s'" % [lib, name] + result = false + end + end + end + + meta_def(method) do + result + end + end + + # Create a new feature collection. + def initialize(path) + @path = path + end + + def load + loader = Puppet::Autoload.new(self, @path) + loader.loadall + end +end + +# $Id$
\ No newline at end of file diff --git a/lib/puppet/feature/usage.rb b/lib/puppet/feature/usage.rb new file mode 100644 index 000000000..c4d1c2745 --- /dev/null +++ b/lib/puppet/feature/usage.rb @@ -0,0 +1,8 @@ +# Created by Luke Kanies on 2006-11-07. +# Copyright (c) 2006. All rights reserved. + +require 'puppet/feature' + +Puppet.features.add(:usage, :libs => %w{rdoc/ri/ri_paths rdoc/usage}) + +# $Id$
\ No newline at end of file diff --git a/lib/puppet/log.rb b/lib/puppet/log.rb index c76dd945c..8362e8d4d 100644 --- a/lib/puppet/log.rb +++ b/lib/puppet/log.rb @@ -6,13 +6,6 @@ module Puppet # multiple destinations, one of which is a remote server. class Log include Puppet::Util - PINK="[0;31m" - GREEN="[0;32m" - YELLOW="[0;33m" - SLATE="[0;34m" - ORANGE="[0;35m" - BLUE="[0;36m" - RESET="[0m" @levels = [:debug,:info,:notice,:warning,:err,:alert,:emerg,:crit] @loglevel = 2 @@ -250,7 +243,17 @@ module Puppet end newdesttype :console do - @@colors = { + + + PINK = {:console => "[0;31m", :html => "FFA0A0"} + GREEN = {:console => "[0;32m", :html => "00CD00"} + YELLOW = {:console => "[0;33m", :html => "FFFF60"} + SLATE = {:console => "[0;34m", :html => "80A0FF"} + ORANGE = {:console => "[0;35m", :html => "FFA500"} + BLUE = {:console => "[0;36m", :html => "40FFFF"} + RESET = {:console => "[0m", :html => ""} + + @@colormap = { :debug => SLATE, :info => GREEN, :notice => PINK, @@ -260,6 +263,22 @@ module Puppet :emerg => RESET, :crit => RESET } + + def colorize(level, str) + case Puppet[:color] + when false: str + when true, :ansi, "ansi": console_color(level, str) + when :html, "html": html_color(level, str) + end + end + + def console_color(level, str) + @@colormap[level][:console] + str + RESET[:console] + end + + def html_color(level, str) + %{<span style="color: %s">%s</span>} % [@@colormap[level][:html], str] + end def initialize # Flush output immediately. @@ -267,20 +286,10 @@ module Puppet end def handle(msg) - color = "" - reset = "" - if Puppet[:color] - color = @@colors[msg.level] - reset = RESET - end if msg.source == "Puppet" - puts color + "%s: %s" % [ - msg.level, msg.to_s - ] + reset + puts colorize(msg.level, "%s: %s" % [msg.level, msg.to_s]) else - puts color + "%s: %s: %s" % [ - msg.level, msg.source, msg.to_s - ] + reset + puts colorize(msg.level, "%s: %s: %s" % [msg.level, msg.source, msg.to_s]) end end end diff --git a/lib/puppet/metric.rb b/lib/puppet/metric.rb index 6356871b6..6702018dc 100644 --- a/lib/puppet/metric.rb +++ b/lib/puppet/metric.rb @@ -16,17 +16,9 @@ module Puppet :rrdinterval => ["$runinterval", "How often RRD should expect data. This should match how often the hosts report back to the server."] ) - - @@haverrd = false - begin - require 'RRD' - @@haverrd = true - rescue LoadError - end - - def self.haverrd? - @@haverrd - end + + # Load the library as a feature, so we can test its presence. + Puppet.features.add :rrd, :libs => 'RRD' attr_accessor :type, :name, :value, :label @@ -63,7 +55,7 @@ module Puppet end def graph(range = nil) - unless @@haverrd + unless Puppet.features.rrd? Puppet.warning "RRD library is missing; cannot graph metrics" return end @@ -120,7 +112,7 @@ module Puppet end def store(time) - unless @@haverrd + unless Puppet.features.rrd? Puppet.warning "RRD library is missing; cannot store metrics" return end diff --git a/lib/puppet/parser/ast/caseopt.rb b/lib/puppet/parser/ast/caseopt.rb index f6f2457d9..1c712e896 100644 --- a/lib/puppet/parser/ast/caseopt.rb +++ b/lib/puppet/parser/ast/caseopt.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/ast/branch' + class Puppet::Parser::AST # Each individual option in a case statement. class CaseOpt < AST::Branch diff --git a/lib/puppet/parser/ast/else.rb b/lib/puppet/parser/ast/else.rb index a29623f56..ff2f233b7 100644 --- a/lib/puppet/parser/ast/else.rb +++ b/lib/puppet/parser/ast/else.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/ast/branch' + class Puppet::Parser::AST # A separate ElseIf statement; can function as an 'else' if there's no # test. @@ -24,3 +26,5 @@ class Puppet::Parser::AST end end end + +# $Id$ diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb index 6729431b7..052b8a8b1 100644 --- a/lib/puppet/parser/ast/function.rb +++ b/lib/puppet/parser/ast/function.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/ast/branch' + class Puppet::Parser::AST # An AST object to call a function. class Function < AST::Branch diff --git a/lib/puppet/parser/ast/resourcedefaults.rb b/lib/puppet/parser/ast/resourcedefaults.rb index 44db4d465..df16b1b59 100644 --- a/lib/puppet/parser/ast/resourcedefaults.rb +++ b/lib/puppet/parser/ast/resourcedefaults.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/ast/branch' + class Puppet::Parser::AST # A statement syntactically similar to an ResourceDef, but uses a # capitalized object type and cannot have a name. diff --git a/lib/puppet/parser/ast/tag.rb b/lib/puppet/parser/ast/tag.rb index 0807d207e..4a2015cde 100644 --- a/lib/puppet/parser/ast/tag.rb +++ b/lib/puppet/parser/ast/tag.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/ast/branch' + class Puppet::Parser::AST # The code associated with a class. This is different from components # in that each class is a singleton -- only one will exist for a given diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb index 145700e27..6093952d4 100644 --- a/lib/puppet/parser/ast/vardef.rb +++ b/lib/puppet/parser/ast/vardef.rb @@ -1,3 +1,5 @@ +require 'puppet/parser/ast/branch' + class Puppet::Parser::AST # Define a variable. Stores the value in the current scope. class VarDef < AST::Branch diff --git a/lib/puppet/parser/grammar.ra b/lib/puppet/parser/grammar.ra index 6fcc4b1d7..aea9b404d 100644 --- a/lib/puppet/parser/grammar.ra +++ b/lib/puppet/parser/grammar.ra @@ -487,16 +487,9 @@ import: IMPORT quotedtext { ) next end - # push the results into the main result array - # We always return an array when we parse. - ast = parser.parse - - # Things that just get added to the classtable or whatever return nil - if ast - ast.each do |child| - result.push child - end - end + + # This will normally add code to the 'main' class. + parser.parse } } } diff --git a/lib/puppet/parser/parser.rb b/lib/puppet/parser/parser.rb index 54772bec8..c69829718 100644 --- a/lib/puppet/parser/parser.rb +++ b/lib/puppet/parser/parser.rb @@ -29,7 +29,7 @@ module Puppet class Parser < Racc::Parser -module_eval <<'..end grammar.ra modeval..idee2a7240ef', 'grammar.ra', 635 +module_eval <<'..end grammar.ra modeval..id4401d72c60', 'grammar.ra', 628 require 'puppet/parser/functions' attr_reader :file, :interp @@ -199,7 +199,7 @@ end # $Id$ -..end grammar.ra modeval..idee2a7240ef +..end grammar.ra modeval..id4401d72c60 ##### racc 1.4.5 generates ### @@ -1457,7 +1457,7 @@ module_eval <<'.,.,', 'grammar.ra', 440 end .,., -module_eval <<'.,.,', 'grammar.ra', 502 +module_eval <<'.,.,', 'grammar.ra', 495 def _reduce_116( val, _values, result ) # importing files # yuk, i hate keywords @@ -1506,23 +1506,16 @@ module_eval <<'.,.,', 'grammar.ra', 502 ) next end - # push the results into the main result array - # We always return an array when we parse. - ast = parser.parse - - # Things that just get added to the classtable or whatever return nil - if ast - ast.each do |child| - result.push child - end - end + + # This will normally add code to the 'main' class. + parser.parse } } result end .,., -module_eval <<'.,.,', 'grammar.ra', 512 +module_eval <<'.,.,', 'grammar.ra', 505 def _reduce_117( val, _values, result ) interp.newdefine fqname(val[1]), :arguments => val[2], :code => val[4] @lexer.indefine = false @@ -1533,7 +1526,7 @@ module_eval <<'.,.,', 'grammar.ra', 512 end .,., -module_eval <<'.,.,', 'grammar.ra', 516 +module_eval <<'.,.,', 'grammar.ra', 509 def _reduce_118( val, _values, result ) interp.newdefine fqname(val[1]), :arguments => val[2] @lexer.indefine = false @@ -1542,7 +1535,7 @@ module_eval <<'.,.,', 'grammar.ra', 516 end .,., -module_eval <<'.,.,', 'grammar.ra', 524 +module_eval <<'.,.,', 'grammar.ra', 517 def _reduce_119( val, _values, result ) # Our class gets defined in the parent namespace, not our own. @lexer.namepop @@ -1552,7 +1545,7 @@ module_eval <<'.,.,', 'grammar.ra', 524 end .,., -module_eval <<'.,.,', 'grammar.ra', 529 +module_eval <<'.,.,', 'grammar.ra', 522 def _reduce_120( val, _values, result ) # Our class gets defined in the parent namespace, not our own. @lexer.namepop @@ -1562,7 +1555,7 @@ module_eval <<'.,.,', 'grammar.ra', 529 end .,., -module_eval <<'.,.,', 'grammar.ra', 534 +module_eval <<'.,.,', 'grammar.ra', 527 def _reduce_121( val, _values, result ) interp.newnode val[1], :parent => val[2], :code => val[4] result = nil @@ -1570,7 +1563,7 @@ module_eval <<'.,.,', 'grammar.ra', 534 end .,., -module_eval <<'.,.,', 'grammar.ra', 537 +module_eval <<'.,.,', 'grammar.ra', 530 def _reduce_122( val, _values, result ) interp.newnode val[1], :parent => val[2] result = nil @@ -1584,7 +1577,7 @@ module_eval <<'.,.,', 'grammar.ra', 537 # reduce 125 omitted -module_eval <<'.,.,', 'grammar.ra', 549 +module_eval <<'.,.,', 'grammar.ra', 542 def _reduce_126( val, _values, result ) result = val[0] result = [result] unless result.is_a?(Array) @@ -1599,14 +1592,14 @@ module_eval <<'.,.,', 'grammar.ra', 549 # reduce 129 omitted -module_eval <<'.,.,', 'grammar.ra', 557 +module_eval <<'.,.,', 'grammar.ra', 550 def _reduce_130( val, _values, result ) result = nil result end .,., -module_eval <<'.,.,', 'grammar.ra', 561 +module_eval <<'.,.,', 'grammar.ra', 554 def _reduce_131( val, _values, result ) result = ast AST::ASTArray, :children => [] result @@ -1615,14 +1608,14 @@ module_eval <<'.,.,', 'grammar.ra', 561 # reduce 132 omitted -module_eval <<'.,.,', 'grammar.ra', 566 +module_eval <<'.,.,', 'grammar.ra', 559 def _reduce_133( val, _values, result ) result = nil result end .,., -module_eval <<'.,.,', 'grammar.ra', 570 +module_eval <<'.,.,', 'grammar.ra', 563 def _reduce_134( val, _values, result ) result = val[1] result = [result] unless result[0].is_a?(Array) @@ -1632,7 +1625,7 @@ module_eval <<'.,.,', 'grammar.ra', 570 # reduce 135 omitted -module_eval <<'.,.,', 'grammar.ra', 577 +module_eval <<'.,.,', 'grammar.ra', 570 def _reduce_136( val, _values, result ) result = val[0] result = [result] unless result[0].is_a?(Array) @@ -1641,7 +1634,7 @@ module_eval <<'.,.,', 'grammar.ra', 577 end .,., -module_eval <<'.,.,', 'grammar.ra', 582 +module_eval <<'.,.,', 'grammar.ra', 575 def _reduce_137( val, _values, result ) Puppet.warning addcontext("Deprecation notice: #{val[0].value} must now include '$' in prototype") result = [val[0], val[2]] @@ -1649,7 +1642,7 @@ module_eval <<'.,.,', 'grammar.ra', 582 end .,., -module_eval <<'.,.,', 'grammar.ra', 586 +module_eval <<'.,.,', 'grammar.ra', 579 def _reduce_138( val, _values, result ) Puppet.warning addcontext("Deprecation notice: #{val[0].value} must now include '$' in prototype") result = [val[0]] @@ -1657,14 +1650,14 @@ module_eval <<'.,.,', 'grammar.ra', 586 end .,., -module_eval <<'.,.,', 'grammar.ra', 588 +module_eval <<'.,.,', 'grammar.ra', 581 def _reduce_139( val, _values, result ) result = [val[0], val[2]] result end .,., -module_eval <<'.,.,', 'grammar.ra', 590 +module_eval <<'.,.,', 'grammar.ra', 583 def _reduce_140( val, _values, result ) result = [val[0]] result @@ -1673,21 +1666,21 @@ module_eval <<'.,.,', 'grammar.ra', 590 # reduce 141 omitted -module_eval <<'.,.,', 'grammar.ra', 595 +module_eval <<'.,.,', 'grammar.ra', 588 def _reduce_142( val, _values, result ) result = val[1] result end .,., -module_eval <<'.,.,', 'grammar.ra', 599 +module_eval <<'.,.,', 'grammar.ra', 592 def _reduce_143( val, _values, result ) result = ast AST::Variable, :value => val[0] result end .,., -module_eval <<'.,.,', 'grammar.ra', 607 +module_eval <<'.,.,', 'grammar.ra', 600 def _reduce_144( val, _values, result ) if val[1].instance_of?(AST::ASTArray) result = val[1] @@ -1698,7 +1691,7 @@ module_eval <<'.,.,', 'grammar.ra', 607 end .,., -module_eval <<'.,.,', 'grammar.ra', 609 +module_eval <<'.,.,', 'grammar.ra', 602 def _reduce_145( val, _values, result ) result = ast AST::ASTArray result @@ -1711,7 +1704,7 @@ module_eval <<'.,.,', 'grammar.ra', 609 # reduce 148 omitted -module_eval <<'.,.,', 'grammar.ra', 614 +module_eval <<'.,.,', 'grammar.ra', 607 def _reduce_149( val, _values, result ) result = nil result diff --git a/lib/puppet/provider.rb b/lib/puppet/provider.rb index 0cd774c35..36c685990 100644 --- a/lib/puppet/provider.rb +++ b/lib/puppet/provider.rb @@ -149,8 +149,10 @@ class Puppet::Provider found = values.find do |v| result == v.to_s.downcase.intern end - debug "Not suitable: %s not in %s" % [check, values] - return false unless found + unless found + debug "Not suitable: %s not in %s" % [check, values] + return false + end else return false end diff --git a/lib/puppet/provider/nameservice/netinfo.rb b/lib/puppet/provider/nameservice/netinfo.rb index 5d6c19969..f6822b087 100644 --- a/lib/puppet/provider/nameservice/netinfo.rb +++ b/lib/puppet/provider/nameservice/netinfo.rb @@ -68,7 +68,6 @@ class NetInfo < Puppet::Provider::NameService val = autogen() else # No value, and it's not required, so skip it. - info "No value for %s" % name next end end diff --git a/lib/puppet/reports/store.rb b/lib/puppet/reports/store.rb index a2ab797e1..e4a2b1fe5 100644 --- a/lib/puppet/reports/store.rb +++ b/lib/puppet/reports/store.rb @@ -49,7 +49,7 @@ Puppet::Server::Report.newreport(:store, :useyaml => true) do begin File.open(file, "w", 0640) do |f| - f.puts yaml + f.print yaml end rescue => detail if Puppet[:trace] diff --git a/lib/puppet/server/servlet.rb b/lib/puppet/server/servlet.rb index d562078e1..81219ef44 100644 --- a/lib/puppet/server/servlet.rb +++ b/lib/puppet/server/servlet.rb @@ -144,7 +144,7 @@ class Server error = XMLRPC::FaultException.new( 1, detail.to_s ) - error.set_backtrace = detail.backtrace + error.set_backtrace detail.backtrace raise error rescue => detail #Puppet.warning obj.inspect diff --git a/lib/puppet/sslcertificates/inventory.rb b/lib/puppet/sslcertificates/inventory.rb index 4dbf60410..045780a69 100644 --- a/lib/puppet/sslcertificates/inventory.rb +++ b/lib/puppet/sslcertificates/inventory.rb @@ -3,48 +3,51 @@ module Puppet::SSLCertificates module Inventory + Puppet.config.setdefaults(:ca, + :cert_inventory => { + :default => "$cadir/inventory.txt", + :mode => 0644, + :owner => "$user", + :group => "$group", + :desc => "A Complete listing of all certificates" + } + ) + # Add CERT to the inventory of issued certs in '$cadir/inventory.txt' # If no inventory exists yet, build an inventory and list all the # certificates that have been signed so far - def Inventory.add(cert) - f = open - format(f, cert) - f.close() - end + def self.add(cert) + unless FileTest.exists?(Puppet[:cert_inventory]) + inited = false + end - def Inventory.filename - File::join(Puppet[:cadir], "inventory.txt") + Puppet.config.write(:cert_inventory, "a") do |f| + unless inited + f.puts self.init + end + f.puts format(cert) + end end private - def Inventory.open - if File::exist?(filename) - File::open(filename, "a") - else - init - end - end - def Inventory.init - if File::exist?(filename) - raise Puppet::Error, - "Inventory file #{filename} already exists" - end - inv = File.open(filename, "w") - inv.puts "# Inventory of signed certificates" - inv.puts "# SERIAL NOT_BEFORE _NOT_AFTER SUBJECT" + def self.init + inv = "# Inventory of signed certificates\n" + inv += "# SERIAL NOT_BEFORE NOT_AFTER SUBJECT\n" Dir.glob(File::join(Puppet[:signeddir], "*.pem")) do |f| - format(inv, OpenSSL::X509::Certificate.new(File::read(f))) + inv += format(OpenSSL::X509::Certificate.new(File::read(f))) + "\n" end return inv end - def Inventory.format(f, cert) + def self.format(cert) iso = '%Y-%m-%dT%H:%M:%S%Z' - f.puts "0x%04x %s %s %s" % [cert.serial, + return "0x%04x %s %s %s" % [cert.serial, cert.not_before.strftime(iso), cert.not_after.strftime(iso), cert.subject] end end end + +# $Id$ diff --git a/lib/puppet/storage.rb b/lib/puppet/storage.rb index 38fea42bb..5f71c171b 100644 --- a/lib/puppet/storage.rb +++ b/lib/puppet/storage.rb @@ -21,7 +21,15 @@ module Puppet unless object.is_a? Puppet::Type raise Puppet::DevFail, "Must pass a Type instance to Storage.cache" end - return @@state[object.path] ||= {} + + # We used to store things by path, now we store them by ref. + # In oscar(0.20.0) this changed to using the ref. + if @@state.include?(object.path) + @@state[object.ref] = @@state[object.path] + @@state.delete(object.path) + end + + return @@state[object.ref] ||= {} end def self.clear diff --git a/lib/puppet/type.rb b/lib/puppet/type.rb index 75f8c02c3..8df86ee81 100644 --- a/lib/puppet/type.rb +++ b/lib/puppet/type.rb @@ -284,9 +284,8 @@ class Type < Puppet::Element hash.delete attr end } - - # While this could theoretically be set after all of the objects are - # created, it seems to make more sense to set them immediately. + + # Set all default values. self.setdefaults if hash.length > 0 @@ -335,6 +334,11 @@ class Type < Puppet::Element return self[:name] end + # Return the "type[name]" style reference. + def ref + "%s[%s]" % [self.class.name, self.title] + end + # Retrieve the title of an object. If no title was set separately, # then use the object's name. def title diff --git a/lib/puppet/type/group.rb b/lib/puppet/type/group.rb index 5bf82b933..aa982c247 100755 --- a/lib/puppet/type/group.rb +++ b/lib/puppet/type/group.rb @@ -187,7 +187,7 @@ module Puppet end def retrieve - if @provider.exists? + if self.provider and @provider.exists? super else # the group does not exist diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb index 233d01da6..15367a0c2 100644 --- a/lib/puppet/type/pfile.rb +++ b/lib/puppet/type/pfile.rb @@ -629,39 +629,34 @@ module Puppet return child end - # Paths are special for files, because we don't actually want to show - # the parent's full path. - def path - unless defined? @path - if defined? @parent - # We only need to behave specially when our parent is also - # a file - if @parent.is_a?(self.class) - # Remove the parent file name - ppath = @parent.path.sub(/\/?file=.+/, '') - @path = [] - if ppath != "/" and ppath != "" - @path << ppath - end - @path << self.class.name.to_s + "=" + self.name - else - super + def pathbuilder + if defined? @parent + # We only need to behave specially when our parent is also + # a file + if @parent.is_a?(self.class) + # Remove the parent file name + ppath = @parent.path.sub(/\/?file=.+/, '') + tmp = [] + if ppath != "/" and ppath != "" + tmp << ppath end + tmp << self.class.name.to_s + "=" + self.name + return tmp else - # The top-level name is always puppet[top], so we don't - # bother with that. And we don't add the hostname - # here, it gets added in the log server thingy. - if self.name == "puppet[top]" - @path = ["/"] - else - # We assume that if we don't have a parent that we - # should not cache the path - @path = [self.class.name.to_s + "=" + self.name] - end + return super + end + else + # The top-level name is always puppet[top], so we don't + # bother with that. And we don't add the hostname + # here, it gets added in the log server thingy. + if self.name == "puppet[top]" + return ["/"] + else + # We assume that if we don't have a parent that we + # should not cache the path + return [self.class.name.to_s + "=" + self.name] end end - - return @path.join("/") end # Recurse into the directory. This basically just calls 'localrecurse' @@ -837,7 +832,7 @@ module Puppet server = sourceobj.server sum = "md5" if state = self.state(:checksum) - sum = state.checktype + sum = state.should end r = false if recurse diff --git a/lib/puppet/type/pfile/checksum.rb b/lib/puppet/type/pfile/checksum.rb index a37ccf9dc..355d211a5 100755 --- a/lib/puppet/type/pfile/checksum.rb +++ b/lib/puppet/type/pfile/checksum.rb @@ -40,35 +40,48 @@ module Puppet :nochange end - # Convert from the sum type to the stored checksum. + # If they pass us a sum type, behave normally, but if they pass + # us a sum type + sum, stick the sum in the cache. munge do |value| - unless defined? @checktypes - @checktypes = [] - end - if value =~ /^\{(\w+)\}(.+)$/ - @checktypes << $1 - #return $2 - return value + type = symbolize($1) + sum = $2 + cache(type, sum) + return type else if FileTest.directory?(@parent[:path]) - value = "time" + return :time + else + return symbolize(value) end - value = super(value) - @checktypes << value - return getcachedsum() end end - def checktype - @checktypes[0] + # Store the checksum in the data cache, or retrieve it if only the + # sum type is provided. + def cache(type, sum = nil) + type = symbolize(type) + unless state = @parent.cached(:checksums) + self.debug "Initializing checksum hash" + state = {} + @parent.cache(:checksums, state) + end + + if sum + unless sum =~ /\{\w+\}/ + sum = "{%s}%s" % [type, sum] + end + state[type] = sum + else + return state[type] + end end # Because source and content and whomever else need to set the checksum # and do the updating, we provide a simple mechanism for doing so. def checksum=(value) @is = value - @should = [value] + munge(@should) self.updatesum end @@ -77,13 +90,13 @@ module Puppet begin if @is == :absent return "defined '%s' as '%s'" % - [self.name, self.should_to_s] + [self.name, self.currentsum] elsif self.should == :absent return "undefined %s from '%s'" % [self.name, self.is_to_s] else return "%s changed '%s' to '%s'" % - [self.name, self.should_to_s, self.is_to_s] + [self.name, self.currentsum, self.is_to_s] end rescue Puppet::Error, Puppet::DevError raise @@ -93,6 +106,11 @@ module Puppet end end + def currentsum + #"{%s}%s" % [self.should, cache(self.should)] + cache(self.should) + end + # Retrieve the cached sum def getcachedsum hash = nil @@ -101,11 +119,7 @@ module Puppet @parent.cache(:checksums, hash) end - sumtype = @checktypes[0] - - #unless state - # self.devfail "Did not get state back from Storage" - #end + sumtype = self.should if hash.include?(sumtype) #self.notice "Found checksum %s for %s" % @@ -133,14 +147,10 @@ module Puppet checktype = checktype.intern if checktype.is_a? String case checktype when :md5, :md5lite: - unless FileTest.file?(@parent[:path]) - @parent.info "Cannot MD5 sum directory %s" % - @parent[:path] - - @should = [nil] - @is = nil - #@parent.delete(self[:path]) - return + if ! FileTest.file?(@parent[:path]) + @parent.debug "Cannot MD5 sum %s; using mtime" % + [@parent.stat.ftype] + sum = @parent.stat.mtime.to_s else begin File.open(@parent[:path]) { |file| @@ -165,7 +175,7 @@ module Puppet @parent[:path] @parent.delete(self.class.name) rescue => detail - self.notice "Cannot checksum %s: %s" % + self.notice "Cannot checksum: %s" % detail @parent.delete(self.class.name) end @@ -181,7 +191,6 @@ module Puppet end return "{#{checktype}}" + sum.to_s - #return sum.to_s end # At this point, we don't actually modify the system, we modify @@ -226,6 +235,16 @@ module Puppet end end + def insync? + if cache(self.should) + return @is == currentsum() + else + # If there's no cached sum, then we don't want to generate + # an event. + return true + end + end + # Even though they can specify multiple checksums, the insync? # mechanism can really only test against one, so we'll just retrieve # the first specified sum type. @@ -236,10 +255,6 @@ module Puppet return @is end - unless defined? @checktypes - @checktypes = ["md5"] - end - stat = nil unless stat = @parent.stat self.is = :absent @@ -249,29 +264,20 @@ module Puppet if stat.ftype == "link" and @parent[:links] != :follow self.debug "Not checksumming symlink" #@parent.delete(:checksum) - self.is = self.should + self.is = self.currentsum return end - if stat.ftype == "directory" and @checktypes[0] =~ /md5/ - @checktypes = ["time"] - end + checktype = self.should || :md5 # Just use the first allowed check type - @is = getsum(@checktypes[0]) - - # @should should always be set, so if it's not set at all, we - # know we haven't looked in the cache yet. - unless defined? @should and ! @should.nil? - @should = [getcachedsum()] - end + @is = getsum(checktype) - # If there is no should defined, then store the current value - # into the 'should' value, so that we're not marked as being + # If there is no sum defined, then store the current value + # into the cache, so that we're not marked as being # out of sync. We don't want to generate an event the first # time we get a sum. - if @should == [:nosum] - @should = [@is] + unless cache(self.should) # FIXME we should support an updatechecksums-like mechanism self.updatesum end @@ -282,36 +288,37 @@ module Puppet # Store the new sum to the state db. def updatesum result = false - state = nil - unless state = @parent.cached(:checksums) - self.debug "Initializing checksum hash for %s" % @parent.title - state = {} - @parent.cache(:checksums, state) - end if @is.is_a?(Symbol) - error = Puppet::Error.new("%s has invalid checksum" % - @parent.title) - raise error + raise Puppet::Error, "%s has invalid checksum" % @parent.title end # if we're replacing, vs. updating - if state.include?(@checktypes[0]) + if sum = cache(self.should) unless defined? @should raise Puppet::Error.new( ("@should is not initialized for %s, even though we " + "found a checksum") % @parent[:path] ) end + + if @is == sum + info "Sums are already equal" + return false + end + + #if cache(self.should) == @is + # raise Puppet::Error, "Got told to update same sum twice" + #end self.debug "Replacing %s checksum %s with %s" % - [@parent.title, state[@checktypes[0]],@is] + [@parent.title, sum, @is] #@parent.debug "@is: %s; @should: %s" % [@is,@should] result = true else @parent.debug "Creating checksum %s" % @is result = false end - state[@checktypes[0]] = @is + cache(self.should, @is) return result end end diff --git a/lib/puppet/type/pfile/group.rb b/lib/puppet/type/pfile/group.rb index 9431b0e65..27ca5c2ff 100755 --- a/lib/puppet/type/pfile/group.rb +++ b/lib/puppet/type/pfile/group.rb @@ -54,24 +54,21 @@ module Puppet self.is = stat.gid end - # Determine if the group is valid, and if so, return the UID + # Determine if the group is valid, and if so, return the GID def validgroup?(value) if value =~ /^\d+$/ value = value.to_i end - - if value = Puppet::Util.gid(value) - return value + + if gid = Puppet::Util.gid(value) + return gid else + warning "could not find %s" % value return false end end - + munge do |value| - method = nil - gid = nil - gname = nil - if val = validgroup?(value) return val else diff --git a/lib/puppet/type/state.rb b/lib/puppet/type/state.rb index 61c1a85e2..d8578eb0a 100644 --- a/lib/puppet/type/state.rb +++ b/lib/puppet/type/state.rb @@ -218,11 +218,11 @@ class State < Puppet::Parameter # return the full path to us, for logging and rollback; not currently # used - def path + def pathbuilder if defined? @parent and @parent - return [@parent.path, self.name].join("/") + return [@parent.path, self.name] else - return self.name + return [self.name] end end diff --git a/lib/puppet/util.rb b/lib/puppet/util.rb index b4e8eb253..b0fb51e98 100644 --- a/lib/puppet/util.rb +++ b/lib/puppet/util.rb @@ -9,6 +9,9 @@ module Puppet end module Util require 'benchmark' + + require 'puppet/util/posix' + extend Puppet::Util::POSIX # Create a hash to store the different sync objects. @@syncresources = {} @@ -97,109 +100,6 @@ module Util end end - # Get the GID of a given group, provided either a GID or a name - def self.gid(group) - if group =~ /^\d+$/ - group = Integer(group) - end - unless group - raise Puppet::DevError, "Invalid group %s" % group.inspect - end - gid = nil - obj = nil - - # We want to look the group up either way - if group.is_a?(Integer) - # If this doesn't find anything - obj = Puppet.type(:group).find { |gobj| - gobj.should(:gid) == group || - gobj.is(:gid) == group - } - - unless obj - begin - gobj = Etc.getgrgid(group) - gid = gobj.gid - rescue ArgumentError => detail - # ignore it; we couldn't find the group - end - end - else - if obj = Puppet.type(:group)[group] - obj[:check] = [:gid] - else - obj = Puppet.type(:group).create( - :name => group, - :check => [:gid] - ) - end - obj.retrieve - end - if obj - gid = obj.should(:gid) || obj.is(:gid) - if gid == :absent - gid = nil - end - end - - return gid - end - - # Get the UID of a given user, whether a UID or name is provided - def self.uid(user) - uid = nil - - # if we don't have any user info, warn and GTFO. - if !user - Puppet.warning "Username provided for lookup is nil" - return nil - end - - # One of the unit tests was passing a Passwd struct - unless user.is_a?(String) or user.is_a?(Integer) - raise Puppet::DevError, "Invalid value for uid: %s" % user.class - end - - if user =~ /^\d+$/ - user = Integer(user) - end - - if user.is_a?(Integer) - # If this doesn't find anything - obj = Puppet.type(:user).find { |uobj| - uobj.should(:uid) == user || - uobj.is(:uid) == user - } - - unless obj - begin - uobj = Etc.getpwuid(user) - uid = uobj.uid - rescue ArgumentError => detail - # ignore it; we couldn't find the user - end - end - else - unless obj = Puppet.type(:user)[user] - obj = Puppet.type(:user).create( - :name => user - ) - end - obj[:check] = [:uid, :gid] - end - - if obj - obj.retrieve - uid = obj.should(:uid) || obj.is(:uid) - if uid == :absent - uid = nil - end - end - - return uid - end - - # Create instance methods for each of the log levels. This allows # the messages to be a little richer. Most classes will be calling this # method. diff --git a/lib/puppet/util/posix.rb b/lib/puppet/util/posix.rb new file mode 100755 index 000000000..75726b3da --- /dev/null +++ b/lib/puppet/util/posix.rb @@ -0,0 +1,78 @@ +# Utility methods for interacting with POSIX objects; mostly user and group +module Puppet::Util::POSIX + # Retrieve a field from a POSIX Etc object. The id can be either an integer + # or a name. This only works for users and groups. + def get_posix_field(space, field, id) + if id =~ /^\d+$/ + id = Integer(id) + end + prefix = "get" + space.to_s + if id.is_a?(Integer) + method = (prefix + idfield(space).to_s).intern + else + method = (prefix + "nam").intern + end + + begin + return Etc.send(method, id).send(field) + rescue ArgumentError => detail + # ignore it; we couldn't find the object + return nil + end + end + + # Look in memory for an already-managed type and use its info if available. + def get_provider_value(type, field, id) + unless typeklass = Puppet::Type.type(type) + raise ArgumentError, "Invalid type %s" % type + end + + id = id.to_s + + chkfield = idfield(type) + obj = typeklass.find { |obj| + if id =~ /^\d+$/ + obj.should(chkfield).to_s == id || + obj.is(chkfield).to_s == id + else + obj[:name] == id + end + } + + return nil unless obj + + if obj.provider + begin + return obj.provider.send(field) + rescue => detail + if Puppet[:trace] + puts detail.backtrace + Puppet.err detail + return nil + end + end + end + end + + # Determine what the field name is for users and groups. + def idfield(space) + case Puppet::Util.symbolize(space) + when :gr, :group: return :gid + when :pw, :user: return :uid + else + raise ArgumentError.new("Can only handle users and groups") + end + end + + # Get the GID of a given group, provided either a GID or a name + def gid(group) + get_provider_value(:group, :gid, group) or get_posix_field(:gr, :gid, group) + end + + # Get the UID of a given user, whether a UID or name is provided + def uid(user) + get_provider_value(:user, :uid, user) or get_posix_field(:pw, :uid, user) + end +end + +# $Id$
\ No newline at end of file diff --git a/test/Rakefile b/test/Rakefile index 3918d127e..4c7ca6ef3 100644 --- a/test/Rakefile +++ b/test/Rakefile @@ -1,5 +1,6 @@ require 'rake/testtask' require 'find' + include Find include FileTest diff --git a/test/certmgr/certmgr.rb b/test/certmgr/certmgr.rb index 5e2210913..d9349a9c0 100755 --- a/test/certmgr/certmgr.rb +++ b/test/certmgr/certmgr.rb @@ -5,6 +5,7 @@ $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ require 'puppet' require 'puppet/sslcertificates.rb' require 'puppettest' +require 'puppettest/certificates' # so, what kind of things do we want to test? @@ -16,7 +17,7 @@ require 'puppettest' # and test whether we've got things in the right scopes class TestCertMgr < Test::Unit::TestCase - include PuppetTest + include PuppetTest::Certificates def setup super #@dir = File.join(Puppet[:certdir], "testing") @@ -24,28 +25,6 @@ class TestCertMgr < Test::Unit::TestCase system("mkdir -p %s" % @dir) end - def mkPassFile() - keyfile = File.join(@dir, "tmpkeyfile") - @@tmpfiles << keyfile - unless FileTest.exists?(@dir) - system("mkdir -p %s" % @dir) - end - File.open(keyfile, "w", 0600) { |f| - f.print "as;dklj23rlkjzdflij23wr" - } - - return keyfile - end - - def mkCA - ca = nil - assert_nothing_raised { - ca = Puppet::SSLCertificates::CA.new() - } - - return ca - end - def testCreateSelfSignedCertificate cert = nil name = "testing" @@ -191,16 +170,6 @@ class TestCertMgr < Test::Unit::TestCase assert_equal($?,0) assert_equal(File.join(Puppet[:certdir], "signedcertest.pem: OK\n"), output) end - - def mkcert(hostname) - cert = nil - assert_nothing_raised { - cert = Puppet::SSLCertificates::Certificate.new(:name => hostname) - cert.mkcsr - } - - return cert - end def test_interactiveca @@ -259,8 +228,8 @@ class TestCertMgr < Test::Unit::TestCase def test_crl ca = mkCA() - h1 = mkSignedCert(ca, "host1.example.com") - h2 = mkSignedCert(ca, "host2.example.com") + h1 = mksignedcert(ca, "host1.example.com") + h2 = mksignedcert(ca, "host2.example.com") assert(ca.cert.verify(ca.cert.public_key)) assert(h1.verify(ca.cert.public_key)) @@ -295,23 +264,6 @@ class TestCertMgr < Test::Unit::TestCase assert(!store.verify(h2, [ca.cert])) end - def mkSignedCert(ca, host) - cert = mkcert(host) - assert_nothing_raised { - signedcert, cacert = ca.sign(cert.mkcsr) - return signedcert - } - end - - def mkStore(ca) - store = OpenSSL::X509::Store.new - store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT - store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK - store.add_cert(ca.cert) - store.add_crl(ca.crl) - store - end - def test_ttl cert = mksignedcert assert_equal(5 * 365 * 24 * 60 * 60, cert.not_after - cert.not_before) @@ -343,15 +295,6 @@ class TestCertMgr < Test::Unit::TestCase assert_equal(3 * 24 * 60 * 60, cert.not_after - cert.not_before) end - - def mksignedcert - ca = mkCA() - hostname = "ttltest.example.com" - - cert = nil - assert_nothing_raised { - cert, cacert = ca.sign(mkcert(hostname).mkcsr) - } - return cert - end end + +# $Id$ diff --git a/test/certmgr/inventory.rb b/test/certmgr/inventory.rb new file mode 100755 index 000000000..c94523d85 --- /dev/null +++ b/test/certmgr/inventory.rb @@ -0,0 +1,79 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppet' +require 'puppettest/certificates' +require 'puppet/sslcertificates/inventory.rb' + +class TestCertInventory < Test::Unit::TestCase + include PuppetTest::Certificates + + Inventory = Puppet::SSLCertificates::Inventory + + def test_format + cert = mksignedcert + + format = nil + assert_nothing_raised do + format = Inventory.format(cert) + end + + assert(format =~ /^0x0001 \S+ \S+ #{cert.subject}/, + "Did not create correct format") + end + + def test_init + # First create a couple of certificates + ca = mkCA + + cert1 = mksignedcert(ca, "host1.madstop.com") + cert2 = mksignedcert(ca, "host2.madstop.com") + + init = nil + assert_nothing_raised do + init = Inventory.init + end + + [cert1, cert2].each do |cert| + assert(init.include?(cert.subject.to_s), + "Did not catch %s" % cert.subject.to_s) + end + end + + def test_add + certs = [] + + user = Puppet::Util.uid(Puppet[:user]) + + ca = mkCA + 3.times do |i| + cert = mksignedcert(ca, "host#{i.to_s}.domain.com") + certs << cert + + # Add the cert + assert_nothing_raised do + Puppet::SSLCertificates::Inventory.add(cert) + end + + # Now make sure the cert is in there + assert(FileTest.exists?(Puppet[:cert_inventory]), + "Inventory file was not created") + + # And make sure all of our certs are in there + certs.each do |c| + assert( + File.read(Puppet[:cert_inventory]).include?(cert.subject.to_s), + "File does not contain %s" % cert.subject.to_s + ) + end + + # And make sure the inventory file is owned by the right user + if Process.uid == 0 + assert_equal(user, File.stat(Puppet[:cert_inventory]).uid) + end + end + end +end + +# $Id$ diff --git a/test/client/networkclient.rb b/test/client/networkclient.rb new file mode 100755 index 000000000..f4ef4c554 --- /dev/null +++ b/test/client/networkclient.rb @@ -0,0 +1,20 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppet' +require 'puppet/client' +require 'puppet/server' +require 'puppettest' + +class TestClient < Test::Unit::TestCase + def test_set_backtrace + error = Puppet::NetworkClientError.new("An error") + assert_nothing_raised do + error.set_backtrace ["caller"] + end + end +end + +# $Id$ + diff --git a/test/language/parser.rb b/test/language/parser.rb index a90ff2c7a..fa87dc6f5 100755 --- a/test/language/parser.rb +++ b/test/language/parser.rb @@ -581,6 +581,29 @@ file { "/tmp/yayness": #assert_instance_of(AST::CollExpr, query.test2) end end + + # We've had problems with files other than site.pp importing into main. + def test_importing_into_main + top = tempfile() + other = tempfile() + File.open(top, "w") do |f| + f.puts "import '#{other}'" + end + + file = tempfile() + File.open(other, "w") do |f| + f.puts "file { '#{file}': ensure => present }" + end + + interp = mkinterp :Manifest => top, :UseNodes => false + + code = nil + assert_nothing_raised do + code = interp.run("hostname.domain.com", {}).flatten + end + assert(code.length == 1, "Did not get the file") + assert_instance_of(Puppet::TransObject, code[0]) + end end # $Id$ diff --git a/test/lib/puppettest.rb b/test/lib/puppettest.rb index 07e3e084e..05d59a3a7 100755 --- a/test/lib/puppettest.rb +++ b/test/lib/puppettest.rb @@ -109,23 +109,16 @@ module PuppetTest Puppet::Log.close Puppet::Log.newdestination tempfile() Puppet[:httplog] = tempfile() - else + else + if textmate? + Puppet[:color] = false + end Puppet::Log.newdestination :console Puppet::Log.level = :debug #$VERBOSE = 1 Puppet.info @method_name Puppet[:trace] = true end - #if $0 =~ /.+\.rb/ or Puppet[:debug] - # Puppet::Log.newdestination :console - # Puppet::Log.level = :debug - # #$VERBOSE = 1 - # Puppet.info @method_name - #else - # Puppet::Log.close - # Puppet::Log.newdestination tempfile() - # Puppet[:httplog] = tempfile() - #end Puppet[:ignoreschedules] = true end @@ -142,6 +135,14 @@ module PuppetTest @@tmpfiles << f return f end + + def textmate? + if ENV["TM_FILENAME"] + return true + else + return false + end + end def tstdir dir = tempfile() diff --git a/test/lib/puppettest/certificates.rb b/test/lib/puppettest/certificates.rb new file mode 100644 index 000000000..ff19b95b3 --- /dev/null +++ b/test/lib/puppettest/certificates.rb @@ -0,0 +1,61 @@ +# Certificate-related helper methods. + +require 'puppettest' + +module PuppetTest::Certificates + include PuppetTest + + def mkPassFile() + keyfile = File.join(@dir, "tmpkeyfile") + @@tmpfiles << keyfile + unless FileTest.exists?(@dir) + system("mkdir -p %s" % @dir) + end + File.open(keyfile, "w", 0600) { |f| + f.print "as;dklj23rlkjzdflij23wr" + } + + return keyfile + end + + def mkCA + ca = nil + assert_nothing_raised { + ca = Puppet::SSLCertificates::CA.new() + } + + return ca + end + + def mkStore(ca) + store = OpenSSL::X509::Store.new + store.purpose = OpenSSL::X509::PURPOSE_SSL_CLIENT + store.flags = OpenSSL::X509::V_FLAG_CRL_CHECK + store.add_cert(ca.cert) + store.add_crl(ca.crl) + store + end + + def mkcert(hostname) + cert = nil + assert_nothing_raised { + cert = Puppet::SSLCertificates::Certificate.new(:name => hostname) + cert.mkcsr + } + + return cert + end + + def mksignedcert(ca = nil, hostname = nil) + ca ||= mkCA() + hostname ||= "ttltest.example.com" + + cert = nil + assert_nothing_raised { + cert, cacert = ca.sign(mkcert(hostname).mkcsr) + } + return cert + end +end + +# $Id$ diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index 1a6b5b12a..c7d4ec961 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -12,7 +12,7 @@ module PuppetTest::ParserTesting end def mkinterp(args = {}) - args[:Code] ||= "" + args[:Code] ||= "" unless args.include?(:Manifest) args[:Local] ||= true Puppet::Parser::Interpreter.new(args) end diff --git a/test/other/features.rb b/test/other/features.rb new file mode 100755 index 000000000..fb643c926 --- /dev/null +++ b/test/other/features.rb @@ -0,0 +1,60 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2006-11-07. +# Copyright (c) 2006. All rights reserved. + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/feature' + +class TestFeatures < Test::Unit::TestCase + include PuppetTest + + def setup + super + libdir = tempfile() + @features = Puppet::Feature.new(libdir) + end + + def test_new + assert_nothing_raised do + @features.add(:failer) do + raise ArgumentError, "nopes" + end + end + + assert(@features.respond_to?(:failer?), "Feature method did not get added") + assert_nothing_raised("failure propagated outside of feature") do + assert(! @features.failer?, "failure was considered true") + end + + # Now make one that succeeds + $succeeds = nil + assert_nothing_raised("Failed to add normal feature") do + @features.add(:succeeds) do + $succeeds = true + end + end + assert($succeeds, "Block was not called on initialization") + + assert(@features.respond_to?(:succeeds?), "Did not add succeeding feature") + assert_nothing_raised("Failed to call succeeds") { assert(@features.succeeds?, "Feature was not true") } + end + + def test_libs + assert_nothing_raised do + @features.add(:puppet, :libs => %w{puppet}) + end + + assert(@features.puppet?) + + assert_nothing_raised do + @features.add(:missing, :libs => %w{puppet no/such/library/okay}) + end + + assert(! @features.missing?, "Missing lib was considered true") + end +end + +# $Id$
\ No newline at end of file diff --git a/test/other/metrics.rb b/test/other/metrics.rb index 049d00093..a2904b2a5 100755 --- a/test/other/metrics.rb +++ b/test/other/metrics.rb @@ -7,14 +7,7 @@ require 'puppet' require 'puppettest' require 'puppet/type' -$haverrd = true -begin - require 'RRD' -rescue LoadError - $haverrd = false -end - -if $haverrd +if Puppet.features.rrd? class TestMetric < Test::Unit::TestCase include PuppetTest diff --git a/test/other/report.rb b/test/other/report.rb index a459e0cb2..433a0d8d8 100755 --- a/test/other/report.rb +++ b/test/other/report.rb @@ -21,6 +21,7 @@ class TestReports < Test::Unit::TestCase # Now make a file for testing logging file = Puppet::Type.newfile(:path => tempfile(), :ensure => "file") + file.finish log = nil assert_nothing_raised { @@ -83,7 +84,7 @@ class TestReports < Test::Unit::TestCase assert_equal(yaml, File.read(file), "File did not get written") end - if Puppet::Metric.haverrd? + if Puppet.features.rrd? def test_rrdgraph_report Puppet.config.use(:metrics) # First do some work diff --git a/test/puppet/defaults.rb b/test/puppet/defaults.rb index 7ac74eb54..033fb71bc 100755 --- a/test/puppet/defaults.rb +++ b/test/puppet/defaults.rb @@ -15,7 +15,7 @@ class TestPuppetDefaults < Test::Unit::TestCase @@booleans = %w{rrdgraph noop} def testVersion - assert( Puppet.version =~ /^[0-9]+(\.[0-9]+)*$/ ) + assert( Puppet.version =~ /^[0-9]+(\.[0-9]+)*/, "got invalid version number %s" % Puppet.version ) end def testStringOrParam diff --git a/test/types/exec.rb b/test/types/exec.rb index 53d343010..305f27d56 100755 --- a/test/types/exec.rb +++ b/test/types/exec.rb @@ -144,7 +144,7 @@ class TestExec < Test::Unit::TestCase file.retrieve sum = file.state(:checksum) - assert_equal(sum.is, sum.should) + assert(sum.insync?, "checksum is not in sync") events = trans.evaluate.collect { |event| event.event } diff --git a/test/types/file.rb b/test/types/file.rb index 027b52b81..c6cccae81 100755 --- a/test/types/file.rb +++ b/test/types/file.rb @@ -388,29 +388,24 @@ class TestFile < Test::Unit::TestCase :checksum => type ) } - comp = Puppet.type(:component).create( - :name => "checksum %s" % type - ) - comp.push file trans = nil file.retrieve if file.title !~ /nonexists/ sum = file.state(:checksum) - assert_equal(sum.is, sum.should) - assert(sum.insync?) + assert(sum.insync?, "file is not in sync") end - events = assert_apply(comp) + events = assert_apply(file) assert(! events.include?(:file_changed), "File incorrectly changed") - assert_events([], comp) + assert_events([], file) # We have to sleep because the time resolution of the time-based # mechanisms is greater than one second - sleep 1 + sleep 1 if type =~ /time/ assert_nothing_raised() { File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| @@ -418,7 +413,6 @@ class TestFile < Test::Unit::TestCase } } Puppet.type(:file).clear - Puppet.type(:component).clear # now recreate the file assert_nothing_raised() { @@ -427,19 +421,19 @@ class TestFile < Test::Unit::TestCase :checksum => type ) } - comp = Puppet.type(:component).create( - :name => "checksum, take 2, %s" % type - ) - comp.push file trans = nil - # If the file was missing, it should not generate an event - # when it gets created. - #if path =~ /nonexists/ - # assert_events([], comp) - #else - assert_events([:file_changed], comp) - #end + assert_events([:file_changed], file) + + # Run it a few times to make sure we aren't getting + # spurious changes. + assert_nothing_raised do + file.state(:checksum).retrieve + end + assert(file.state(:checksum).insync?, + "checksum is not in sync") + + sleep 1.1 if type =~ /time/ assert_nothing_raised() { File.unlink(path) File.open(path,File::CREAT|File::TRUNC|File::WRONLY) { |of| @@ -451,13 +445,11 @@ class TestFile < Test::Unit::TestCase of.flush } } - #assert_apply(comp) - assert_events([:file_changed], comp) + assert_events([:file_changed], file) # verify that we're actually getting notified when a file changes assert_nothing_raised() { Puppet.type(:file).clear - Puppet.type(:component).clear } if path =~ /nonexists/ diff --git a/test/types/group.rb b/test/types/group.rb index c681b5bd0..e12089256 100755 --- a/test/types/group.rb +++ b/test/types/group.rb @@ -136,19 +136,17 @@ class TestGroup < Test::Unit::TestCase def test_mkgroup gobj = nil - comp = nil name = "pptestgr" assert_nothing_raised { gobj = Puppet.type(:group).create( :name => name, - :ensure => :present + :gid => 123 ) - - comp = newcomp("groupmaker %s" % name, gobj) } + gobj.finish - trans = assert_events([:group_created], comp, "group") + trans = assert_events([:group_created], gobj, "group") assert(gobj.provider.exists?, "Did not create group") diff --git a/test/types/package.rb b/test/types/package.rb index 3cf1ea34c..611d73044 100755 --- a/test/types/package.rb +++ b/test/types/package.rb @@ -131,6 +131,8 @@ class TestPackages < Test::Unit::TestCase assert_nothing_raised { obj.retrieve } + + assert(obj.is(:ensure) != :absent, "Package %s is not installed" % obj.title) assert_instance_of(String, obj[:ensure], "Ensure did not return a version number") diff --git a/test/types/type.rb b/test/types/type.rb index 2438503c8..4be929ae9 100755 --- a/test/types/type.rb +++ b/test/types/type.rb @@ -798,6 +798,15 @@ end filetype[path] = one end end + + def test_ref + path = tempfile() + file = Puppet::Type.newfile(:path => path) + assert_equal("file[#{path}]", file.ref) + + exec = Puppet::Type.newexec(:title => "yay", :command => "/bin/echo yay") + assert_equal("exec[yay]", exec.ref) + end end # $Id$ diff --git a/test/util/posixtest.rb b/test/util/posixtest.rb new file mode 100755 index 000000000..354e3ad4c --- /dev/null +++ b/test/util/posixtest.rb @@ -0,0 +1,173 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2006-11-07. +# Copyright (c) 2006. All rights reserved. + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/util/posix' + +class TestPosixUtil < Test::Unit::TestCase + include PuppetTest + include Puppet::Util::POSIX + + def mk_posix_resource(type, obj) + field = idfield(type) + res = Puppet::Type.type(type).create( + :name => obj.name, + field => obj.send(field) + ) + res.setdefaults + res + end + + def test_get_posix_field + {:gr => nonrootgroup, :pw => nonrootuser}.each do |space, obj| + if space == :gr + id = :gid + else + id = :uid + end + [obj.name, obj.send(id), obj.send(id).to_s].each do |test| + value = nil + assert_nothing_raised do + value = get_posix_field(space, :name, test) + end + assert_equal(obj.name, value) + end + end + end + + def test_get_provider_value + user = nonrootuser + obj = mk_posix_resource(:user, user) + + assert_nothing_raised do + assert_equal(user.uid, get_provider_value(:user, :uid, user.uid)) + assert_equal(user.name, get_provider_value(:user, :name, user.name)) + end + end + + def test_gid_and_uid + {:user => nonrootuser, :group => nonrootgroup}.each do |type, obj| + method = idfield(type) + # First make sure we get it back with both name and id with no object + [obj.name, obj.send(method)].each do |value| + assert_equal(obj.send(method), send(method, value)) + end + + # Now make a Puppet resource and make sure we get it from that. + resource = mk_posix_resource(type, obj) + + [obj.name, obj.send(method)].each do |value| + assert_equal(obj.send(method), send(method, value)) + end + end + end + + def test_util_methods + assert(Puppet::Util.respond_to?(:uid), "util does not have methods") + end + + # First verify we can convert a known user + def test_gidbyname + %x{groups}.split(" ").each { |group| + gid = nil + assert_nothing_raised { + gid = Puppet::Util.gid(group) + } + + assert(gid, "Could not retrieve gid for %s" % group) + } + end + + # Then verify we can retrieve a known group by gid + def test_gidbyid + %x{groups}.split(" ").each { |group| + obj = Puppet.type(:group).create( + :name => group, + :check => [:gid] + ) + obj.setdefaults + obj.retrieve + id = obj.is(:gid) + gid = nil + assert_nothing_raised { + gid = Puppet::Util.gid(id) + } + + assert(gid, "Could not retrieve gid for %s" % group) + assert_equal(id, gid, "Got mismatched ids") + } + end + + # Finally, verify that we can find groups by id even if we don't + # know them + def test_gidbyunknownid + gid = nil + group = Puppet::SUIDManager.gid + assert_nothing_raised { + gid = Puppet::Util.gid(group) + } + + assert(gid, "Could not retrieve gid for %s" % group) + assert_equal(group, gid, "Got mismatched ids") + end + + def user + require 'etc' + unless defined? @user + obj = Etc.getpwuid(Puppet::SUIDManager.uid) + @user = obj.name + end + return @user + end + + # And do it all over again for users + # First verify we can convert a known user + def test_uidbyname + user = user() + uid = nil + assert_nothing_raised { + uid = Puppet::Util.uid(user) + } + + assert(uid, "Could not retrieve uid for %s" % user) + assert_equal(Puppet::SUIDManager.uid, uid, "UIDs did not match") + end + + # Then verify we can retrieve a known user by uid + def test_uidbyid + user = user() + obj = Puppet.type(:user).create( + :name => user, + :check => [:uid] + ) + obj.setdefaults + obj.retrieve + id = obj.is(:uid) + uid = nil + assert_nothing_raised { + uid = Puppet::Util.uid(id) + } + + assert(uid, "Could not retrieve uid for %s" % user) + assert_equal(id, uid, "Got mismatched ids") + end + + # Finally, verify that we can find users by id even if we don't + # know them + def test_uidbyunknownid + uid = nil + user = Puppet::SUIDManager.uid + assert_nothing_raised { + uid = Puppet::Util.uid(user) + } + + assert(uid, "Could not retrieve uid for %s" % user) + assert_equal(user, uid, "Got mismatched ids") + end +end + +# $Id$
\ No newline at end of file diff --git a/test/util/utiltest.rb b/test/util/utiltest.rb index 1ab2ebb9c..ffb2ef347 100755 --- a/test/util/utiltest.rb +++ b/test/util/utiltest.rb @@ -40,105 +40,6 @@ class TestPuppetUtil < Test::Unit::TestCase threads.each { |th| th.join } end - # First verify we can convert a known user - def test_gidbyname - %x{groups}.split(" ").each { |group| - gid = nil - assert_nothing_raised { - gid = Puppet::Util.gid(group) - } - - assert(gid, "Could not retrieve gid for %s" % group) - - assert(Puppet.type(:group)[group], "Util did not create %s" % group) - } - end - - # Then verify we can retrieve a known group by gid - def test_gidbyid - %x{groups}.split(" ").each { |group| - obj = Puppet.type(:group).create( - :name => group, - :check => [:gid] - ) - obj.retrieve - id = obj.is(:gid) - gid = nil - assert_nothing_raised { - gid = Puppet::Util.gid(id) - } - - assert(gid, "Could not retrieve gid for %s" % group) - assert_equal(id, gid, "Got mismatched ids") - } - end - - # Finally, verify that we can find groups by id even if we don't - # know them - def test_gidbyunknownid - gid = nil - group = Puppet::SUIDManager.gid - assert_nothing_raised { - gid = Puppet::Util.gid(group) - } - - assert(gid, "Could not retrieve gid for %s" % group) - assert_equal(group, gid, "Got mismatched ids") - end - - def user - require 'etc' - unless defined? @user - obj = Etc.getpwuid(Puppet::SUIDManager.uid) - @user = obj.name - end - return @user - end - - # And do it all over again for users - # First verify we can convert a known user - def test_uidbyname - user = user() - uid = nil - assert_nothing_raised { - uid = Puppet::Util.uid(user) - } - - assert(uid, "Could not retrieve uid for %s" % user) - assert_equal(Puppet::SUIDManager.uid, uid, "UIDs did not match") - assert(Puppet.type(:user)[user], "Util did not create %s" % user) - end - - # Then verify we can retrieve a known user by uid - def test_uidbyid - user = user() - obj = Puppet.type(:user).create( - :name => user, - :check => [:uid] - ) - obj.retrieve - id = obj.is(:uid) - uid = nil - assert_nothing_raised { - uid = Puppet::Util.uid(id) - } - - assert(uid, "Could not retrieve uid for %s" % user) - assert_equal(id, uid, "Got mismatched ids") - end - - # Finally, verify that we can find users by id even if we don't - # know them - def test_uidbyunknownid - uid = nil - user = Puppet::SUIDManager.uid - assert_nothing_raised { - uid = Puppet::Util.uid(user) - } - - assert(uid, "Could not retrieve uid for %s" % user) - assert_equal(user, uid, "Got mismatched ids") - end def test_withumask oldmask = File.umask |