summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/pi223
-rw-r--r--lib/puppet/application/pi.rb216
-rwxr-xr-xspec/unit/application/pi.rb84
3 files changed, 303 insertions, 220 deletions
diff --git a/bin/pi b/bin/pi
index 0b700a2d0..6ac759ed3 100755
--- a/bin/pi
+++ b/bin/pi
@@ -11,224 +11,7 @@
# (2) The command line options are kinda screwy; unclear how best to
# present the various pieces of info to user
-require 'puppet'
-require 'optparse'
+require 'puppet/application'
+require 'puppet/application/pi'
-class Formatter
-
- def initialize(width)
- @width = width
- end
-
- def wrap(txt, opts)
- return "" unless txt && !txt.empty?
- work = (opts[:scrub] ? scrub(txt) : txt)
- indent = (opts[:indent] ? opts[:indent] : 0)
- textLen = @width - indent
- patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
- prefix = " " * indent
-
- res = []
-
- while work.length > textLen
- if work =~ patt
- res << $1
- work.slice!(0, $&.length)
- else
- res << work.slice!(0, textLen)
- end
- end
- res << work if work.length.nonzero?
- return prefix + res.join("\n" + prefix)
- end
-
- def header(txt, sep = "-")
- "\n#{txt}\n" + sep * txt.size
- end
-
- private
-
- def scrub(text)
- # 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
- return text.gsub(/^#{indent}/,'')
- else
- return text
- end
- end
-
-end
-
-class TypeDoc
-
- def initialize
- @format = Formatter.new(76)
- @types = {}
- Puppet::Type.loadall
- Puppet::Type.eachtype { |type|
- next if type.name == :component
- @types[type.name] = type
- }
- end
-
- def list_types
- puts "These are the types known to puppet:\n"
- @types.keys.sort { |a, b|
- a.to_s <=> b.to_s
- }.each do |name|
- type = @types[name]
- s = type.doc.gsub(/\s+/, " ")
- n = s.index(".")
- if n.nil?
- s = ".. no documentation .."
- elsif n > 45
- s = s[0, 45] + " ..."
- else
- s = s[0, n]
- end
- printf "%-15s - %s\n", name, s
- end
- end
-
- def format_type(name, opts)
- name = name.to_sym
- unless @types.has_key?(name)
- puts "Unknown type #{name}"
- return
- end
- type = @types[name]
- puts @format.header(name.to_s, "=")
- puts @format.wrap(type.doc, :indent => 0, :scrub => true) + "\n\n"
-
- puts @format.header("Parameters")
- if opts[:parameters]
- format_attrs(type, [:property, :param])
- else
- list_attrs(type, [:property, :param])
- end
-
- if opts[:metaparams]
- puts @format.header("Meta Parameters")
- if opts[:parameters]
- format_attrs(type, [:meta])
- else
- list_attrs(type, [:meta])
- end
- end
-
- if type.providers.size > 0
- puts @format.header("Providers")
- if opts[:providers]
- format_providers(type)
- else
- list_providers(type)
- end
- end
- end
-
- # List details about attributes
- def format_attrs(type, attrs)
- docs = {}
- type.eachattr do |obj, kind|
- if attrs.include?(kind) && obj.name != :provider
- docs[obj.name] = obj.doc
- end
- end
-
- docs.sort { |a,b|
- a[0].to_s <=> b[0].to_s
- }.each { |name, doc|
- print "\n- **%s**" % name
- if type.namevar == name and name != :name
- puts " (*namevar*)"
- else
- puts ""
- end
- puts @format.wrap(doc, :indent => 4, :scrub => true)
- }
- end
-
- # List the names of attributes
- def list_attrs(type, attrs)
- params = []
- type.eachattr do |obj, kind|
- if attrs.include?(kind) && obj.name != :provider
- params << obj.name.to_s
- end
- end
- puts @format.wrap(params.sort.join(", "), :indent => 4)
- end
-
- def format_providers(type)
- type.providers.sort { |a,b|
- a.to_s <=> b.to_s
- }.each { |prov|
- puts "\n- **%s**" % prov
- puts @format.wrap(type.provider(prov).doc,
- :indent => 4, :scrub => true)
- }
- end
-
- def list_providers(type)
- list = type.providers.sort { |a,b|
- a.to_s <=> b.to_s
- }.join(", ")
- puts @format.wrap(list, :indent => 4)
- end
-
-end
-
-def process_args
- result = {
- :list => false,
- :providers => false,
- :parameters => true,
- :metaparams => false
- }
- opts = OptionParser.new("#{$0} [options] [type]")
- opts.separator(" Print documentation for puppet types and their parameters")
- opts.on("-l", "--list", "List all types") do |val|
- result[:list] = true
- end
- opts.on("-p", "--providers",
- "Describe providers in detail") do |val|
- result[:providers] = true
- end
- opts.on("-s", "--short",
- "Only list parameters without detail") do |val|
- result[:parameters] = false
- end
- opts.on("-m", "--meta",
- "Include metaparams") do |val|
- result[:metaparams] = true
- end
- result[:types] = opts.order(ARGV)
- # Check for obviously bogus options
- unless result[:list] || result[:types].size > 0
- $stderr.puts opts
- exit(1)
- end
- if result[:list] && result[:types].size > 0
- $stderr.puts "Warning: ignoring types when listing all types"
- end
-
- return result
-end
-
-opts = process_args
-
-doc = TypeDoc.new
-
-if opts[:list]
- doc.list_types
-else
- opts[:types].each { |name| doc.format_type(name, opts) }
-end
+Puppet::Application[:pi].run \ No newline at end of file
diff --git a/lib/puppet/application/pi.rb b/lib/puppet/application/pi.rb
new file mode 100644
index 000000000..4c73418a8
--- /dev/null
+++ b/lib/puppet/application/pi.rb
@@ -0,0 +1,216 @@
+require 'puppet'
+require 'puppet/application'
+
+class Formatter
+
+ def initialize(width)
+ @width = width
+ end
+
+ def wrap(txt, opts)
+ return "" unless txt && !txt.empty?
+ work = (opts[:scrub] ? scrub(txt) : txt)
+ indent = (opts[:indent] ? opts[:indent] : 0)
+ textLen = @width - indent
+ patt = Regexp.new("^(.{0,#{textLen}})[ \n]")
+ prefix = " " * indent
+
+ res = []
+
+ while work.length > textLen
+ if work =~ patt
+ res << $1
+ work.slice!(0, $&.length)
+ else
+ res << work.slice!(0, textLen)
+ end
+ end
+ res << work if work.length.nonzero?
+ return prefix + res.join("\n" + prefix)
+ end
+
+ def header(txt, sep = "-")
+ "\n#{txt}\n" + sep * txt.size
+ end
+
+ private
+
+ def scrub(text)
+ # 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
+ return text.gsub(/^#{indent}/,'')
+ else
+ return text
+ end
+ end
+
+end
+
+class TypeDoc
+
+ def initialize
+ @format = Formatter.new(76)
+ @types = {}
+ Puppet::Type.loadall
+ Puppet::Type.eachtype { |type|
+ next if type.name == :component
+ @types[type.name] = type
+ }
+ end
+
+ def list_types
+ puts "These are the types known to puppet:\n"
+ @types.keys.sort { |a, b|
+ a.to_s <=> b.to_s
+ }.each do |name|
+ type = @types[name]
+ s = type.doc.gsub(/\s+/, " ")
+ n = s.index(".")
+ if n.nil?
+ s = ".. no documentation .."
+ elsif n > 45
+ s = s[0, 45] + " ..."
+ else
+ s = s[0, n]
+ end
+ printf "%-15s - %s\n", name, s
+ end
+ end
+
+ def format_type(name, opts)
+ name = name.to_sym
+ unless @types.has_key?(name)
+ puts "Unknown type #{name}"
+ return
+ end
+ type = @types[name]
+ puts @format.header(name.to_s, "=")
+ puts @format.wrap(type.doc, :indent => 0, :scrub => true) + "\n\n"
+
+ puts @format.header("Parameters")
+ if opts[:parameters]
+ format_attrs(type, [:property, :param])
+ else
+ list_attrs(type, [:property, :param])
+ end
+
+ if opts[:metaparams]
+ puts @format.header("Meta Parameters")
+ if opts[:parameters]
+ format_attrs(type, [:meta])
+ else
+ list_attrs(type, [:meta])
+ end
+ end
+
+ if type.providers.size > 0
+ puts @format.header("Providers")
+ if opts[:providers]
+ format_providers(type)
+ else
+ list_providers(type)
+ end
+ end
+ end
+
+ # List details about attributes
+ def format_attrs(type, attrs)
+ docs = {}
+ type.eachattr do |obj, kind|
+ if attrs.include?(kind) && obj.name != :provider
+ docs[obj.name] = obj.doc
+ end
+ end
+
+ docs.sort { |a,b|
+ a[0].to_s <=> b[0].to_s
+ }.each { |name, doc|
+ print "\n- **%s**" % name
+ if type.namevar == name and name != :name
+ puts " (*namevar*)"
+ else
+ puts ""
+ end
+ puts @format.wrap(doc, :indent => 4, :scrub => true)
+ }
+ end
+
+ # List the names of attributes
+ def list_attrs(type, attrs)
+ params = []
+ type.eachattr do |obj, kind|
+ if attrs.include?(kind) && obj.name != :provider
+ params << obj.name.to_s
+ end
+ end
+ puts @format.wrap(params.sort.join(", "), :indent => 4)
+ end
+
+ def format_providers(type)
+ type.providers.sort { |a,b|
+ a.to_s <=> b.to_s
+ }.each { |prov|
+ puts "\n- **%s**" % prov
+ puts @format.wrap(type.provider(prov).doc,
+ :indent => 4, :scrub => true)
+ }
+ end
+
+ def list_providers(type)
+ list = type.providers.sort { |a,b|
+ a.to_s <=> b.to_s
+ }.join(", ")
+ puts @format.wrap(list, :indent => 4)
+ end
+
+end
+
+Puppet::Application.new(:pi,"#{$0} [options] [type]") do
+ @opt_parser.separator(" Print documentation for puppet types and their parameters")
+
+ should_not_parse_config
+
+ option("--short", "-s", "Only list parameters without detail") do |arg|
+ options[:parameters] = false
+ end
+
+ option("--providers","-p", "Describe providers in detail")
+ option("--list", "-l", "List all types")
+ option("--meta","-m", "Include metaparams")
+ option("--help","-h") do |v|
+ puts @opt_parser
+ end
+
+ preinit do
+ options[:parameters] = true
+ end
+
+ command(:main) do
+ doc = TypeDoc.new
+
+ if options[:list]
+ doc.list_types
+ else
+ options[:types].each { |name| doc.format_type(name, options) }
+ end
+ end
+
+ setup do
+ options[:types] = ARGV.dup
+ unless options[:list] || options[:types].size > 0
+ handle_help(nil)
+ end
+ if options[:list] && options[:types].size > 0
+ $stderr.puts "Warning: ignoring types when listing all types"
+ end
+ end
+
+end
diff --git a/spec/unit/application/pi.rb b/spec/unit/application/pi.rb
new file mode 100755
index 000000000..84d6a7ff5
--- /dev/null
+++ b/spec/unit/application/pi.rb
@@ -0,0 +1,84 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../spec_helper'
+
+require 'puppet/application/pi'
+
+describe "pi" do
+ before :each do
+ @pi = Puppet::Application[:pi]
+ end
+
+ it "should ask Puppet::Application to not parse Puppet configuration file" do
+ @pi.should_parse_config?.should be_false
+ end
+
+ it "should declare a main command" do
+ @pi.should respond_to(:main)
+ end
+
+ it "should declare a preinit block" do
+ @pi.should respond_to(:run_preinit)
+ end
+
+ [:providers,:list,:meta].each do |option|
+ it "should declare handle_#{option} method" do
+ @pi.should respond_to("handle_#{option}".to_sym)
+ end
+
+ it "should store argument value when calling handle_#{option}" do
+ @pi.options.expects(:[]=).with("#{option}".to_sym, 'arg')
+ @pi.send("handle_#{option}".to_sym, 'arg')
+ end
+ end
+
+
+ describe "in preinit" do
+ it "should set options[:parameteers] to true" do
+ @pi.run_preinit
+
+ @pi.options[:parameters].should be_true
+ end
+ end
+
+ describe "when handling parameters" do
+ it "should set options[:parameters] to false" do
+ @pi.handle_short(nil)
+
+ @pi.options[:parameters].should be_false
+ end
+ end
+
+ describe "during setup" do
+ it "should collect ARGV in options[:types]" do
+ ARGV.stubs(:dup).returns(['1','2'])
+ @pi.run_setup
+
+ @pi.options[:types].should == ['1','2']
+ end
+ end
+
+ describe "when running" do
+
+ before :each do
+ @typedoc = stub 'type_doc'
+ TypeDoc.stubs(:new).returns(@typedoc)
+ end
+
+ it "should call list_types if options list is set" do
+ @pi.options[:list] = true
+
+ @typedoc.expects(:list_types)
+
+ @pi.run_command
+ end
+
+ it "should call format_type for each given types" do
+ @pi.options[:list] = false
+ @pi.options[:types] = ['type']
+
+ @typedoc.expects(:format_type).with('type', @pi.options)
+ @pi.run_command
+ end
+ end
+end