Refactoring puppetdoc so it is a bit cleaner and is actually object-oriented. PDF output still fails miserably (there has to be some kind of markup problem, but I have no idea what), but other output now successfully varies on the pages.
git-svn-id: https://reductivelabs.com/svn/puppet/trunk@2411 980ebf18-57e1-0310-9a29-db15c13687c0
This commit is contained in:
Родитель
0ff37720f9
Коммит
0681cfa481
455
bin/puppetdoc
455
bin/puppetdoc
|
@ -8,7 +8,7 @@
|
|||
#
|
||||
# = Usage
|
||||
#
|
||||
# puppetdoc [-h|--help] [-m|--mode <typedocs|configref>
|
||||
# puppetdoc [-a|--all] [-h|--help] [-m|--mode <text|pdf|trac> [-s|--section <[type]|configuration|report|function>]
|
||||
#
|
||||
# = Description
|
||||
#
|
||||
|
@ -26,19 +26,14 @@
|
|||
# Print this help message
|
||||
#
|
||||
# mode::
|
||||
# Print documentation of a given type. Valid optinos are 'typedocs', for
|
||||
# resource type documentation, and 'configref', for documentation on all
|
||||
# of the configuration parameters.
|
||||
# Determine the output mode. Valid modes are 'text', 'trac', and 'pdf'. Note that 'trac' mode only works on Reductive Labs servers. The default mode is 'text'.
|
||||
#
|
||||
# pdf::
|
||||
# Create a PDF of the output.
|
||||
#
|
||||
# trac::
|
||||
# Write the reference docs to trac. Only works on servers at Reductive Labs.
|
||||
# section::
|
||||
# Handle a particular section. Available sections are 'type', 'configuration', 'report', and 'function'. The default section is 'type'.
|
||||
#
|
||||
# = Example
|
||||
#
|
||||
# $ puppetdoc > /tmp/reference.rst
|
||||
# $ puppetdoc > /tmp/type_reference.rst
|
||||
#
|
||||
# = Author
|
||||
#
|
||||
|
@ -46,37 +41,194 @@
|
|||
#
|
||||
# = Copyright
|
||||
#
|
||||
# Copyright (c) 2005 Reductive Labs, LLC
|
||||
# Copyright (c) 2005-2007 Reductive Labs, LLC
|
||||
# Licensed under the GNU Public License
|
||||
|
||||
require 'puppet'
|
||||
|
||||
class PuppetDoc
|
||||
include Puppet::Util::Docs
|
||||
@@sections = {}
|
||||
|
||||
attr_accessor :page, :depth, :header, :title
|
||||
|
||||
def self.[](name)
|
||||
@@sections[name]
|
||||
end
|
||||
|
||||
def self.each
|
||||
@@sections.sort { |a, b| a[0].to_s <=> b[0].to_s }.each { |name, instance| yield instance }
|
||||
end
|
||||
|
||||
def self.footer
|
||||
"\n\n----------------\n\n*This page autogenerated on %s*\n" % Time.now
|
||||
end
|
||||
|
||||
def self.page(*sections)
|
||||
depth = 4
|
||||
# Use the minimum depth
|
||||
sections.each do |name|
|
||||
section = @@sections[name] or raise "Could not find section %s" % name
|
||||
depth = section.depth if section.depth < depth
|
||||
end
|
||||
text = ".. contents:: :depth: 2\n\n"
|
||||
end
|
||||
|
||||
def self.pdf(text)
|
||||
puts "creating pdf"
|
||||
File.open("/tmp/puppetdoc.txt", "w") do |f|
|
||||
f.puts text
|
||||
end
|
||||
rst2latex = %x{which rst2latex}
|
||||
if $? != 0 or rst2latex =~ /no /
|
||||
rst2latex = %x{which rst2latex.py}
|
||||
end
|
||||
if $? != 0 or rst2latex =~ /no /
|
||||
raise "Could not find rst2latex"
|
||||
end
|
||||
rst2latex.chomp!
|
||||
cmd = %{#{rst2latex} /tmp/puppetdoc.txt > /tmp/puppetdoc.tex}
|
||||
output = %x{#{cmd}}
|
||||
unless $? == 0
|
||||
$stderr.puts "rst2latex failed"
|
||||
$stderr.puts output
|
||||
exit(1)
|
||||
end
|
||||
$stderr.puts output
|
||||
|
||||
# Now convert to pdf
|
||||
puts "handling pdf"
|
||||
Dir.chdir("/tmp") do
|
||||
%x{texi2pdf puppetdoc.tex >/dev/null 2>/dev/null}
|
||||
end
|
||||
|
||||
#if FileTest.exists?("/tmp/puppetdoc.pdf")
|
||||
# FileUtils.mv("/tmp/puppetdoc.pdf", "/export/apache/docroots/reductivelabs.com/htdocs/downloads/puppet/reference.pdf")
|
||||
#end
|
||||
end
|
||||
|
||||
def self.sections
|
||||
@@sections.keys.sort { |a,b| a.to_s <=> b.to_s }
|
||||
end
|
||||
|
||||
HEADER_LEVELS = [nil, "=", "-", "+", "'", "~"]
|
||||
|
||||
def h(name, level)
|
||||
return "%s\n%s\n" % [name, HEADER_LEVELS[level] * name.to_s.length]
|
||||
end
|
||||
|
||||
def initialize(name, options = {}, &block)
|
||||
@name = name
|
||||
options.each do |option, value|
|
||||
send(option.to_s + "=", value)
|
||||
end
|
||||
|
||||
meta_def(:generate, &block)
|
||||
|
||||
@@sections[name] = self
|
||||
|
||||
# Now handle the defaults
|
||||
@title ||= "%s Reference" % @name.to_s.capitalize
|
||||
@page ||= @title.gsub(/\s+/, '')
|
||||
@depth ||= 2
|
||||
@header ||= ""
|
||||
end
|
||||
|
||||
# Indent every line in the chunk except those which begin with '..'.
|
||||
def indent(text, tab)
|
||||
return text.gsub(/(^|\A)/, tab).gsub(/^ +\.\./, "..")
|
||||
end
|
||||
|
||||
def paramwrap(name, text, options = {})
|
||||
options[:level] ||= 5
|
||||
#str = "%s : " % name
|
||||
str = h(name, options[:level])
|
||||
if options[:namevar]
|
||||
str += "- **namevar**\n\n"
|
||||
end
|
||||
str += text
|
||||
#str += text.gsub(/\n/, "\n ")
|
||||
|
||||
str += "\n\n"
|
||||
return str
|
||||
end
|
||||
|
||||
def output(withcontents = true)
|
||||
# First the header
|
||||
text = h(@title, 1)
|
||||
if withcontents
|
||||
text += ".. contents:: :depth: %s\n\n" % @depth
|
||||
end
|
||||
|
||||
text += @header
|
||||
|
||||
text += generate()
|
||||
|
||||
if withcontents
|
||||
text += self.class.footer
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
def text
|
||||
puts output
|
||||
end
|
||||
|
||||
def trac
|
||||
File.open("/tmp/puppetdoc.txt", "w") do |f|
|
||||
|
||||
f.puts "{{{
|
||||
#!rst\n
|
||||
#{self.output}
|
||||
}}}"
|
||||
end
|
||||
|
||||
puts "Writing %s reference to trac as %s" % [@name, @page]
|
||||
cmd = %{sudo trac-admin /export/svn/trac/puppet wiki import %s /tmp/puppetdoc.txt} % self.page
|
||||
output = %x{#{cmd}}
|
||||
unless $? == 0
|
||||
$stderr.puts "trac-admin failed"
|
||||
$stderr.puts output
|
||||
exit(1)
|
||||
end
|
||||
unless output =~ /^\s+/
|
||||
$stderr.puts output
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
require 'puppet'
|
||||
require 'puppet/network/handler'
|
||||
require 'getoptlong'
|
||||
|
||||
result = GetoptLong.new(
|
||||
[ "--pdf", "-p", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--all", "-a", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--trac", "-t", GetoptLong::NO_ARGUMENT ],
|
||||
[ "--mode", "-m", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--section", "-s", GetoptLong::REQUIRED_ARGUMENT ],
|
||||
[ "--help", "-h", GetoptLong::NO_ARGUMENT ]
|
||||
)
|
||||
|
||||
debug = false
|
||||
|
||||
$tab = " "
|
||||
options = {:modes => []}
|
||||
options = {:sections => [], :mode => :text}
|
||||
|
||||
begin
|
||||
result.each { |opt,arg|
|
||||
case opt
|
||||
when "--all"
|
||||
options[:all] = true
|
||||
when "--trac"
|
||||
options[:trac] = true
|
||||
when "--pdf"
|
||||
options[:pdf] = true
|
||||
when "--mode"
|
||||
options[:modes] << arg.intern
|
||||
case arg
|
||||
when "text", "pdf", "trac":
|
||||
options[:mode] = arg.intern
|
||||
else
|
||||
raise "Invalid output mode %s" % arg
|
||||
end
|
||||
when "--section"
|
||||
options[:sections] << arg.intern
|
||||
when "--help"
|
||||
if Puppet.features.usage?
|
||||
RDoc::usage && exit
|
||||
|
@ -91,23 +243,52 @@ rescue GetoptLong::InvalidOption => detail
|
|||
exit(1)
|
||||
end
|
||||
|
||||
if options[:modes].empty?
|
||||
options[:modes] << :typedocs
|
||||
if options[:sections].empty?
|
||||
options[:sections] << :type
|
||||
end
|
||||
|
||||
include Puppet::Util::Docs
|
||||
config = PuppetDoc.new :configuration, :depth => 1 do
|
||||
docs = {}
|
||||
Puppet.config.each do |name, object|
|
||||
docs[name] = object
|
||||
end
|
||||
|
||||
TRACMAP = {
|
||||
:configref => "ConfigurationReference",
|
||||
:reports => "ReportReference",
|
||||
:functions => "FunctionReference",
|
||||
:typedocs => "TypeReference"
|
||||
}
|
||||
str = ""
|
||||
docs.sort { |a, b|
|
||||
a[0].to_s <=> b[0].to_s
|
||||
}.each do |name, object|
|
||||
# Make each name an anchor
|
||||
header = name.to_s
|
||||
str += h(header, 3)
|
||||
|
||||
HEADERS = {
|
||||
:configref => "Puppet Configuration Reference
|
||||
==============================
|
||||
# Print the doc string itself
|
||||
begin
|
||||
str += object.desc.gsub(/\n/, " ")
|
||||
rescue => detail
|
||||
puts detail.backtrace
|
||||
puts detail
|
||||
end
|
||||
str += "\n\n"
|
||||
|
||||
# Now print the data about the item.
|
||||
str += ""
|
||||
val = object.default
|
||||
if name.to_s == "vardir"
|
||||
val = "/var/puppet"
|
||||
elsif name.to_s == "confdir"
|
||||
val = "/etc/puppet"
|
||||
end
|
||||
str += "- **Section**: %s\n" % object.section
|
||||
unless val == ""
|
||||
str += "- **Default**: %s\n" % val
|
||||
end
|
||||
str += "\n"
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
config.header = "
|
||||
Specifying Configuration Parameters
|
||||
-----------------------------------
|
||||
|
||||
|
@ -181,24 +362,26 @@ and one `puppet` user) if it is invoked as `root` with the `--mkusers` argument:
|
|||
|
||||
Signals
|
||||
-------
|
||||
The `puppetd` and `puppetmasterd` executables catch some signals for special
|
||||
handling. Both daemons catch (`SIGHUP`), which forces the server to restart
|
||||
tself. Predictably, interrupt and terminate (`SIGINT` and `SIGHUP`) will shut
|
||||
down the server, whether it be an instance of `puppetd` or `puppetmasterd`.
|
||||
The ``puppetd`` and ``puppetmasterd`` executables catch some signals for special
|
||||
handling. Both daemons catch (``SIGHUP``), which forces the server to restart
|
||||
tself. Predictably, interrupt and terminate (``SIGINT`` and ``SIGHUP``) will shut
|
||||
down the server, whether it be an instance of ``puppetd`` or ``puppetmasterd``.
|
||||
|
||||
Sending the `SIGUSR1` signal to an instance of `puppetd` will cause it to
|
||||
Sending the ``SIGUSR1`` signal to an instance of ``puppetd`` will cause it to
|
||||
immediately begin a new configuration transaction with the server. This
|
||||
signal has no effect on `puppetmasterd`.
|
||||
signal has no effect on ``puppetmasterd``.
|
||||
|
||||
Configuration Parameter Reference
|
||||
---------------------------------
|
||||
Below is a list of all documented parameters. Not all of them are valid with all
|
||||
Puppet executables, but the executables will ignore any inappropriate values.
|
||||
|
||||
Below is a list of all documented parameters. Any default values are in ``block type`` at the end of the description.
|
||||
"
|
||||
|
||||
",
|
||||
:reports => "
|
||||
Reports Reference
|
||||
=================
|
||||
report = PuppetDoc.new :report do
|
||||
Puppet::Network::Handler.report.reportdocs
|
||||
end
|
||||
report.header = "
|
||||
Puppet clients can report back to the server after each transaction. This
|
||||
transaction report is sent as a YAML dump of the
|
||||
``Puppet::Transaction::Report`` class and includes every log message that was
|
||||
|
@ -214,11 +397,12 @@ reports must be comma-separated. You can also specify ``none`` to disable
|
|||
reports entirely.
|
||||
|
||||
Puppet provides multiple report handlers that will process client reports:
|
||||
"
|
||||
|
||||
",
|
||||
:functions => "
|
||||
Function Reference
|
||||
==================
|
||||
function = PuppetDoc.new :function do
|
||||
Puppet::Parser::Functions.functiondocs
|
||||
end
|
||||
function.header = "
|
||||
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
|
||||
|
@ -226,102 +410,9 @@ only be used in a statement requiring a value, such as an assignment or a case
|
|||
statement.
|
||||
|
||||
Here are the functions available in Puppet:
|
||||
|
||||
",
|
||||
:typedocs => "
|
||||
Resource Type Reference
|
||||
=======================
|
||||
|
||||
"
|
||||
}
|
||||
|
||||
def h(name, level)
|
||||
levels = [nil, "=", "-", "+", "'", "~"]
|
||||
return "%s\n%s\n" % [name, levels[level] * name.to_s.length]
|
||||
end
|
||||
|
||||
# Indent every line in the chunk except those which begin with '..'.
|
||||
def indent(text, tab)
|
||||
return text.gsub(/(^|\A)/, tab).gsub(/^ +\.\./, "..")
|
||||
end
|
||||
|
||||
def paramwrap(name, text, options = {})
|
||||
options[:level] ||= 5
|
||||
#str = "%s : " % name
|
||||
str = h(name, options[:level])
|
||||
if options[:namevar]
|
||||
str += "- **namevar**\n\n"
|
||||
end
|
||||
str += text
|
||||
#str += text.gsub(/\n/, "\n ")
|
||||
|
||||
str += "\n\n"
|
||||
return str
|
||||
end
|
||||
|
||||
def tracwrite(text, mode)
|
||||
File.open("/tmp/puppetdoc.txt", "w") do |f|
|
||||
|
||||
f.puts "{{{
|
||||
#!rst\n
|
||||
#{text}
|
||||
}}}"
|
||||
end
|
||||
cmd = %{sudo trac-admin /export/svn/trac/puppet wiki import %s /tmp/puppetdoc.txt} % TRACMAP[mode]
|
||||
output = %x{#{cmd}}
|
||||
unless $? == 0
|
||||
$stderr.puts "trac-admin failed"
|
||||
$stderr.puts output
|
||||
exit(1)
|
||||
end
|
||||
unless output =~ /^\s+/
|
||||
$stderr.puts output
|
||||
end
|
||||
end
|
||||
|
||||
# Print the docs for arguments
|
||||
def self.configref
|
||||
docs = {}
|
||||
Puppet.config.each do |name, object|
|
||||
docs[name] = object
|
||||
end
|
||||
|
||||
str = ""
|
||||
docs.sort { |a, b|
|
||||
a[0].to_s <=> b[0].to_s
|
||||
}.each do |name, object|
|
||||
# Make each name an anchor
|
||||
header = name.to_s
|
||||
str += h(header, 3)
|
||||
|
||||
# Print the doc string itself
|
||||
begin
|
||||
str += object.desc.gsub(/\n/, " ")
|
||||
rescue => detail
|
||||
puts detail.backtrace
|
||||
puts detail
|
||||
end
|
||||
str += "\n"
|
||||
|
||||
# Now print the data about the item.
|
||||
str += ""
|
||||
default = ""
|
||||
val = object.value
|
||||
str += "- **Section**: %s\n" % object.section
|
||||
unless val == ""
|
||||
str += "- **Default**: %s\n" % val
|
||||
end
|
||||
#if val = object.value and val != ""
|
||||
# default = " ``%s``" % val
|
||||
#end
|
||||
str += "\n"
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
# Print the docs for types
|
||||
def self.typedocs
|
||||
type = PuppetDoc.new :type do
|
||||
types = {}
|
||||
Puppet::Type.loadall
|
||||
|
||||
|
@ -474,78 +565,38 @@ Resource Types
|
|||
str
|
||||
end
|
||||
|
||||
def self.reports
|
||||
Puppet::Network::Handler.report.reportdocs
|
||||
end
|
||||
|
||||
def self.functions
|
||||
Puppet::Parser::Functions.functiondocs
|
||||
end
|
||||
|
||||
if options[:all]
|
||||
options[:modes] = HEADERS.keys
|
||||
options[:sections] = PuppetDoc.sections
|
||||
end
|
||||
|
||||
text = ".. contents::\n\n"
|
||||
|
||||
options[:modes].sort { |a, b| a.to_s <=> b.to_s }.each do |mode|
|
||||
unless respond_to?(mode)
|
||||
raise "Invalid mode %s" % mode
|
||||
case options[:mode]
|
||||
when :trac
|
||||
options[:sections].each do |name|
|
||||
section = PuppetDoc[name] or raise "Could not find section %s" % name
|
||||
unless options[:mode] == :pdf
|
||||
section.trac
|
||||
end
|
||||
end
|
||||
|
||||
text += HEADERS[mode]
|
||||
text += send(mode)
|
||||
end
|
||||
|
||||
text += "
|
||||
|
||||
----------------
|
||||
|
||||
"
|
||||
text += "\n*This page autogenerated on %s*" % Time.now
|
||||
|
||||
if options[:trac]
|
||||
if options[:modes].length > 1
|
||||
raise "Cannot write more than one mode to trac at once"
|
||||
end
|
||||
tracwrite(text, options[:modes][0])
|
||||
else
|
||||
text = ".. contents:: :depth: 1\n\n"
|
||||
options[:sections].sort { |a,b| a.to_s <=> b.to_s }.each do |name|
|
||||
section = PuppetDoc[name]
|
||||
|
||||
# Add the per-section text, but with no ToC
|
||||
text += section.output(false)
|
||||
end
|
||||
|
||||
text += PuppetDoc.footer
|
||||
|
||||
# Replace the trac links, since they're invalid everywhere else
|
||||
text.gsub!(/`\w+\s+([^`]+)`:trac/) { |m| $1 }
|
||||
text.gsub!(/`\w+\s+([^`]+)`:trac:/) { |m| $1 }
|
||||
|
||||
if options[:pdf]
|
||||
File.open("/tmp/puppetdoc.txt", "w") do |f|
|
||||
f.puts text
|
||||
end
|
||||
rst2latex = %x{which rst2latex}
|
||||
if $? != 0 or rst2latex =~ /no /
|
||||
rst2latex = %x{which rst2latex.py}
|
||||
end
|
||||
if $? != 0 or rst2latex =~ /no /
|
||||
raise "Could not find rst2latex"
|
||||
end
|
||||
rst2latex.chomp!
|
||||
cmd = %{#{rst2latex} /tmp/puppetdoc.txt > /tmp/puppetdoc.tex}
|
||||
output = %x{#{cmd}}
|
||||
unless $? == 0
|
||||
$stderr.puts "trac-admin failed"
|
||||
$stderr.puts output
|
||||
exit(1)
|
||||
end
|
||||
$stderr.puts output
|
||||
|
||||
# Now convert to pdf
|
||||
puts "handling pdf"
|
||||
Dir.chdir("/tmp") do
|
||||
%x{texi2pdf puppetdoc.tex >/dev/null 2>/dev/null}
|
||||
end
|
||||
|
||||
if FileTest.exists?("/tmp/puppetdoc.pdf")
|
||||
FileUtils.mv("/tmp/puppetdoc.pdf", "/export/apache/docroots/reductivelabs.com/htdocs/downloads/puppet/reference.pdf")
|
||||
end
|
||||
if options[:mode] == :pdf
|
||||
PuppetDoc.pdf(text)
|
||||
else
|
||||
puts text
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# $Id$
|
||||
|
|
|
@ -15,8 +15,10 @@ module Puppet
|
|||
end
|
||||
|
||||
self.setdefaults(:puppet,
|
||||
:confdir => [conf, "The main Puppet configuration directory."],
|
||||
:vardir => [var, "Where Puppet stores dynamic and growing data."],
|
||||
:confdir => [conf, "The main Puppet configuration directory. The default for this parameter is calculated based on the user. If the process
|
||||
is runnig as root or the user that ``puppetmasterd`` is supposed to run as, it defaults to a system directory, but if it's running as any other user,
|
||||
it defaults to being in ``~``."],
|
||||
:vardir => [var, "Where Puppet stores dynamic and growing data. The default for this parameter is calculated specially, like `confdir`_."],
|
||||
:name => [name, "The name of the service, if we are running as one. The
|
||||
default is essentially $0 without the path or ``.rb``."]
|
||||
)
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
# Provides feature definitions.
|
||||
require 'puppet/util/methodhelper'
|
||||
require 'puppet/util/docs'
|
||||
require 'puppet/util'
|
||||
module Puppet::Util::ProviderFeatures
|
||||
include Puppet::Util::Docs
|
||||
# The class that models the features and handles checking whether the features
|
||||
# are present.
|
||||
class ProviderFeature
|
||||
require 'puppet/util/methodhelper'
|
||||
require 'puppet/util/docs'
|
||||
require 'puppet/util'
|
||||
include Puppet::Util
|
||||
include Puppet::Util::MethodHelper
|
||||
include Puppet::Util::Docs
|
||||
attr_accessor :name, :docs, :methods
|
||||
|
||||
# Are all of the requirements met?
|
||||
|
|
Загрузка…
Ссылка в новой задаче