diff --git a/lib/puppet/reference/configuration.rb b/lib/puppet/reference/configuration.rb index c17151e7d..c1e225367 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 << markdown_header(header, 3) # 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/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" unless val == "" str << "- *Default*: #{val}\n" end str << "\n" end return str end config.header = < 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 << markdown_header(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 0e77e484f..576b00bcb 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) end ret << "\n" count = 1 # Produce output for each type. types.each do |type| features = type.features 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" 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" else 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" when :false details << " - Got #{values} false tests that should have been true\n" when :feature 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 << markdown_header(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) notes.each do |note| ret << note + "\n" end ret << "\n" end 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 635d84249..f620dfc64 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 << h(name, 3) + str << markdown_header(name, 3) str << scrub(type.doc) + "\n\n" # Handle the feature docs. if featuredocs = type.featuredocs - str << h("Features", 4) + str << markdown_header("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 << markdown_header("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 << "\n" } str end diff --git a/lib/puppet/util/reference.rb b/lib/puppet/util/reference.rb index 03523843f..597047002 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) + def markdown_header(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 = markdown_header(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 = markdown_header(@title, 1) text << "\n\n**This page is autogenerated; any changes will get overwritten** *(last generated on #{Time.now.to_s})*\n\n" text << @header text << generate text << self.class.footer if withcontents text end end