Ok, this one was missing from the previous patchset, I was about to complain :-)
On Tue, 2009-04-14 at 23:30 -0500, Luke Kanies wrote: > Signed-off-by: Luke Kanies <[email protected]> > --- > lib/puppet/application.rb | 302 > +++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 302 insertions(+), 0 deletions(-) > create mode 100644 lib/puppet/application.rb > > diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb > new file mode 100644 > index 0000000..88ad9d4 > --- /dev/null > +++ b/lib/puppet/application.rb > @@ -0,0 +1,302 @@ > +require 'puppet' > +require 'optparse' > + > +# This class handles all the aspects of a Puppet application/executable > +# * setting up options > +# * setting up logs > +# * choosing what to run > +# > +# === 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. > +# > +# The executable uses the application object like this: > +# Puppet::Application[:example].run > +# > +# > +# Puppet::Application.new(:example) do > +# > +# preinit do > +# # perform some pre initialization > +# @all = false > +# end > +# > +# # dispatch is called to know to what command to call > +# dispatch do > +# ARGV.shift > +# end > +# > +# option("--arg ARGUMENT") do |v| > +# @args << v > +# end > +# > +# option("--debug", "-d") do |v| > +# @debug = v > +# end > +# > +# option("--all", "-a:) do |v| > +# @all = v > +# end > +# > +# unknown do |opt,arg| > +# # last chance to manage an option > +# ... > +# # let's say to the framework we finally handle this option > +# true > +# end > +# > +# command(:read) do > +# # read action > +# end > +# > +# command(:write) do > +# # writeaction > +# end > +# > +# end > +# > +# === Preinit > +# The preinit block is the first code to be called in your application, > before option parsing, > +# setup or command execution. > +# > +# === Options > +# Puppet::Application uses +OptionParser+ to manage the application options. > +# Options are defined with the +option+ method to which are passed various > +# arguments, including the long option, the short option, a description... > +# Refer to +OptionParser+ documentation for the exact format. > +# * If the option method is given a block, this one will be called whenever > +# the option is encountered in the command-line argument. > +# * If the option method has no block, a default functionnality will be > used, that > +# stores the argument (or true/false if the option doesn't require an > argument) in > +# the global (to the application) options array. > +# * If a given option was not defined by a the +option+ method, but it > exists as a Puppet settings: > +# * if +unknown+ was used with a block, it will be called with the option > name and argument > +# * if +unknown+ wasn't used, then the option/argument is handed to > Puppet.settings.handlearg for > +# a default behavior > +# > +# --help is managed directly by the Puppet::Application class, but can be > overriden. > +# > +# === Setup > +# Applications can use the setup block to perform any initialization. > +# The defaul +setup+ behaviour is to: read Puppet configuration and manage > log level and destination > +# > +# === What and how to run > +# If the +dispatch+ block is defined it is called. This block should return > the name of the registered command > +# to be run. > +# If it doesn't exist, it defaults to execute the +main+ command if defined. > +# > +class Puppet::Application > + include Puppet::Util > + > + @@applications = {} > + class << self > + include Puppet::Util > + end > + > + attr_reader :options, :opt_parser > + > + def self.[](name) > + name = symbolize(name) > + @@applications[name] > + end > + > + def should_parse_config > + @parse_config = true > + end > + > + def should_not_parse_config > + @parse_config = false > + end > + > + def should_parse_config? > + unless @parse_config.nil? > + return @parse_config > + end > + @parse_config = true > + end > + > + # used to declare a new command > + def command(name, &block) > + meta_def(symbolize(name), &block) > + end > + > + # used as a catch-all for unknown option > + def unknown(&block) > + meta_def(:handle_unknown, &block) > + end > + > + # 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 > + end > + end > + @opt_parser.on(*options) do |value| > + self.send(symbolize(fname), value) > + 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 > + end > + end > + > + # used to declare code run instead the default setup > + def setup(&block) > + meta_def(:run_setup, &block) > + end > + > + # used to declare code to choose which command to run > + def dispatch(&block) > + meta_def(:get_command, &block) > + end > + > + # used to execute code before running anything else > + def preinit(&block) > + meta_def(:run_preinit, &block) > + 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 > + end > + > + # initialize default application behaviour > + def init_default > + setup do > + default_setup > + end > + > + dispatch do > + :main > + end > + > + # empty by default > + preinit do > + end > + > + option("--version", "-V") do |arg| > + puts "%s" % Puppet.version > + exit > + end > + > + option("--help", "-h") do |v| > + help > + end > + end > + > + # This is the main application entry point > + def run > + run_preinit > + parse_options > + Puppet.settings.parse if should_parse_config? > + run_setup > + run_command > + end > + > + def main > + raise NotImplementedError, "No valid command or main" > + end > + > + def run_command > + if command = get_command() and respond_to?(command) > + send(command) > + else > + main > + end > + end > + > + def default_setup > + # Handle the logging settings > + if options[:debug] or options[:verbose] > + Puppet::Util::Log.newdestination(:console) > + if options[:debug] > + Puppet::Util::Log.level = :debug > + else > + Puppet::Util::Log.level = :info > + end > + end > + > + unless options[:setdest] > + Puppet::Util::Log.newdestination(:syslog) > + end > + end > + > + def parse_options > + # get all puppet options > + optparse_opt = [] > + optparse_opt = Puppet.settings.optparse_addargs(optparse_opt) > + > + # convert them to OptionParser format > + optparse_opt.each do |option| > + @opt_parser.on(*option) do |arg| > + handlearg(option[0], arg) > + end > + end > + > + # scan command line argument > + begin > + @opt_parser.parse! > + rescue OptionParser::ParseError => detail > + $stderr.puts detail > + $stderr.puts "Try '#{$0} --help'" > + exit(1) > + end > + end > + > + def handlearg(opt, arg) > + # rewrite --[no-]option to --no-option if that's what was given > + if opt =~ /\[no-\]/ and !arg > + opt = opt.gsub(/\[no-\]/,'no-') > + end > + # otherwise remove the [no-] prefix to not confuse everybody > + opt = opt.gsub(/\[no-\]/, '') > + unless respond_to?(:handle_unknown) and send(:handle_unknown, opt, > arg) > + # Puppet.settings.handlearg doesn't handle direct true/false :-) > + if arg.is_a?(FalseClass) > + arg = "false" > + elsif arg.is_a?(TrueClass) > + arg = "true" > + end > + Puppet.settings.handlearg(opt, arg) > + end > + end > + > + # this is used for testing > + def self.exit(code) > + exit(code) > + end > + > + def help > + if Puppet.features.usage? > + ::RDoc::usage && exit > + else > + puts "No help available unless you have RDoc::usage installed" > + exit > + end > + end > + > +end -- Brice Figureau My Blog: http://www.masterzen.fr/ --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en -~----------~----~----~----~------~----~------~--~---
