diff --git a/lib/puppet/reference/configuration.rb b/lib/puppet/reference/configuration.rb index 18efb6fe7..c17151e7d 100644 --- a/lib/puppet/reference/configuration.rb +++ b/lib/puppet/reference/configuration.rb @@ -1,69 +1,69 @@ config = Puppet::Util::Reference.newreference(:configuration, :depth => 1, :doc => "A reference for all configuration parameters") do docs = {} Puppet.settings.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) + str << h(header, 3) # Print the doc string itself begin - str += object.desc.gsub(/\n/, " ") + str << object.desc.gsub(/\n/, " ") rescue => detail puts detail.backtrace puts detail end - str += "\n\n" + str << "\n\n" # Now print the data about the item. - str += "" + str << "" val = object.default if name.to_s == "vardir" val = "/var/lib/puppet" elsif name.to_s == "confdir" val = "/etc/puppet" end # Leave out the section information; it was apparently confusing people. - #str += "- **Section**: #{object.section}\n" + #str << "- **Section**: #{object.section}\n" unless val == "" - str += "- *Default*: #{val}\n" + str << "- *Default*: #{val}\n" end - str += "\n" + str << "\n" end return str end config.header = < "Indirection types and their terminus classes" do text = "" Puppet::Indirector::Indirection.instances.sort { |a,b| a.to_s <=> b.to_s }.each do |indirection| ind = Puppet::Indirector::Indirection.instance(indirection) name = indirection.to_s.capitalize - text += "## " + indirection.to_s + "\n\n" + text << "## " + indirection.to_s + "\n\n" - text += ind.doc + "\n\n" + text << ind.doc + "\n\n" Puppet::Indirector::Terminus.terminus_classes(ind.name).sort { |a,b| a.to_s <=> b.to_s }.each do |terminus| text += "### " + terminus.to_s + "\n\n" term_class = Puppet::Indirector::Terminus.terminus_class(ind.name, terminus) text += Puppet::Util::Docs.scrub(term_class.doc) + "\n\n" end end text end reference.header = "This is the list of all indirections, their associated terminus classes, and how you select between them. In general, the appropriate terminus class is selected by the application for you (e.g., `puppet agent` would always use the `rest` terminus for most of its indirected classes), but some classes are tunable via normal settings. These will have `terminus setting` documentation listed with them. " diff --git a/lib/puppet/reference/network.rb b/lib/puppet/reference/network.rb index fda7931fb..7efa7273d 100644 --- a/lib/puppet/reference/network.rb +++ b/lib/puppet/reference/network.rb @@ -1,39 +1,39 @@ require 'puppet/network/handler' network = Puppet::Util::Reference.newreference :network, :depth => 2, :doc => "Available network handlers and clients" do ret = "" Puppet::Network::Handler.subclasses.sort { |a,b| a.to_s <=> b.to_s }.each do |name| handler = Puppet::Network::Handler.handler(name) next if ! handler.doc or handler.doc == "" interface = handler.interface - ret += h(name, 2) - - ret += scrub(handler.doc) - ret += "\n\n" - ret += option(:prefix, interface.prefix) - ret += option(:side, handler.side.to_s.capitalize) - ret += option(:methods, interface.methods.collect { |ary| ary[0] }.join(", ") ) - ret += "\n\n" + ret << h(name, 2) + + ret << scrub(handler.doc) + ret << "\n\n" + ret << option(:prefix, interface.prefix) + ret << option(:side, handler.side.to_s.capitalize) + ret << option(:methods, interface.methods.collect { |ary| ary[0] }.join(", ") ) + ret << "\n\n" end ret end network.header = " This is a list of all Puppet network interfaces. Each interface is implemented in the form of a client and a handler; the handler is loaded on the server, and the client knows how to call the handler's methods appropriately. Most handlers are meant to be started on the server, usually within `puppet master`, and the clients are mostly started on the client, usually within `puppet agent`. You can find the server-side handler for each interface at `puppet/network/handler/.rb` and the client class at `puppet/network/client/.rb`. " diff --git a/lib/puppet/reference/providers.rb b/lib/puppet/reference/providers.rb index c85ad23ab..0e77e484f 100644 --- a/lib/puppet/reference/providers.rb +++ b/lib/puppet/reference/providers.rb @@ -1,123 +1,123 @@ # This doesn't get stored in trac, since it changes every time. providers = Puppet::Util::Reference.newreference :providers, :title => "Provider Suitability Report", :depth => 1, :dynamic => true, :doc => "Which providers are valid for this machine" do types = [] Puppet::Type.loadall Puppet::Type.eachtype do |klass| next unless klass.providers.length > 0 types << klass end types.sort! { |a,b| a.name.to_s <=> b.name.to_s } command_line = Puppet::Util::CommandLine.new types.reject! { |type| ! command_line.args.include?(type.name.to_s) } unless command_line.args.empty? ret = "Details about this host:\n\n" # Throw some facts in there, so we know where the report is from. ["Ruby Version", "Puppet Version", "Operating System", "Operating System Release"].each do |label| name = label.gsub(/\s+/, '') value = Facter.value(name) - ret += option(label, value) + ret << option(label, value) end - ret += "\n" + ret << "\n" count = 1 # Produce output for each type. types.each do |type| features = type.features - ret += "\n" # add a trailing newline + ret << "\n" # add a trailing newline # Now build up a table of provider suitability. headers = %w{Provider Suitable?} + features.collect { |f| f.to_s }.sort table_data = {} functional = false notes = [] begin default = type.defaultprovider.name rescue Puppet::DevError default = "none" end type.providers.sort { |a,b| a.to_s <=> b.to_s }.each do |pname| data = [] table_data[pname] = data provider = type.provider(pname) # Add the suitability note if missing = provider.suitable?(false) and missing.empty? data << "*X*" suit = true functional = true else data << "[#{count}]_" # A pointer to the appropriate footnote suit = false end # Add a footnote with the details about why this provider is unsuitable, if that's the case unless suit details = ".. [#{count}]\n" missing.each do |test, values| case test when :exists - details += " - Missing files #{values.join(", ")}\n" + details << " - Missing files #{values.join(", ")}\n" when :variable values.each do |name, facts| if Puppet.settings.valid?(name) - details += " - Setting #{name} (currently #{Puppet.settings.value(name).inspect}) not in list #{facts.join(", ")}\n" + details << " - Setting #{name} (currently #{Puppet.settings.value(name).inspect}) not in list #{facts.join(", ")}\n" else - details += " - Fact #{name} (currently #{Facter.value(name).inspect}) not in list #{facts.join(", ")}\n" + details << " - Fact #{name} (currently #{Facter.value(name).inspect}) not in list #{facts.join(", ")}\n" end end when :true - details += " - Got #{values} true tests that should have been false\n" + details << " - Got #{values} true tests that should have been false\n" when :false - details += " - Got #{values} false tests that should have been true\n" + details << " - Got #{values} false tests that should have been true\n" when :feature - details += " - Missing features #{values.collect { |f| f.to_s }.join(",")}\n" + details << " - Missing features #{values.collect { |f| f.to_s }.join(",")}\n" end end notes << details count += 1 end # Add a note for every feature features.each do |feature| if provider.features.include?(feature) data << "*X*" else data << "" end end end - ret += h(type.name.to_s + "_", 2) + ret << h(type.name.to_s + "_", 2) - ret += "[#{type.name}](#{"http://docs.puppetlabs.com/references/stable/type.html##{type.name}"})\n\n" - ret += option("Default provider", default) - ret += doctable(headers, table_data) + ret << "[#{type.name}](#{"http://docs.puppetlabs.com/references/stable/type.html##{type.name}"})\n\n" + ret << option("Default provider", default) + ret << doctable(headers, table_data) notes.each do |note| - ret += note + "\n" + ret << note + "\n" end - ret += "\n" + ret << "\n" end - ret += "\n" + ret << "\n" ret end providers.header = " Puppet resource types are usually backed by multiple implementations called `providers`, which handle variance between platforms and tools. Different providers are suitable or unsuitable on different platforms based on things like the presence of a given tool. Here are all of the provider-backed types and their different providers. Any unmentioned types do not use providers yet. " diff --git a/lib/puppet/reference/type.rb b/lib/puppet/reference/type.rb index b423387e9..635d84249 100644 --- a/lib/puppet/reference/type.rb +++ b/lib/puppet/reference/type.rb @@ -1,113 +1,113 @@ type = Puppet::Util::Reference.newreference :type, :doc => "All Puppet resource types and all their details" do types = {} Puppet::Type.loadall Puppet::Type.eachtype { |type| next if type.name == :puppet next if type.name == :component next if type.name == :whit types[type.name] = type } str = %{ ## Resource Types - The *namevar* is the parameter used to uniquely identify a type instance. This is the parameter that gets assigned when a string is provided before the colon in a type declaration. In general, only developers will need to worry about which parameter is the `namevar`. In the following code: file { "/etc/passwd": owner => root, group => root, mode => 644 } `/etc/passwd` is considered the title of the file object (used for things like dependency handling), and because `path` is the namevar for `file`, that string is assigned to the `path` parameter. - *Parameters* determine the specific configuration of the instance. They either directly modify the system (internally, these are called properties) or they affect how the instance behaves (e.g., adding a search path for `exec` instances or determining recursion on `file` instances). - *Providers* provide low-level functionality for a given resource type. This is usually in the form of calling out to external commands. When required binaries are specified for providers, fully qualifed paths indicate that the binary must exist at that specific path and unqualified binaries indicate that Puppet will search for the binary using the shell path. - *Features* are abilities that some providers might not support. You can use the list of supported features to determine how a given provider can be used. Resource types define features they can use, and providers can be tested to see which features they provide. } types.sort { |a,b| a.to_s <=> b.to_s }.each { |name,type| - str += " + str << " ---------------- " - str += h(name, 3) - str += scrub(type.doc) + "\n\n" + str << h(name, 3) + str << scrub(type.doc) + "\n\n" # Handle the feature docs. if featuredocs = type.featuredocs - str += h("Features", 4) - str += featuredocs + str << h("Features", 4) + str << featuredocs end docs = {} type.validproperties.sort { |a,b| a.to_s <=> b.to_s }.reject { |sname| property = type.propertybyname(sname) property.nodoc }.each { |sname| property = type.propertybyname(sname) raise "Could not retrieve property #{sname} on type #{type.name}" unless property doc = nil unless doc = property.doc $stderr.puts "No docs for #{type}[#{sname}]" next end doc = doc.dup tmp = doc tmp = scrub(tmp) docs[sname] = tmp } - str += h("Parameters", 4) + "\n" + str << h("Parameters", 4) + "\n" type.parameters.sort { |a,b| a.to_s <=> b.to_s }.each { |name,param| #docs[name] = indent(scrub(type.paramdoc(name)), $tab) docs[name] = scrub(type.paramdoc(name)) } additional_key_attributes = type.key_attributes - [:name] docs.sort { |a, b| a[0].to_s <=> b[0].to_s }.each { |name, doc| - str += paramwrap(name, doc, :namevar => additional_key_attributes.include?(name)) + str << paramwrap(name, doc, :namevar => additional_key_attributes.include?(name)) } - str += "\n" + str << "\n" } str end diff --git a/lib/puppet/util/reference.rb b/lib/puppet/util/reference.rb index a4921ed2a..03523843f 100644 --- a/lib/puppet/util/reference.rb +++ b/lib/puppet/util/reference.rb @@ -1,140 +1,140 @@ require 'puppet/util/instance_loader' require 'fileutils' # Manage Reference Documentation. class Puppet::Util::Reference include Puppet::Util include Puppet::Util::Docs extend Puppet::Util::InstanceLoader instance_load(:reference, 'puppet/reference') def self.footer "\n\n----------------\n\n*This page autogenerated on #{Time.now}*\n" end def self.modes %w{pdf text} end def self.newreference(name, options = {}, &block) ref = self.new(name, options, &block) instance_hash(:reference)[symbolize(name)] = ref ref end def self.page(*sections) depth = 4 # Use the minimum depth sections.each do |name| section = reference(name) or raise "Could not find section #{name}" depth = section.depth if section.depth < depth end end def self.pdf(text) puts "creating pdf" Puppet::Util.secure_open("/tmp/puppetdoc.txt", "w") do |f| f.puts text end rst2latex = which('rst2latex') || which('rst2latex.py') || raise("Could not find rst2latex") cmd = %{#{rst2latex} /tmp/puppetdoc.txt > /tmp/puppetdoc.tex} Puppet::Util.secure_open("/tmp/puppetdoc.tex","w") do |f| # If we get here without an error, /tmp/puppetdoc.tex isn't a tricky cracker's symlink end output = %x{#{cmd}} unless $CHILD_STATUS == 0 $stderr.puts "rst2latex failed" $stderr.puts output exit(1) end $stderr.puts output # Now convert to pdf Dir.chdir("/tmp") do %x{texi2pdf puppetdoc.tex >/dev/null 2>/dev/null} end end def self.references instance_loader(:reference).loadall loaded_instances(:reference).sort { |a,b| a.to_s <=> b.to_s } end HEADER_LEVELS = [nil, "#", "##", "###", "####", "#####"] attr_accessor :page, :depth, :header, :title, :dynamic attr_writer :doc def doc if defined?(@doc) return "#{@name} - #{@doc}" else return @title end end def dynamic? self.dynamic end def h(name, level) "#{HEADER_LEVELS[level]} #{name}\n\n" end def initialize(name, options = {}, &block) @name = name options.each do |option, value| send(option.to_s + "=", value) end meta_def(:generate, &block) # Now handle the defaults @title ||= "#{@name.to_s.capitalize} Reference" @page ||= @title.gsub(/\s+/, '') @depth ||= 2 @header ||= "" end # Indent every line in the chunk except those which begin with '..'. def indent(text, tab) text.gsub(/(^|\A)/, tab).gsub(/^ +\.\./, "..") end def option(name, value) ":#{name.to_s.capitalize}: #{value}\n" end def paramwrap(name, text, options = {}) options[:level] ||= 5 #str = "#{name} : " str = h(name, options[:level]) str += "- **namevar**\n\n" if options[:namevar] str += text #str += text.gsub(/\n/, "\n ") str += "\n\n" end def text puts output end def to_markdown(withcontents = true) # First the header text = h(@title, 1) - text += "\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on #{Time.now.to_s})*\n\n" + text << "\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on #{Time.now.to_s})*\n\n" - text += @header + text << @header - text += generate + text << generate - text += self.class.footer if withcontents + text << self.class.footer if withcontents text end end