summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJesse Wolfe <jes5199@gmail.com>2010-04-30 16:05:43 -0700
committertest branch <puppet-dev@googlegroups.com>2010-02-17 06:50:53 -0800
commitd038a1d3ddffdf1366c78fe31118e9f15c1c6ed1 (patch)
tree6ff89deef467aa58b8b50ea06200b5d2f2dc97ac /lib
parent7656ba73ddfd883b36a01c81147ae69e80773bce (diff)
downloadpuppet-d038a1d3ddffdf1366c78fe31118e9f15c1c6ed1.tar.gz
puppet-d038a1d3ddffdf1366c78fe31118e9f15c1c6ed1.tar.xz
puppet-d038a1d3ddffdf1366c78fe31118e9f15c1c6ed1.zip
Refactor #3706 Reify eigenclasses of Applications
The Puppet::Application DSL is complicated by the fact that it operates on eigenclasses of instances of Puppet::Application, rather than subclassing it. This patch reifies the eigenclasses as subclasses of Puppet::Application. Signed-off-by: Jesse Wolfe <jes5199@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/puppet/application.rb196
-rw-r--r--lib/puppet/application/agent.rb20
-rw-r--r--lib/puppet/application/apply.rb18
-rw-r--r--lib/puppet/application/cert.rb6
-rw-r--r--lib/puppet/application/describe.rb9
-rw-r--r--lib/puppet/application/doc.rb22
-rw-r--r--lib/puppet/application/filebucket.rb20
-rw-r--r--lib/puppet/application/kick.rb15
-rw-r--r--lib/puppet/application/master.rb20
-rw-r--r--lib/puppet/application/queue.rb11
-rw-r--r--lib/puppet/application/resource.rb8
11 files changed, 156 insertions, 189 deletions
diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb
index 7b404a906..49a146ffe 100644
--- a/lib/puppet/application.rb
+++ b/lib/puppet/application.rb
@@ -8,26 +8,28 @@ require 'optparse'
# * representing execution status
#
# === Usage
-# The application is a Puppet::Application object that register itself in the list
-# of available application. Each application needs a +name+ and a getopt +options+
-# description array.
+# An application is a subclass of Puppet::Application.
#
-# The executable uses the application object like this:
+# For legacy compatibility,
# Puppet::Application[:example].run
+# is equivalent to
+# Puppet::Application::Example.new.run
#
#
-# Puppet::Application.new(:example) do
+# class Puppet::Application::Example << Puppet::Application
#
-# preinit do
+# def preinit
# # perform some pre initialization
# @all = false
# end
#
-# # dispatch is called to know to what command to call
-# dispatch do
-# Puppet::Util::CommandLine.args.shift
+# # run_command is called to actually run the specified command
+# def run_command
+# send Puppet::Util::CommandLine.args.shift
# end
#
+# # option uses metaprogramming to create a method
+# # and also tells the option parser how to invoke that method
# option("--arg ARGUMENT") do |v|
# @args << v
# end
@@ -40,18 +42,18 @@ require 'optparse'
# @all = v
# end
#
-# unknown do |opt,arg|
+# def handle_unknown(opt,arg)
# # last chance to manage an option
# ...
# # let's say to the framework we finally handle this option
# true
# end
#
-# command(:read) do
+# def read
# # read action
# end
#
-# command(:write) do
+# def write
# # writeaction
# end
#
@@ -117,9 +119,6 @@ class Puppet::Application
BINDIRS = %w{sbin bin}.map{|dir| File.expand_path(File.dirname(__FILE__)) + "/../../#{dir}/*"}.join(" ")
- @@applications = {}
- def self.applications; @@applications end
-
class << self
include Puppet::Util
@@ -172,128 +171,97 @@ class Puppet::Application
Process.kill(:HUP, $$) if restart_requested?
result
end
- end
- attr_reader :options, :opt_parser
+ def should_parse_config
+ @parse_config = true
+ end
- def self.[](name)
- name = symbolize(name)
- @@applications[name]
- end
+ def should_not_parse_config
+ @parse_config = false
+ end
- def should_parse_config
- @parse_config = true
- end
+ def should_parse_config?
+ if ! defined? @parse_config
+ @parse_config = true
+ end
+ return @parse_config
+ end
- def should_not_parse_config
- @parse_config = false
- end
+ # used to declare code that handle an option
+ def option(*options, &block)
+ long = options.find { |opt| opt =~ /^--/ }.gsub(/^--(?:\[no-\])?([^ =]+).*$/, '\1' ).gsub('-','_')
+ fname = symbolize("handle_#{long}")
+ if (block_given?)
+ define_method(fname, &block)
+ else
+ define_method(fname) do |value|
+ self.options["#{long}".to_sym] = value
+ end
+ end
+ @opt_parser_commands ||= []
+ @opt_parser_commands << [options, fname]
+ end
- def should_parse_config?
- unless @parse_config.nil?
- return @parse_config
+ def banner(banner = nil)
+ @banner = banner unless banner.nil?
end
- @parse_config = true
- end
- # used to declare a new command
- def command(name, &block)
- meta_def(symbolize(name), &block)
- end
+ def new_option_parser( target )
+ @banner ||= nil
- # used as a catch-all for unknown option
- def unknown(&block)
- meta_def(:handle_unknown, &block)
- end
+ opt_parser = OptionParser.new(@banner)
- # used to declare code that handle an option
- def option(*options, &block)
- long = options.find { |opt| opt =~ /^--/ }.gsub(/^--(?:\[no-\])?([^ =]+).*$/, '\1' ).gsub('-','_')
- fname = "handle_#{long}"
- if (block_given?)
- meta_def(symbolize(fname), &block)
- else
- meta_def(symbolize(fname)) do |value|
- self.options["#{long}".to_sym] = value
+ @opt_parser_commands ||= []
+ @opt_parser_commands.each do |options, fname|
+ opt_parser.on(*options) do |value|
+ target.send(fname, value)
+ end
end
+ opt_parser
end
- @opt_parser.on(*options) do |value|
- self.send(symbolize(fname), value)
+
+ def find(name)
+ self.const_get(name.to_s.capitalize)
end
- end
- # used to declare accessor in a more natural way in the
- # various applications
- def attr_accessor(*args)
- args.each do |arg|
- meta_def(arg) do
- instance_variable_get("@#{arg}".to_sym)
- end
- meta_def("#{arg}=") do |value|
- instance_variable_set("@#{arg}".to_sym, value)
- end
+ def [](name)
+ find(name).new
end
end
- # used to declare code run instead the default setup
- def setup(&block)
- meta_def(:run_setup, &block)
- end
+ attr_reader :options, :opt_parser
- # used to declare code to choose which command to run
- def dispatch(&block)
- meta_def(:get_command, &block)
+ # Every app responds to --version
+ option("--version", "-V") do |arg|
+ puts "%s" % Puppet.version
+ exit
end
- # used to execute code before running anything else
- def preinit(&block)
- meta_def(:run_preinit, &block)
+ # Every app responds to --help
+ option("--help", "-h") do |v|
+ help
end
- def initialize(name, banner = nil, &block)
- @opt_parser = OptionParser.new(banner)
-
- @name = symbolize(name)
-
- init_default
-
- @options = {}
-
- instance_eval(&block) if block_given?
-
- @@applications[@name] = self
+ def should_parse_config?
+ self.class.should_parse_config?
end
- # initialize default application behaviour
- def init_default
- setup do
- default_setup
- end
-
- dispatch do
- :main
- end
-
- # empty by default
- preinit do
- end
+ # override to execute code before running anything else
+ def preinit
+ end
- option("--version", "-V") do |arg|
- puts "%s" % Puppet.version
- exit
- end
+ def initialize
+ @opt_parser = self.class.new_option_parser( self )
- option("--help", "-h") do |v|
- help
- end
+ @options = {}
end
# This is the main application entry point
def run
- exit_on_fail("initialize") { run_preinit }
+ exit_on_fail("initialize") { preinit }
exit_on_fail("parse options") { parse_options }
exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config?
- exit_on_fail("prepare for execution") { run_setup }
+ exit_on_fail("prepare for execution") { setup }
exit_on_fail("run") { run_command }
end
@@ -302,14 +270,10 @@ class Puppet::Application
end
def run_command
- if command = get_command() and respond_to?(command)
- send(command)
- else
- main
- end
+ main
end
- def default_setup
+ def setup
# Handle the logging settings
if options[:debug] or options[:verbose]
Puppet::Util::Log.newdestination(:console)
@@ -370,10 +334,14 @@ class Puppet::Application
exit(code)
end
+ def name
+ self.class.to_s.sub(/.*::/,"").downcase.to_sym
+ end
+
def help
if Puppet.features.usage?
# RH:FIXME: My goodness, this is ugly.
- ::RDoc.const_set("PuppetSourceFile", @name)
+ ::RDoc.const_set("PuppetSourceFile", name)
def (::RDoc).caller
docfile = `grep -l 'Puppet::Application\\[:#{::RDoc::PuppetSourceFile}\\]' #{BINDIRS}`.chomp
super << "#{docfile}:0"
@@ -384,7 +352,7 @@ class Puppet::Application
exit
end
rescue Errno::ENOENT
- puts "No help available for puppet #@name"
+ puts "No help available for puppet #{name}"
exit
end
diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb
index 985d87dd0..093e5b94d 100644
--- a/lib/puppet/application/agent.rb
+++ b/lib/puppet/application/agent.rb
@@ -5,13 +5,13 @@ require 'puppet/daemon'
require 'puppet/configurer'
require 'puppet/network/client'
-Puppet::Application.new(:agent) do
+class Puppet::Application::Agent < Puppet::Application
should_parse_config
attr_accessor :explicit_waitforcert, :args, :agent, :daemon, :host
- preinit do
+ def preinit
# Do an initial trap, so that cancels don't get a stack trace.
trap(:INT) do
$stderr.puts "Cancelling startup"
@@ -96,13 +96,13 @@ Puppet::Application.new(:agent) do
@args[:Port] = arg
end
- dispatch do
- return :fingerprint if options[:fingerprint]
- return :onetime if options[:onetime]
- return :main
+ def run_command
+ return fingerprint if options[:fingerprint]
+ return onetime if options[:onetime]
+ return main
end
- command(:fingerprint) do
+ def fingerprint
unless cert = host.certificate || host.certificate_request
$stderr.puts "Fingerprint asked but no certificate nor certificate request have yet been issued"
exit(1)
@@ -114,7 +114,7 @@ Puppet::Application.new(:agent) do
Puppet.notice fingerprint
end
- command(:onetime) do
+ def onetime
unless options[:client]
$stderr.puts "onetime is specified but there is no client"
exit(43)
@@ -141,7 +141,7 @@ Puppet::Application.new(:agent) do
end
end
- command(:main) do
+ def main
Puppet.notice "Starting Puppet client version %s" % [Puppet.version]
@daemon.start
@@ -207,7 +207,7 @@ Puppet::Application.new(:agent) do
@daemon.server = server
end
- setup do
+ def setup
setup_test if options[:test]
setup_logs
diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb
index d977cf1d0..88385f0a0 100644
--- a/lib/puppet/application/apply.rb
+++ b/lib/puppet/application/apply.rb
@@ -4,7 +4,7 @@ require 'puppet/configurer'
require 'puppet/network/handler'
require 'puppet/network/client'
-Puppet::Application.new(:apply) do
+class Puppet::Application::Apply < Puppet::Application
should_parse_config
@@ -30,17 +30,17 @@ Puppet::Application.new(:apply) do
end
end
- dispatch do
+ def run_command
if options[:catalog]
- :apply
+ apply
elsif Puppet[:parseonly]
- :parseonly
+ parseonly
else
- :main
+ main
end
end
- command(:apply) do
+ def apply
require 'puppet/configurer'
if options[:catalog] == "-"
@@ -64,7 +64,7 @@ Puppet::Application.new(:apply) do
configurer.run :catalog => catalog
end
- command(:parseonly) do
+ def parseonly
# Set our code or file to use.
if options[:code] or Puppet::Util::CommandLine.args.length == 0
Puppet[:code] = options[:code] || STDIN.read
@@ -80,7 +80,7 @@ Puppet::Application.new(:apply) do
exit 0
end
- command(:main) do
+ def main
# Set our code or file to use.
if options[:code] or Puppet::Util::CommandLine.args.length == 0
Puppet[:code] = options[:code] || STDIN.read
@@ -153,7 +153,7 @@ Puppet::Application.new(:apply) do
end
end
- setup do
+ def setup
if Puppet.settings.print_configs?
exit(Puppet.settings.print_configs ? 0 : 1)
end
diff --git a/lib/puppet/application/cert.rb b/lib/puppet/application/cert.rb
index 7a7784b09..92da03ca7 100644
--- a/lib/puppet/application/cert.rb
+++ b/lib/puppet/application/cert.rb
@@ -2,7 +2,7 @@ require 'puppet'
require 'puppet/application'
require 'puppet/ssl/certificate_authority'
-Puppet::Application.new(:cert) do
+class Puppet::Application::Cert < Puppet::Application
should_parse_config
@@ -40,7 +40,7 @@ Puppet::Application.new(:cert) do
Puppet::Util::Log.level = :info
end
- command(:main) do
+ def main
if @all
hosts = :all
else
@@ -56,7 +56,7 @@ Puppet::Application.new(:cert) do
end
end
- setup do
+ def setup
if Puppet.settings.print_configs?
exit(Puppet.settings.print_configs ? 0 : 1)
end
diff --git a/lib/puppet/application/describe.rb b/lib/puppet/application/describe.rb
index ea4ac162c..45f017a48 100644
--- a/lib/puppet/application/describe.rb
+++ b/lib/puppet/application/describe.rb
@@ -175,7 +175,8 @@ class TypeDoc
end
-Puppet::Application.new(:describe,"#{$0} [options] [type]") do
+class Puppet::Application::Describe < Puppet::Application
+ banner "puppet describe [options] [type]"
should_not_parse_config
@@ -187,11 +188,11 @@ Puppet::Application.new(:describe,"#{$0} [options] [type]") do
option("--list", "-l")
option("--meta","-m")
- preinit do
+ def preinit
options[:parameters] = true
end
- command(:main) do
+ def main
doc = TypeDoc.new
if options[:list]
@@ -201,7 +202,7 @@ Puppet::Application.new(:describe,"#{$0} [options] [type]") do
end
end
- setup do
+ def setup
options[:types] = Puppet::Util::CommandLine.args.dup
unless options[:list] || options[:types].size > 0
handle_help(nil)
diff --git a/lib/puppet/application/doc.rb b/lib/puppet/application/doc.rb
index 0a11d6045..295cd6771 100644
--- a/lib/puppet/application/doc.rb
+++ b/lib/puppet/application/doc.rb
@@ -7,13 +7,13 @@ require 'puppet/util/rdoc'
$tab = " "
Reference = Puppet::Util::Reference
-Puppet::Application.new(:doc) do
+class Puppet::Application::Doc < Puppet::Application
should_not_parse_config
attr_accessor :unknown_args, :manifest
- preinit do
+ def preinit
{:references => [], :mode => :text, :format => :to_rest }.each do |name,value|
options[name] = value
end
@@ -52,17 +52,17 @@ Puppet::Application.new(:doc) do
options[:references] << arg.intern
end
- unknown do |opt, arg|
+ def handle_unknown( opt, arg )
@unknown_args << {:opt => opt, :arg => arg }
true
end
- dispatch do
- return options[:mode] if [:rdoc, :trac, :markdown].include?(options[:mode])
- return :other
+ def run_command
+ return send(options[:mode]) if [:rdoc, :trac, :markdown].include?(options[:mode])
+ return other
end
- command(:rdoc) do
+ def rdoc
exit_code = 0
files = []
unless @manifest
@@ -93,7 +93,7 @@ Puppet::Application.new(:doc) do
exit exit_code
end
- command(:trac) do
+ def trac
options[:references].each do |name|
section = Puppet::Util::Reference.reference(name) or raise "Could not find section %s" % name
unless options[:mode] == :pdf
@@ -102,7 +102,7 @@ Puppet::Application.new(:doc) do
end
end
- command(:markdown) do
+ def markdown
text = ""
with_contents = false
exit_code = 0
@@ -127,7 +127,7 @@ Puppet::Application.new(:doc) do
exit exit_code
end
- command(:other) do
+ def other
text = ""
if options[:references].length > 1
with_contents = false
@@ -165,7 +165,7 @@ Puppet::Application.new(:doc) do
exit exit_code
end
- setup do
+ def setup
# sole manifest documentation
if Puppet::Util::CommandLine.args.size > 0
options[:mode] = :rdoc
diff --git a/lib/puppet/application/filebucket.rb b/lib/puppet/application/filebucket.rb
index cd7c854af..ddc46e394 100644
--- a/lib/puppet/application/filebucket.rb
+++ b/lib/puppet/application/filebucket.rb
@@ -2,7 +2,7 @@ require 'puppet'
require 'puppet/application'
require 'puppet/file_bucket/dipper'
-Puppet::Application.new(:filebucket) do
+class Puppet::Application::Filebucket < Puppet::Application
should_not_parse_config
@@ -12,22 +12,22 @@ Puppet::Application.new(:filebucket) do
option("--remote","-r")
option("--verbose","-v")
- class << self
- attr :args
- end
+ attr :args
- dispatch do
+ def run_command
@args = Puppet::Util::CommandLine.args
- args.shift
+ command = args.shift
+ return send(command) if %w[get backup restore].include? command
+ help
end
- command(:get) do
+ def get
md5 = args.shift
out = @client.getfile(md5)
print out
end
- command(:backup) do
+ def backup
args.each do |file|
unless FileTest.exists?(file)
$stderr.puts "%s: no such file" % file
@@ -42,13 +42,13 @@ Puppet::Application.new(:filebucket) do
end
end
- command(:restore) do
+ def restore
file = args.shift
md5 = args.shift
@client.restore(file, md5)
end
- setup do
+ def setup
Puppet::Log.newdestination(:console)
@client = nil
diff --git a/lib/puppet/application/kick.rb b/lib/puppet/application/kick.rb
index 7b4993bb4..37d3e533f 100644
--- a/lib/puppet/application/kick.rb
+++ b/lib/puppet/application/kick.rb
@@ -4,7 +4,7 @@ require 'puppet/application'
Puppet.warning "RubyGems not installed" unless Puppet.features.rubygems?
Puppet.warning "Failed to load ruby LDAP library. LDAP functionality will not be available" unless Puppet.features.ldap?
-Puppet::Application.new(:kick) do
+class Puppet::Application::Kick < Puppet::Application
should_not_parse_config
@@ -41,17 +41,16 @@ Puppet::Application.new(:kick) do
end
end
-
- dispatch do
- options[:test] ? :test : :main
+ def run_command
+ options[:test] ? test : main
end
- command(:test) do
+ def test
puts "Skipping execution in test mode"
exit(0)
end
- command(:main) do
+ def main
require 'puppet/network/client'
require 'puppet/util/ldap/connection'
@@ -147,7 +146,7 @@ Puppet::Application.new(:kick) do
end
end
- preinit do
+ def preinit
[:INT, :TERM].each do |signal|
trap(signal) do
$stderr.puts "Cancelling"
@@ -165,7 +164,7 @@ Puppet::Application.new(:kick) do
@tags = []
end
- setup do
+ def setup
if options[:debug]
Puppet::Util::Log.level = :debug
else
diff --git a/lib/puppet/application/master.rb b/lib/puppet/application/master.rb
index 8f1c0cd95..2433780c2 100644
--- a/lib/puppet/application/master.rb
+++ b/lib/puppet/application/master.rb
@@ -4,7 +4,7 @@ require 'puppet/daemon'
require 'puppet/network/server'
require 'puppet/network/http/rack' if Puppet.features.rack?
-Puppet::Application.new(:master) do
+class Puppet::Application::Master < Puppet::Application
should_parse_config
@@ -30,7 +30,7 @@ Puppet::Application.new(:master) do
end
end
- preinit do
+ def preinit
trap(:INT) do
$stderr.puts "Cancelling startup"
exit(0)
@@ -41,17 +41,17 @@ Puppet::Application.new(:master) do
@daemon.argv = ARGV.dup
end
- dispatch do
+ def run_command
if options[:node]
- :compile
+ compile
elsif Puppet[:parseonly]
- :parseonly
+ parseonly
else
- :main
+ main
end
end
- command(:compile) do
+ def compile
Puppet::Util::Log.newdestination :console
raise ArgumentError, "Cannot render compiled catalogs without pson support" unless Puppet.features.pson?
begin
@@ -67,7 +67,7 @@ Puppet::Application.new(:master) do
exit(0)
end
- command(:parseonly) do
+ def parseonly
begin
Puppet::Resource::TypeCollection.new(Puppet[:environment]).perform_initial_import
rescue => detail
@@ -77,7 +77,7 @@ Puppet::Application.new(:master) do
exit(0)
end
- command(:main) do
+ def main
require 'etc'
require 'puppet/file_serving/content'
require 'puppet/file_serving/metadata'
@@ -124,7 +124,7 @@ Puppet::Application.new(:master) do
end
end
- setup do
+ def setup
# Handle the logging settings.
if options[:debug] or options[:verbose]
if options[:debug]
diff --git a/lib/puppet/application/queue.rb b/lib/puppet/application/queue.rb
index 13fb3e107..4b3aa57b5 100644
--- a/lib/puppet/application/queue.rb
+++ b/lib/puppet/application/queue.rb
@@ -5,13 +5,12 @@ require 'puppet/resource/catalog'
require 'puppet/indirector/catalog/queue'
require 'puppet/util'
-Puppet::Application.new(:queue) do
- extend Puppet::Util
+class Puppet::Application::Queue < Puppet::Application
should_parse_config
attr_accessor :daemon
- preinit do
+ def preinit
@daemon = Puppet::Daemon.new
@daemon.argv = ARGV.dup
Puppet::Util::Log.newdestination(:console)
@@ -41,13 +40,13 @@ Puppet::Application.new(:queue) do
option("--debug","-d")
option("--verbose","-v")
- command(:main) do
+ def main
Puppet.notice "Starting puppetqd %s" % Puppet.version
Puppet::Resource::Catalog::Queue.subscribe do |catalog|
# Once you have a Puppet::Resource::Catalog instance, calling save() on it should suffice
# to put it through to the database via its active_record indirector (which is determined
# by the terminus_class = :active_record setting above)
- benchmark(:notice, "Processing queued catalog for %s" % catalog.name) do
+ Puppet::Util.benchmark(:notice, "Processing queued catalog for %s" % catalog.name) do
begin
catalog.save
rescue => detail
@@ -72,7 +71,7 @@ Puppet::Application.new(:queue) do
end
end
- setup do
+ def setup
unless Puppet.features.stomp?
raise ArgumentError, "Could not load the 'stomp' library, which must be present for queueing to work. You must install the required library."
end
diff --git a/lib/puppet/application/resource.rb b/lib/puppet/application/resource.rb
index 78aed95c5..52320e7a1 100644
--- a/lib/puppet/application/resource.rb
+++ b/lib/puppet/application/resource.rb
@@ -2,13 +2,13 @@ require 'puppet'
require 'puppet/application'
require 'facter'
-Puppet::Application.new(:resource) do
+class Puppet::Application::Resource < Puppet::Application
should_not_parse_config
attr_accessor :host, :extra_params
- preinit do
+ def preinit
@extra_params = []
@host = nil
Facter.loadfacts
@@ -37,7 +37,7 @@ Puppet::Application.new(:resource) do
@extra_params << arg.to_sym
end
- command(:main) do
+ def main
args = Puppet::Util::CommandLine.args
type = args.shift or raise "You must specify the type to display"
typeobj = Puppet::Type.type(type) or raise "Could not find type #{type}"
@@ -109,7 +109,7 @@ Puppet::Application.new(:resource) do
end
end
- setup do
+ def setup
Puppet::Util::Log.newdestination(:console)
# Now parse the config