diff options
-rwxr-xr-x | bin/puppetdoc | 2 | ||||
-rw-r--r-- | lib/puppet/parser/collector.rb | 2 | ||||
-rw-r--r-- | lib/puppet/parser/functions.rb | 92 | ||||
-rw-r--r-- | lib/puppet/rails.rb | 18 | ||||
-rw-r--r-- | lib/puppet/reports/tagmail.rb | 2 | ||||
-rwxr-xr-x | lib/puppet/server/report.rb | 26 | ||||
-rw-r--r-- | lib/puppet/util/docs.rb | 28 | ||||
-rwxr-xr-x | test/language/functions.rb | 4 |
8 files changed, 149 insertions, 25 deletions
diff --git a/bin/puppetdoc b/bin/puppetdoc index 1ee7406c2..ff4e8f4ec 100755 --- a/bin/puppetdoc +++ b/bin/puppetdoc @@ -217,7 +217,7 @@ Below is a list of all documented parameters. Any default values are in ``block end # Print the docs for types -def self.types +def self.typedocs puts %{--- inMenu: true title: Type Reference diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb index 61807717d..2b4e71d77 100644 --- a/lib/puppet/parser/collector.rb +++ b/lib/puppet/parser/collector.rb @@ -27,7 +27,7 @@ class Puppet::Parser::Collector # and such, we'll need to vary the conditions, but this works with no # attributes, anyway. Puppet::Util.benchmark(:debug, "Collected #{self.type} resources") do - Puppet::Rails::RailsResource.find_all_by_restype_and_exported(@type, true, + Puppet::Rails::Resource.find_all_by_restype_and_exported(@type, true, args ).each do |obj| count += 1 diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb index 7fb19475e..35c51da7c 100644 --- a/lib/puppet/parser/functions.rb +++ b/lib/puppet/parser/functions.rb @@ -11,8 +11,19 @@ module Functions include Puppet::Util end + def self.autoloader + unless defined? @autoloader + @autoloader = Puppet::Autoload.new(self, + "puppet/parser/functions", + :wrap => false + ) + end + + @autoloader + end + # Create a new function type. - def self.newfunction(name, ftype = :statement, doc = nil, &block) + def self.newfunction(name, options = {}, &block) @functions ||= {} name = symbolize(name) @@ -26,6 +37,8 @@ module Functions eval("module FCollection; end") end + ftype = options[:type] || :statement + unless ftype == :statement or ftype == :rvalue raise Puppet::DevError, "Invalid statement type %s" % ftype.inspect end @@ -36,21 +49,17 @@ module Functions # Someday we'll support specifying an arity, but for now, nope #@functions[name] = {:arity => arity, :type => ftype} @functions[name] = {:type => ftype, :name => fname} + if options[:doc] + @functions[name][:doc] = options[:doc] + end end # Determine if a given name is a function def self.function(name) name = symbolize(name) - unless defined? @autoloader - @autoloader = Puppet::Autoload.new(self, - "puppet/parser/functions", - :wrap => false - ) - end - unless @functions.include? name - @autoloader.load(name) + autoloader.load(name) end if @functions.include? name @@ -60,6 +69,42 @@ module Functions end end + def self.functiondocs + autoloader.loadall + + header = %{inMenu: true +title: Function Reference +orderInfo: 40 + +There are two types of functions in Puppet: Statements and rvalues. +Statements stand on their own and do not return arguments; they are used for +performing stand-alone work like importing. Rvalues return values and can +only be used in a statement requiring a value, such as an assignment or a case +statement. + +Here are the functions available in Puppet: + +} + + ret = header.dup + + @functions.sort { |a,b| a[0].to_s <=> b[0].to_s }.each do |name, hash| + ret += "* **%s** (*%s*)" % [name, hash[:type]] + if hash[:doc] + ret += ": " + hash[:doc].gsub(/\n\s*/, ' ') + else + ret += ": ``undocumented``" + end + ret += "\n\n" + end + + return ret + end + + def self.functions + @functions.keys + end + # Determine if a given function returns a value or not. def self.rvalue?(name) name = symbolize(name) @@ -75,7 +120,7 @@ module Functions end # Include the specified classes - newfunction(:include) do |vals| + newfunction(:include, :doc => "Evaluate one or more classes.") do |vals| klasses = evalclasses(*vals) missing = vals.find_all do |klass| @@ -93,13 +138,18 @@ module Functions end # Tag the current scope with each passed name - newfunction(:tag) do |vals| + newfunction(:tag, :doc => "Add the specified tags to the containing class + or definition. All contained objects will then acquire that tag, also. + ") do |vals| self.tag(*vals) end # Test whether a given tag is set. This functions as a big OR -- if any of the # specified tags are unset, we return false. - newfunction(:tagged, :rvalue) do |vals| + newfunction(:tagged, :type => :rvalue, :doc => "A boolean function that + tells you whether the current container is tagged with the specified tags. + The tags are ANDed, so thta all of the specified tags must be included for + the function to return true.") do |vals| classlist = self.classlist retval = true @@ -114,7 +164,8 @@ module Functions end # Test whether a given class or definition is defined - newfunction(:defined, :rvalue) do |vals| + newfunction(:defined, :type => :rvalue, :doc => "Determine whether a given + type is defined, either as a native type or a defined type.") do |vals| # For some reason, it doesn't want me to return from here. if vals.detect do |val| Puppet::Type.type(val) or finddefine(val) end true @@ -124,19 +175,22 @@ module Functions end - newfunction(:fail, :statement) do |vals| + newfunction(:fail, :doc => "Fail with a parse error.") do |vals| vals = vals.collect { |s| s.to_s }.join(" ") if vals.is_a? Array raise Puppet::ParseError, vals.to_s end # Runs a newfunction to create a function for each of the log levels Puppet::Log.levels.each do |level| - newfunction(level, :statement) do |vals| + newfunction(level, :doc => "Log a message on the server at level + #{level.to_s}.") do |vals| send(level, vals.join(" ")) end end - newfunction(:template, :rvalue) do |vals| + newfunction(:template, :type => :rvalue, :doc => "Evaluate a template and + return its value. See [the templating docs](../advanced/templating.html) + for more information.") do |vals| require 'erb' vals.collect do |file| @@ -157,7 +211,11 @@ module Functions # This is just syntactic sugar for a collection, although it will generally # be a good bit faster. - newfunction(:realize, :statement) do |vals| + newfunction(:realize, :doc => "Make a virtual object real. This is useful + when you want to know the name of the virtual object and don't want to + bother with a full collection. It is slightly faster than a collection, + and, of course, is a bit shorter. You must pass the object using a + reference; e.g.: ``realize User[luke]``." ) do |vals| coll = Puppet::Parser::Collector.new(self, :nomatter, nil, nil, :virtual) vals = [vals] unless vals.is_a?(Array) coll.resources = vals diff --git a/lib/puppet/rails.rb b/lib/puppet/rails.rb index e041f8342..42baee8bb 100644 --- a/lib/puppet/rails.rb +++ b/lib/puppet/rails.rb @@ -38,7 +38,7 @@ require 'puppet/rails/database/schema_init' Puppet.config.setdefaults(:puppetmaster, #this should be changed to use $statedir, but for now it only works this way. - :dblocation => { :default => "#{Puppet[:statedir]}/clientconfigs.sqlite3", + :dblocation => { :default => "$statedir/clientconfigs.sqlite3", :mode => 0600, :owner => "$user", :group => "$group", @@ -54,14 +54,13 @@ require 'puppet/rails/database/schema_init' :dbpassword => [ "puppet", "The database password for Client caching. Only used when networked databases are used."], #this should be changed to use $logdir, but for now it only works this way. - :railslog => {:default => "#{Puppet[:logdir]}/puppetrails.log", + :railslog => {:default => "$logdir/puppetrails.log", :mode => 0600, :owner => "$user", :group => "$group", :desc => "Where Rails-specific logs are sent" } ) - ActiveRecord::Base.logger = Logger.new(Puppet[:railslog]) def self.clear @inited = false @@ -85,6 +84,12 @@ require 'puppet/rails/database/schema_init' case Puppet[:dbadapter] when "sqlite3": args[:database] = Puppet[:dblocation] + unless FileTest.exists?(Puppet[:dblocation]) + Puppet.config.use(:puppet) + Puppet.config.write(:dblocation) do |f| + f.print "" + end + end when "mysql": args[:host] = Puppet[:dbserver] @@ -101,7 +106,11 @@ require 'puppet/rails/database/schema_init' end raise Puppet::Error, "Could not connect to database: %s" % detail end - @inited = true if ActiveRecord::Base.connection.tables.include? "resources" + begin + @inited = true if ActiveRecord::Base.connection.tables.include? "resources" + rescue SQLite3::CantOpenException => detail + @inited = false + end #puts "Database initialized: #{@inited.inspect} " end @@ -130,6 +139,7 @@ require 'puppet/rails/database/schema_init' Puppet::Rails::Schema.init end Puppet.config.use(:puppet) + ActiveRecord::Base.logger = Logger.new(Puppet[:railslog]) end end diff --git a/lib/puppet/reports/tagmail.rb b/lib/puppet/reports/tagmail.rb index 6018c6424..6c1dca675 100644 --- a/lib/puppet/reports/tagmail.rb +++ b/lib/puppet/reports/tagmail.rb @@ -36,6 +36,8 @@ Puppet::Server::Report.newreport(:tagmail) do all: me@domain.com webserver, !mailserver: httpadmins@domain.com + This will send all messages to ``me@domain.com``, and all messages from + webservers that are not also from mailservers to ``httpadmins@domain.com``. " def process diff --git a/lib/puppet/server/report.rb b/lib/puppet/server/report.rb index 6253f6a0e..bbc8e7ddb 100755 --- a/lib/puppet/server/report.rb +++ b/lib/puppet/server/report.rb @@ -72,6 +72,32 @@ class Server @reports[symbolize(name)] end + def self.reportdocs + docs = %{Puppet clients can report back to the server after each +transaction. This transaction report is sent as a YAML dump and includes every +log message that was generated during the transaction along with as many metrics +as Puppet knows how to collect. + +Currently, clients default to not sending in reports; you can enable reporting +by setting the ``report`` parameter to true. + +To use a report, set the ``reports`` parameter on the server; multiple +reports must be comma-separated. + +Puppet provides multiple report handlers that will process client reports: + +} + # Use this method so they all get loaded + reports.sort { |a,b| a.to_s <=> b.to_s }.each do |name| + mod = self.report(name) + docs += "## %s\n\n" % name + + docs += Puppet::Util::Docs.scrub(mod.doc) + "\n\n" + end + + docs + end + def self.reports @reportloader.loadall @reports.keys diff --git a/lib/puppet/util/docs.rb b/lib/puppet/util/docs.rb index 01aea7d3d..ebbce7317 100644 --- a/lib/puppet/util/docs.rb +++ b/lib/puppet/util/docs.rb @@ -26,6 +26,34 @@ module Puppet::Util::Docs extra end end + + # Handle the inline indentation in the docs. + def scrub(text) + # Stupid markdown + #text = text.gsub("<%=", "<%=") + # For text with no carriage returns, there's nothing to do. + if text !~ /\n/ + return text + end + indent = nil + + # If we can match an indentation, then just remove that same level of + # indent from every line. + if text =~ /^(\s+)/ + indent = $1 + begin + return text.gsub(/^#{indent}/,'') + rescue => detail + puts detail.backtrace + puts detail + end + else + return text + end + + end + + module_function :scrub end # $Id$ diff --git a/test/language/functions.rb b/test/language/functions.rb index bd7143db6..b69c2bfa2 100755 --- a/test/language/functions.rb +++ b/test/language/functions.rb @@ -23,7 +23,7 @@ class TestLangFunctions < Test::Unit::TestCase end assert_nothing_raised do - Puppet::Parser::Functions.newfunction(:fakefunction, :rvalue) do |input| + Puppet::Parser::Functions.newfunction(:fakefunction, :type => :rvalue) do |input| return "output %s" % input[0] end end @@ -289,7 +289,7 @@ class TestLangFunctions < Test::Unit::TestCase File.open(File.join(newpath, "autofunc.rb"), "w") { |f| f.puts %{ - Puppet::Parser::Functions.newfunction(:autofunc, :rvalue) do |vals| + Puppet::Parser::Functions.newfunction(:autofunc, :type => :rvalue) do |vals| Puppet.wanring vals.inspect end } |