Class: Puppet::Application
Overview
This class handles all the aspects of a Puppet application/executable
-
setting up options
-
setting up logs
-
choosing what to run
-
representing execution status
Usage
An application is a subclass of Puppet::Application.
For legacy compatibility,
Puppet::Application[:example].run
is equivalent to
Puppet::Application::Example.new.run
class Puppet::Application::Example < Puppet::Application
def preinit
# perform some pre initialization
@all = false
end
# run_command is called to actually run the specified command
def run_command
send Puppet::Util::CommandLine.new.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
option("--debug", "-d") do |v|
@debug = v
end
option("--all", "-a:) do |v|
@all = v
end
def handle_unknown(opt,arg)
# last chance to manage an option
...
# let's say to the framework we finally handle this option
true
end
def read
# read action
end
def write
# 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 functionality 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 overridden.
Setup
Applications can use the setup block to perform any initialization. The default 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.
Execution state
The class attributes/methods of Puppet::Application serve as a global place to set and query the execution status of the application: stopping, restarting, etc. The setting of the application status does not directly affect its running status; it’s assumed that the various components within the application will consult these settings appropriately and affect their own processing accordingly. Control operations (signal handlers and the like) should set the status appropriately to indicate to the overall system that it’s the process of stopping or restarting (or just running as usual).
So, if something in your application needs to stop the process, for some reason, you might consider:
def stop_me!
# indicate that we're stopping
Puppet::Application.stop!
# ...do stuff...
end
And, if you have some component that involves a long-running process, you might want to consider:
def my_long_process(giant_list_to_munge)
giant_list_to_munge.collect do |member|
# bail if we're stopping
return if Puppet::Application.stop_requested?
process_member(member)
end
end
Direct Known Subclasses
Agent, Apply, Cert, Describe, Device, Doc, FaceBase, Filebucket, Lookup, Resource, Script, Ssl, UploadFacts, ModuleTool::Applications::Installer, ModuleTool::Applications::Searcher, ModuleTool::Applications::Unpacker, ModuleTool::Applications::Upgrader
Defined Under Namespace
Classes: Agent, Apply, Catalog, Cert, CommandLineArgs, Config, Describe, Device, Doc, Epp, FaceBase, Facts, Filebucket, Generate, Help, IndirectionBase, Key, Lookup, Man, Module, Node, Parser, Plugin, Report, Resource, Script, Ssl, Status, UploadFacts
Constant Summary collapse
- DOCPATTERN =
::File.(::File.dirname(__FILE__) + "/util/command_line/*" )
Constants included from Util
Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE, Util::RFC_3986_URI_REGEX
Constants included from Util::POSIX
Util::POSIX::LOCALE_ENV_VARS, Util::POSIX::USER_ENV_VARS
Constants included from Util::SymbolicFileMode
Util::SymbolicFileMode::SetGIDBit, Util::SymbolicFileMode::SetUIDBit, Util::SymbolicFileMode::StickyBit, Util::SymbolicFileMode::SymbolicMode, Util::SymbolicFileMode::SymbolicSpecialToBit
Class Attribute Summary collapse
-
.run_status ⇒ Object
Returns the value of attribute run_status.
Instance Attribute Summary collapse
-
#command_line ⇒ Object
readonly
Returns the value of attribute command_line.
-
#options ⇒ Object
readonly
Returns the value of attribute options.
Class Method Summary collapse
- .[](name) ⇒ Object
-
.available_application_names ⇒ Array<String>
The names of available applications.
- .banner(banner = nil) ⇒ Object
- .clear! ⇒ Object
-
.clear? ⇒ Boolean
Indicates that Puppet::Application believes that it’s in usual running run_mode (no stop/restart request currently active).
-
.clear_everything_for_tests ⇒ Object
This is for testing only.
-
.controlled_run(&block) ⇒ Object
Only executes the given block if the run status of Puppet::Application is clear (no restarts, stops, etc. requested).
-
.environment_mode(mode_name) ⇒ Object
Sets environment_mode name.
-
.exit(code) ⇒ Object
this is used for testing.
-
.find(application_name) ⇒ Class
Finds the class for a given application and loads the class.
-
.get_environment_mode ⇒ Object
Gets environment_mode name.
-
.interrupted? ⇒ Boolean
Indicates that one of stop! or start! was invoked on Puppet::Application, and some kind of process shutdown/short-circuit may be necessary.
-
.option(*options, &block) ⇒ Object
used to declare code that handle an option.
- .option_parser_commands ⇒ Object
- .restart! ⇒ Object
-
.restart_requested? ⇒ Boolean
Indicates that Puppet::Application.restart! has been invoked and components should do what is necessary to facilitate a restart.
-
.run_mode(mode_name = nil) ⇒ Object
Sets or gets the run_mode name.
- .stop! ⇒ Object
-
.stop_requested? ⇒ Boolean
Indicates that Puppet::Application.stop! has been invoked and components should do what is necessary for a clean stop.
-
.try_load_class(class_name) ⇒ Class
Given the fully qualified name of a class, attempt to get the class instance.
Instance Method Summary collapse
- #app_defaults ⇒ Object
- #configure_indirector_routes ⇒ Object
-
#deprecate ⇒ Object
call in setup of subclass to deprecate an application.
- #deprecated? ⇒ Boolean
- #handle_logdest_arg(arg) ⇒ Object
- #handlearg(opt, val) ⇒ Object
- #help ⇒ Object
-
#initialize(command_line = Puppet::Util::CommandLine.new) ⇒ Application
constructor
A new instance of Application.
- #initialize_app_defaults ⇒ Object
-
#log_runtime_environment(extra_info = nil) ⇒ void
Output basic information about the runtime environment for debugging purposes.
- #main ⇒ Object
- #name ⇒ Object
- #parse_options ⇒ Object
-
#preinit ⇒ Object
override to execute code before running anything else.
-
#run ⇒ void
Execute the application.
- #run_command ⇒ Object
- #set_log_level(opts = nil) ⇒ Object
- #setup ⇒ Object
- #setup_logs ⇒ Object
-
#summary ⇒ Object
The description used in top level ‘puppet help` output If left empty in implementations, we will attempt to extract the summary from the help text itself.
Methods included from Util
absolute_path?, benchmark, chuser, clear_environment, default_env, deterministic_rand, deterministic_rand_int, exit_on_fail, get_env, get_environment, logmethods, merge_environment, path_to_uri, pretty_backtrace, replace_file, safe_posix_fork, set_env, symbolizehash, thinmark, uri_encode, uri_query_encode, uri_to_path, which, withenv, withumask
Methods included from Util::POSIX
#get_posix_field, #gid, groups_of, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid
Methods included from Util::SymbolicFileMode
#normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?
Constructor Details
#initialize(command_line = Puppet::Util::CommandLine.new) ⇒ Application
Returns a new instance of Application.
344 345 346 347 |
# File 'lib/puppet/application.rb', line 344 def initialize(command_line = Puppet::Util::CommandLine.new) @command_line = CommandLineArgs.new(command_line.subcommand_name, command_line.args.dup) @options = {} end |
Class Attribute Details
.run_status ⇒ Object
Returns the value of attribute run_status.
134 135 136 |
# File 'lib/puppet/application.rb', line 134 def run_status @run_status end |
Instance Attribute Details
#command_line ⇒ Object (readonly)
Returns the value of attribute command_line.
314 315 316 |
# File 'lib/puppet/application.rb', line 314 def command_line @command_line end |
#options ⇒ Object (readonly)
Returns the value of attribute options.
314 315 316 |
# File 'lib/puppet/application.rb', line 314 def @options end |
Class Method Details
.[](name) ⇒ Object
273 274 275 |
# File 'lib/puppet/application.rb', line 273 def [](name) find(name).new end |
.available_application_names ⇒ Array<String>
Returns the names of available applications.
211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/puppet/application.rb', line 211 def available_application_names # Use our configured environment to load the application, as it may # be in a module we installed locally, otherwise fallback to our # current environment (*root*). Once we load the application the # current environment will change from *root* to the application # specific environment. environment = Puppet.lookup(:environments).get(Puppet[:environment]) || Puppet.lookup(:current_environment) @loader.files_to_load(environment).map do |fn| ::File.basename(fn, '.rb') end.uniq end |
.banner(banner = nil) ⇒ Object
198 199 200 |
# File 'lib/puppet/application.rb', line 198 def ( = nil) @banner ||= end |
.clear! ⇒ Object
136 137 138 |
# File 'lib/puppet/application.rb', line 136 def clear! self.run_status = nil end |
.clear? ⇒ Boolean
Indicates that Puppet::Application believes that it’s in usual running run_mode (no stop/restart request currently active).
168 169 170 |
# File 'lib/puppet/application.rb', line 168 def clear? run_status.nil? end |
.clear_everything_for_tests ⇒ Object
This is for testing only
309 310 311 |
# File 'lib/puppet/application.rb', line 309 def clear_everything_for_tests @run_mode = @banner = @run_status = @option_parser_commands = nil end |
.controlled_run(&block) ⇒ Object
Only executes the given block if the run status of Puppet::Application is clear (no restarts, stops, etc. requested). Upon block execution, checks the run status again; if a restart has been requested during the block’s execution, then controlled_run will send a new HUP signal to the current process. Thus, long-running background processes can potentially finish their work before a restart.
177 178 179 180 181 182 |
# File 'lib/puppet/application.rb', line 177 def controlled_run(&block) return unless clear? result = block.call Process.kill(:HUP, $PID) if restart_requested? result end |
.environment_mode(mode_name) ⇒ Object
Sets environment_mode name
297 298 299 300 |
# File 'lib/puppet/application.rb', line 297 def environment_mode(mode_name) raise Puppet::Error, _("Invalid environment mode '%{mode_name}'") % { mode_name: mode_name } unless [:local, :remote, :not_required].include?(mode_name) @environment_mode = mode_name end |
.exit(code) ⇒ Object
this is used for testing
495 496 497 |
# File 'lib/puppet/application.rb', line 495 def self.exit(code) exit(code) end |
.find(application_name) ⇒ Class
Finds the class for a given application and loads the class. This does not create an instance of the application, it only gets a handle to the class. The code for the application is expected to live in a ruby file ‘puppet/application/##name.rb` that is available on the `$LOAD_PATH`.
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
# File 'lib/puppet/application.rb', line 234 def find(application_name) begin require @loader.(application_name.to_s.downcase) rescue LoadError => e Puppet.log_and_raise(e, _("Unable to find application '%{application_name}'. %{error}") % { application_name: application_name, error: e }) end class_name = Puppet::Util::ConstantInflector.file2constant(application_name.to_s) clazz = try_load_class(class_name) ################################################################ #### Begin 2.7.x backward compatibility hack; #### eventually we need to issue a deprecation warning here, #### and then get rid of this stanza in a subsequent release. ################################################################ if (clazz.nil?) class_name = application_name.capitalize clazz = try_load_class(class_name) end ################################################################ #### End 2.7.x backward compatibility hack ################################################################ if clazz.nil? raise Puppet::Error.new(_("Unable to load application class '%{class_name}' from file 'puppet/application/%{application_name}.rb'") % { class_name: class_name, application_name: application_name }) end return clazz end |
.get_environment_mode ⇒ Object
Gets environment_mode name. If none is set with ‘environment_mode=`, default to :local.
304 305 306 |
# File 'lib/puppet/application.rb', line 304 def get_environment_mode @environment_mode || :local end |
.interrupted? ⇒ Boolean
Indicates that one of stop! or start! was invoked on Puppet::Application, and some kind of process shutdown/short-circuit may be necessary.
162 163 164 |
# File 'lib/puppet/application.rb', line 162 def interrupted? [:restart_requested, :stop_requested].include? run_status end |
.option(*options, &block) ⇒ Object
used to declare code that handle an option
185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/puppet/application.rb', line 185 def option(*, &block) long = .find { |opt| opt =~ /^--/ }.gsub(/^--(?:\[no-\])?([^ =]+).*$/, '\1' ).gsub('-','_') fname = "handle_#{long}".intern if (block_given?) define_method(fname, &block) else define_method(fname) do |value| self.["#{long}".to_sym] = value end end self.option_parser_commands << [, fname] end |
.option_parser_commands ⇒ Object
202 203 204 205 206 207 |
# File 'lib/puppet/application.rb', line 202 def option_parser_commands @option_parser_commands ||= ( superclass.respond_to?(:option_parser_commands) ? superclass.option_parser_commands.dup : [] ) @option_parser_commands end |
.restart! ⇒ Object
144 145 146 |
# File 'lib/puppet/application.rb', line 144 def restart! self.run_status = :restart_requested end |
.restart_requested? ⇒ Boolean
Indicates that Puppet::Application.restart! has been invoked and components should do what is necessary to facilitate a restart.
150 151 152 |
# File 'lib/puppet/application.rb', line 150 def restart_requested? :restart_requested == run_status end |
.run_mode(mode_name = nil) ⇒ Object
Sets or gets the run_mode name. Sets the run_mode name if a mode_name is passed. Otherwise, gets the run_mode or a default run_mode
280 281 282 283 284 285 286 287 288 289 |
# File 'lib/puppet/application.rb', line 280 def run_mode( mode_name = nil) if mode_name Puppet.settings.preferred_run_mode = mode_name end return @run_mode if @run_mode and not mode_name require 'puppet/util/run_mode' @run_mode = Puppet::Util::RunMode[ mode_name || Puppet.settings.preferred_run_mode ] end |
.stop! ⇒ Object
140 141 142 |
# File 'lib/puppet/application.rb', line 140 def stop! self.run_status = :stop_requested end |
.stop_requested? ⇒ Boolean
Indicates that Puppet::Application.stop! has been invoked and components should do what is necessary for a clean stop.
156 157 158 |
# File 'lib/puppet/application.rb', line 156 def stop_requested? :stop_requested == run_status end |
.try_load_class(class_name) ⇒ Class
Given the fully qualified name of a class, attempt to get the class instance.
268 269 270 |
# File 'lib/puppet/application.rb', line 268 def try_load_class(class_name) return self.const_defined?(class_name) ? const_get(class_name) : nil end |
Instance Method Details
#app_defaults ⇒ Object
330 331 332 333 334 |
# File 'lib/puppet/application.rb', line 330 def app_defaults() Puppet::Settings.app_defaults_for_run_mode(self.class.run_mode).merge( :name => name ) end |
#configure_indirector_routes ⇒ Object
432 433 434 |
# File 'lib/puppet/application.rb', line 432 def configure_indirector_routes Puppet::ApplicationSupport.configure_indirector_routes(name.to_s) end |
#deprecate ⇒ Object
call in setup of subclass to deprecate an application
350 351 352 |
# File 'lib/puppet/application.rb', line 350 def deprecate @deprecated = true end |
#deprecated? ⇒ Boolean
354 355 356 |
# File 'lib/puppet/application.rb', line 354 def deprecated? @deprecated end |
#handle_logdest_arg(arg) ⇒ Object
420 421 422 423 424 425 426 427 428 429 430 |
# File 'lib/puppet/application.rb', line 420 def handle_logdest_arg(arg) return if [:setdest] || arg.nil? begin Puppet[:logdest] = arg Puppet::Util::Log.newdestination(arg) [:setdest] = true rescue => detail Puppet.log_and_raise(detail, _("Could not set logdest to %{dest}.") % { dest: arg }) end end |
#handlearg(opt, val) ⇒ Object
489 490 491 492 |
# File 'lib/puppet/application.rb', line 489 def handlearg(opt, val) opt, val = Puppet::Settings.clean_opt(opt, val) send(:handle_unknown, opt, val) if respond_to?(:handle_unknown) end |
#help ⇒ Object
503 504 505 |
# File 'lib/puppet/application.rb', line 503 def help _("No help available for puppet %{app_name}") % { app_name: name } end |
#initialize_app_defaults ⇒ Object
336 337 338 |
# File 'lib/puppet/application.rb', line 336 def initialize_app_defaults() Puppet.settings.initialize_app_defaults(app_defaults) end |
#log_runtime_environment(extra_info = nil) ⇒ void
This method returns an undefined value.
Output basic information about the runtime environment for debugging purposes.
444 445 446 447 448 449 450 451 452 453 454 |
# File 'lib/puppet/application.rb', line 444 def log_runtime_environment(extra_info=nil) runtime_info = { 'puppet_version' => Puppet.version, 'ruby_version' => RUBY_VERSION, 'run_mode' => self.class.run_mode.name, } runtime_info['default_encoding'] = Encoding.default_external runtime_info.merge!(extra_info) unless extra_info.nil? Puppet.debug 'Runtime environment: ' + runtime_info.map{|k,v| k + '=' + v.to_s}.join(', ') end |
#main ⇒ Object
385 386 387 |
# File 'lib/puppet/application.rb', line 385 def main raise NotImplementedError, _("No valid command or main") end |
#name ⇒ Object
499 500 501 |
# File 'lib/puppet/application.rb', line 499 def name self.class.to_s.sub(/.*::/,"").downcase.to_sym end |
#parse_options ⇒ Object
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/puppet/application.rb', line 456 def # Create an option parser option_parser = OptionParser.new(self.class.) # Here we're building up all of the options that the application may need to handle. The main # puppet settings defined in "defaults.rb" have already been parsed once (in command_line.rb) by # the time we get here; however, our app may wish to handle some of them specially, so we need to # make the parser aware of them again. We might be able to make this a bit more efficient by # re-using the parser object that gets built up in command_line.rb. --cprice 2012-03-16 # Add all global options to it. Puppet.settings.optparse_addargs([]).each do |option| option_parser.on(*option) do |arg| handlearg(option[0], arg) end end # Add options that are local to this application, which were # created using the "option()" metaprogramming method. If there # are any conflicts, this application's options will be favored. self.class.option_parser_commands.each do |, fname| option_parser.on(*) do |value| # Call the method that "option()" created. self.send(fname, value) end end # Scan command line. We just hand any exceptions to our upper levels, # rather than printing help and exiting, so that we can meaningfully # respond with context-sensitive help if we want to. --daniel 2011-04-12 option_parser.parse!(self.command_line.args) end |
#preinit ⇒ Object
override to execute code before running anything else
341 342 |
# File 'lib/puppet/application.rb', line 341 def preinit end |
#run ⇒ void
This method returns an undefined value.
Execute the application.
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 |
# File 'lib/puppet/application.rb', line 361 def run # I don't really like the names of these lifecycle phases. It would be nice to change them to some more meaningful # names, and make deprecated aliases. --cprice 2012-03-16 exit_on_fail(_("Could not get application-specific default settings")) do initialize_app_defaults end Puppet::ApplicationSupport.push_application_context(self.class.run_mode, self.class.get_environment_mode) exit_on_fail(_("Could not initialize")) { preinit } exit_on_fail(_("Could not parse application options")) { } exit_on_fail(_("Could not prepare for execution")) { setup } if deprecated? Puppet.deprecation_warning(_("`puppet %{name}` is deprecated and will be removed in a future release.") % { name: name }) end exit_on_fail(_("Could not configure routes from %{route_file}") % { route_file: Puppet[:route_file] }) { configure_indirector_routes } exit_on_fail(_("Could not log runtime debug info")) { log_runtime_environment } exit_on_fail(_("Could not run")) { run_command } end |
#run_command ⇒ Object
389 390 391 |
# File 'lib/puppet/application.rb', line 389 def run_command main end |
#set_log_level(opts = nil) ⇒ Object
411 412 413 414 415 416 417 418 |
# File 'lib/puppet/application.rb', line 411 def set_log_level(opts = nil) opts ||= if opts[:debug] Puppet::Util::Log.level = :debug elsif opts[:verbose] && !Puppet::Util::Log.sendlevel?(:info) Puppet::Util::Log.level = :info end end |
#setup ⇒ Object
393 394 395 |
# File 'lib/puppet/application.rb', line 393 def setup setup_logs end |
#setup_logs ⇒ Object
397 398 399 400 401 402 403 404 405 406 407 408 409 |
# File 'lib/puppet/application.rb', line 397 def setup_logs handle_logdest_arg(Puppet[:logdest]) unless [:setdest] if [:debug] || [:verbose] Puppet::Util::Log.newdestination(:console) end end set_log_level Puppet::Util::Log.setup_default unless [:setdest] end |
#summary ⇒ Object
The description used in top level ‘puppet help` output If left empty in implementations, we will attempt to extract the summary from the help text itself.
510 511 512 |
# File 'lib/puppet/application.rb', line 510 def summary "" end |