Class: Puppet::Application Abstract
Overview
Defines an abstract Puppet application.
# Usage
To create a new application extend ‘Puppet::Application`. Derived applications must implement the `main` method and should implement the `summary` and `help` methods in order to be included in `puppet help`, and should define application-specific options. For example:
“‘ class Puppet::Application::Example < Puppet::Application
def summary
"My puppet example application"
end
def help
<<~HELP
puppet-example(8) -- #{summary}
...
HELP
end
# define arg with a required option
option("--arg ARGUMENT") do |v|
[:arg] = v
end
# define arg with an optional option
option("--maybe [ARGUMENT]") do |v|
[:maybe] = v
end
# define long and short arg
option("--all", "-a")
def initialize(command_line = Puppet::Util::CommandLine.new)
super
@data = {}
end
def main
# call action
send(@command_line.args.shift)
end
def read
# read action
end
def write
# write action
end
end “‘
Puppet defines the following application lifecycle methods that are called in the following order:
## 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, Describe, Device, Doc, FaceBase, Filebucket, Lookup, Resource, Script, Ssl, ModuleTool::Applications::Installer, ModuleTool::Applications::Unpacker, ModuleTool::Applications::Upgrader
Defined Under Namespace
Classes: Agent, Apply, Catalog, CommandLineArgs, Config, Describe, Device, Doc, Epp, FaceBase, Facts, Filebucket, Generate, Help, IndirectionBase, Lookup, Module, Node, Parser, Plugin, Report, Resource, Script, Ssl
Constant Summary collapse
Constants included from Util
Util::ALNUM, Util::ALPHA, Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE, Util::ESCAPED, Util::HEX, Util::HttpProxy, Util::PUPPET_STACK_INSERTION_FRAME, Util::RESERVED, Util::RFC_3986_URI_REGEX, Util::UNRESERVED, Util::UNSAFE
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
Instance Attribute Summary collapse
- #command_line ⇒ Object readonly
- #options ⇒ Object readonly
Class Method Summary collapse
-
.[](name) ⇒ Puppet::Application
Return an instance of the specified application.
-
.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 ⇒ Symbol
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
Signal that the application should restart.
-
.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
Signal that the application should stop.
-
.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 ⇒ Hash<String, String>
Now that the ‘run_mode` has been resolved, return default settings for the application.
- #configure_indirector_routes ⇒ Object
-
#deprecate ⇒ void
Call in setup of subclass to deprecate an application.
-
#deprecated? ⇒ Boolean
Return true if this application is deprecated.
- #handle_logdest_arg(arg) ⇒ Object
- #handlearg(opt, val) ⇒ Object
-
#help ⇒ String
Return the text to display when running ‘puppet help`.
-
#initialize(command_line = Puppet::Util::CommandLine.new) ⇒ Application
constructor
Initialize the application receiving the Util::CommandLine object containing the application name and arguments.
-
#initialize_app_defaults ⇒ void
Initialize application defaults.
-
#log_runtime_environment(extra_info = nil) ⇒ void
Output basic information about the runtime environment for debugging purposes.
-
#main ⇒ void
This method must be overridden and perform whatever action is required for the application.
- #name ⇒ Object
-
#parse_options ⇒ void
Options defined with the ‘option` method are parsed from settings and the command line.
-
#preinit ⇒ void
The preinit block is the first code to be called in your application, after ‘initialize`, but before option parsing, setup or command execution.
-
#run ⇒ void
Execute the application.
-
#run_command ⇒ void
Run the application.
- #set_log_level(opts = nil) ⇒ Object
-
#setup ⇒ void
Setup the application.
-
#setup_logs ⇒ void
Setup logging.
-
#summary ⇒ String
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, create_erb, default_env, deterministic_rand, deterministic_rand_int, exit_on_fail, format_backtrace_array, format_puppetstack_frame, get_env, get_environment, logmethods, merge_environment, path_to_uri, pretty_backtrace, replace_file, resolve_stackframe, rfc2396_escape, safe_posix_fork, set_env, skip_external_facts, symbolizehash, thinmark, uri_encode, uri_query_encode, uri_to_path, uri_unescape, 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
#display_mode, #normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?
Constructor Details
#initialize(command_line = Puppet::Util::CommandLine.new) ⇒ Application
Initialize the application receiving the Util::CommandLine object containing the application name and arguments.
346 347 348 349 |
# File 'lib/puppet/application.rb', line 346 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
120 121 122 |
# File 'lib/puppet/application.rb', line 120 def run_status @run_status end |
Instance Attribute Details
#command_line ⇒ Object (readonly)
325 326 327 |
# File 'lib/puppet/application.rb', line 325 def command_line @command_line end |
#options ⇒ Object (readonly)
325 326 327 |
# File 'lib/puppet/application.rb', line 325 def @options end |
Class Method Details
.[](name) ⇒ Puppet::Application
Return an instance of the specified application.
274 275 276 |
# File 'lib/puppet/application.rb', line 274 def [](name) find(name).new end |
.available_application_names ⇒ Array<String>
Returns the names of available applications.
205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'lib/puppet/application.rb', line 205 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
192 193 194 |
# File 'lib/puppet/application.rb', line 192 def ( = nil) @banner ||= end |
.clear! ⇒ Object
122 123 124 |
# File 'lib/puppet/application.rb', line 122 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).
162 163 164 |
# File 'lib/puppet/application.rb', line 162 def clear? run_status.nil? end |
.clear_everything_for_tests ⇒ Object
This is for testing only
320 321 322 |
# File 'lib/puppet/application.rb', line 320 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.
171 172 173 174 175 176 |
# File 'lib/puppet/application.rb', line 171 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. When acting as a compiler, the environment mode should be ‘:local` since the directory must exist to compile the catalog. When acting as an agent, the environment mode should be `:remote` since the Puppet setting refers to an environment directoy on a remote system. The `:not_required` mode is for cases where the application does not need an environment to run.
305 306 307 308 |
# File 'lib/puppet/application.rb', line 305 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
573 574 575 |
# File 'lib/puppet/application.rb', line 573 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`.
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/puppet/application.rb', line 228 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 ⇒ Symbol
Gets environment_mode name. If none is set with ‘environment_mode=`, default to :local.
314 315 316 |
# File 'lib/puppet/application.rb', line 314 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.
155 156 157 |
# File 'lib/puppet/application.rb', line 155 def interrupted? [:restart_requested, :stop_requested].include? run_status end |
.option(*options, &block) ⇒ Object
used to declare code that handle an option
179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/puppet/application.rb', line 179 def option(*, &block) long = .find { |opt| opt =~ /^--/ }.gsub(/^--(?:\[no-\])?([^ =]+).*$/, '\1' ).tr('-','_') 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
196 197 198 199 200 201 |
# File 'lib/puppet/application.rb', line 196 def option_parser_commands @option_parser_commands ||= ( superclass.respond_to?(:option_parser_commands) ? superclass.option_parser_commands.dup : [] ) @option_parser_commands end |
.restart! ⇒ Object
Signal that the application should restart.
134 135 136 |
# File 'lib/puppet/application.rb', line 134 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.
141 142 143 |
# File 'lib/puppet/application.rb', line 141 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
281 282 283 284 285 286 287 288 289 290 |
# File 'lib/puppet/application.rb', line 281 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_relative '../puppet/util/run_mode' @run_mode = Puppet::Util::RunMode[ mode_name || Puppet.settings.preferred_run_mode ] end |
.stop! ⇒ Object
Signal that the application should stop.
128 129 130 |
# File 'lib/puppet/application.rb', line 128 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.
148 149 150 |
# File 'lib/puppet/application.rb', line 148 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.
262 263 264 |
# File 'lib/puppet/application.rb', line 262 def try_load_class(class_name) return self.const_defined?(class_name) ? const_get(class_name) : nil end |
Instance Method Details
#app_defaults ⇒ Hash<String, String>
Now that the ‘run_mode` has been resolved, return default settings for the application. Note these values may be overridden when puppet’s configuration is loaded later.
364 365 366 367 368 |
# File 'lib/puppet/application.rb', line 364 def app_defaults Puppet::Settings.app_defaults_for_run_mode(self.class.run_mode).merge( :name => name ) end |
#configure_indirector_routes ⇒ Object
492 493 494 |
# File 'lib/puppet/application.rb', line 492 def configure_indirector_routes Puppet::ApplicationSupport.configure_indirector_routes(name.to_s) end |
#deprecate ⇒ void
This method returns an undefined value.
Call in setup of subclass to deprecate an application.
388 389 390 |
# File 'lib/puppet/application.rb', line 388 def deprecate @deprecated = true end |
#deprecated? ⇒ Boolean
Return true if this application is deprecated.
394 395 396 |
# File 'lib/puppet/application.rb', line 394 def deprecated? @deprecated end |
#handle_logdest_arg(arg) ⇒ Object
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 |
# File 'lib/puppet/application.rb', line 476 def handle_logdest_arg(arg) return if arg.nil? logdest = arg.split(',').map!(&:strip) Puppet[:logdest] = arg logdest.each do |dest| begin Puppet::Util::Log.newdestination(dest) [:setdest] = true rescue => detail Puppet.log_and_raise(detail, _("Could not set logdest to %{dest}.") % { dest: arg }) end end end |
#handlearg(opt, val) ⇒ Object
567 568 569 570 |
# File 'lib/puppet/application.rb', line 567 def handlearg(opt, val) opt, val = Puppet::Settings.clean_opt(opt, val) send(:handle_unknown, opt, val) if respond_to?(:handle_unknown) end |
#help ⇒ String
Return the text to display when running ‘puppet help`.
584 585 586 |
# File 'lib/puppet/application.rb', line 584 def help _("No help available for puppet %{app_name}") % { app_name: name } end |
#initialize_app_defaults ⇒ void
This method returns an undefined value.
Initialize application defaults. It’s usually not necessary to override this method.
373 374 375 |
# File 'lib/puppet/application.rb', line 373 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.
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 |
# File 'lib/puppet/application.rb', line 503 def log_runtime_environment(extra_info=nil) runtime_info = { 'puppet_version' => Puppet.version, 'ruby_version' => RUBY_VERSION, 'run_mode' => self.class.run_mode.name } unless Puppet::Util::Platform.jruby_fips? runtime_info['openssl_version'] = "'#{OpenSSL::OPENSSL_VERSION}'" runtime_info['openssl_fips'] = OpenSSL::OPENSSL_FIPS end 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 ⇒ void
This method returns an undefined value.
This method must be overridden and perform whatever action is required for the application. The ‘command_line` reader contains the actions and arguments.
430 431 432 |
# File 'lib/puppet/application.rb', line 430 def main raise NotImplementedError, _("No valid command or main") end |
#name ⇒ Object
577 578 579 |
# File 'lib/puppet/application.rb', line 577 def name self.class.to_s.sub(/.*::/,"").downcase.to_sym end |
#parse_options ⇒ void
This method returns an undefined value.
Options defined with the ‘option` method are parsed from settings and the command line. Refer to OptionParser documentation for the exact format. Options are parsed as follows:
-
If the option method is given a block, then it will be called whenever the option is encountered in the command-line argument.
-
If the option method has no block, then the default option handler will store the argument in the ‘options` instance variable.
-
If a given option was not defined by an ‘option` method, but it exists as a Puppet setting:
-
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.
-
-
The ‘-h` and `–help` options are automatically handled by the command line before creating the application.
Options specified on the command line override settings. It is usually not necessary to override this method.
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
# File 'lib/puppet/application.rb', line 534 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 ⇒ void
This method returns an undefined value.
The preinit block is the first code to be called in your application, after ‘initialize`, but before option parsing, setup or command execution. It is usually not necessary to override this method.
382 383 |
# File 'lib/puppet/application.rb', line 382 def preinit end |
#run ⇒ void
This method returns an undefined value.
Execute the application. This method should not be overridden.
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 |
# File 'lib/puppet/application.rb', line 401 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 ⇒ void
This method returns an undefined value.
Run the application. By default, it calls #main.
437 438 439 |
# File 'lib/puppet/application.rb', line 437 def run_command main end |
#set_log_level(opts = nil) ⇒ Object
467 468 469 470 471 472 473 474 |
# File 'lib/puppet/application.rb', line 467 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 ⇒ void
This method returns an undefined value.
Setup the application. It is usually not necessary to override this method.
444 445 446 |
# File 'lib/puppet/application.rb', line 444 def setup setup_logs end |
#setup_logs ⇒ void
This method returns an undefined value.
Setup logging. By default the ‘console` log destination will only be created if `debug` or `verbose` is specified on the command line. Override to customize the logging behavior.
453 454 455 456 457 458 459 460 461 462 463 464 465 |
# File 'lib/puppet/application.rb', line 453 def setup_logs handle_logdest_arg(Puppet[:logdest]) if ![:setdest] unless [:setdest] if [:debug] || [:verbose] Puppet::Util::Log.newdestination(:console) end end set_log_level Puppet::Util::Log.setup_default unless [:setdest] end |
#summary ⇒ String
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.
593 594 595 |
# File 'lib/puppet/application.rb', line 593 def summary "" end |