# class MCollective::Application

### Public Class Methods

[](option) click to toggle source

retrieves a specific option

    # File lib/mcollective/application.rb, line 20
    def [](option)
      intialize_application_options unless @application_options
      @application_options[option]
    end

[]=(option, value) click to toggle source

set an option in the options hash

    # File lib/mcollective/application.rb, line 14
    def []=(option, value)
      intialize_application_options unless @application_options
      @application_options[option] = value
    end

application_options() click to toggle source

Intialize a blank set of options if its the first time used else returns active options

    # File lib/mcollective/application.rb, line 8
    def application_options
      intialize_application_options unless @application_options
      @application_options
    end

description(descr) click to toggle source

Sets the application description, there can be only one description per application so multiple calls will just change the description

    # File lib/mcollective/application.rb, line 28
    def description(descr)
      self[:description] = descr
    end

exclude_argument_sections(*sections) click to toggle source

    # File lib/mcollective/application.rb, line 38
    def exclude_argument_sections(*sections)
      sections = [sections].flatten

      sections.each do |s|
        raise "Unknown CLI argument section #{s}" unless ["rpc", "common", "filter"].include?(s)
      end

      intialize_application_options unless @application_options
      self[:exclude_arg_sections] = sections
    end

intialize_application_options() click to toggle source

Creates an empty set of options

    # File lib/mcollective/application.rb, line 79
    def intialize_application_options
      @application_options = {:description          => nil,
                              :usage                => [],
                              :cli_arguments        => [],
                              :exclude_arg_sections => []}
    end

option(name, arguments) click to toggle source

Wrapper to create command line options

    - name: varaible name that will be used to access the option value
    - description: textual info shown in --help
    - arguments: a list of possible arguments that can be used
      to activate this option
    - type: a data type that ObjectParser understand of :bool or :array
    - required: true or false if this option has to be supplied
    - validate: a proc that will be called with the value used to validate
      the supplied value

     option :foo,
            :description => "The foo option"
            :arguments   => ["--foo ARG"]

after this the value supplied will be in configuration

    # File lib/mcollective/application.rb, line 65
    def option(name, arguments)
      opt = {:name => name,
             :description => nil,
             :arguments => [],
             :type => String,
             :required => false,
             :validate => Proc.new { true }}

      arguments.each_pair{|k,v| opt[k] = v}

      self[:cli_arguments] << opt
    end

usage(usage) click to toggle source

Supplies usage information, calling multiple times will create multiple usage lines in –help output

    # File lib/mcollective/application.rb, line 34
    def usage(usage)
      self[:usage] << usage
    end

### Public Instance Methods

application_cli_arguments() click to toggle source

Returns an array of all the arguments built using calls to optin

    # File lib/mcollective/application.rb, line 245
    def application_cli_arguments
      application_options[:cli_arguments]
    end

application_description() click to toggle source

Retrieve the current application description

    # File lib/mcollective/application.rb, line 232
    def application_description
      application_options[:description]
    end

application_failure(e, err_dest=STDERR) click to toggle source

Handles failure, if we’re far enough in the initialization phase it will log backtraces if its in verbose mode only

    # File lib/mcollective/application.rb, line 251
    def application_failure(e, err_dest=STDERR)
      # peole can use exit() anywhere and not get nasty backtraces as a result
      if e.is_a?(SystemExit)
        disconnect
        raise(e)
      end

      err_dest.puts "\nThe %s application failed to run, use -v for full error details: %s\n" % [ Util.colorize(:bold, $0), Util.colorize(:red, e.to_s)]

      if options.nil? || options[:verbose]
        e.backtrace.first << Util.colorize(:red, "  <----")
        err_dest.puts "\n%s %s" % [ Util.colorize(:red, e.to_s), Util.colorize(:bold, "(#{e.class.to_s})")]
        e.backtrace.each{|l| err_dest.puts "\tfrom #{l}"}
      end

      disconnect

      exit 1
    end

application_options() click to toggle source

Retrieves the full hash of application options

    # File lib/mcollective/application.rb, line 227
    def application_options
      self.class.application_options
    end

application_parse_options(help=false) click to toggle source

Builds an ObjectParser config, parse the CLI options and validates based on the option config

    # File lib/mcollective/application.rb, line 135
    def application_parse_options(help=false)
      @options ||= {:verbose => false}

      @options = clioptions(help) do |parser, options|
        parser.define_head application_description if application_description
        parser.banner = ""

        if application_usage
          parser.separator ""

          application_usage.each do |u|
            parser.separator "Usage: #{u}"
          end

          parser.separator ""
        end

        parser.define_tail ""
        parser.define_tail "The Marionette Collective #{MCollective.version}"

        application_cli_arguments.each do |carg|
          opts_array = []

          opts_array << :on

          # if a default is set from the application set it up front
          if carg.include?(:default)
            configuration[carg[:name]] = carg[:default]
          end

          # :arguments are multiple possible ones
          if carg[:arguments].is_a?(Array)
            carg[:arguments].each {|a| opts_array << a}
          else
            opts_array << carg[:arguments]
          end

          # type was given and its not one of our special types, just pass it onto optparse
          opts_array << carg[:type] if carg[:type] && ![:boolean, :bool, :array].include?(carg[:type])

          opts_array << carg[:description]

          # Handle our special types else just rely on the optparser to handle the types
          if [:bool, :boolean].include?(carg[:type])
            parser.send(*opts_array) do |v|
              validate_option(carg[:validate], carg[:name], v)

              configuration[carg[:name]] = true
            end

          elsif carg[:type] == :array
            parser.send(*opts_array) do |v|
              validate_option(carg[:validate], carg[:name], v)

              configuration[carg[:name]] = [] unless configuration.include?(carg[:name])
              configuration[carg[:name]] << v
            end

          else
            parser.send(*opts_array) do |v|
              validate_option(carg[:validate], carg[:name], v)

              configuration[carg[:name]] = v
            end
          end
        end
      end
    end

application_usage() click to toggle source

Return the current usage text false if nothing is set

    # File lib/mcollective/application.rb, line 237
    def application_usage
      usage = application_options[:usage]

      usage.empty? ? false : usage
    end

clioptions(help) { |parser, options| ... } click to toggle source

Creates a standard options hash, pass in a block to add extra headings etc see Optionparser

    # File lib/mcollective/application.rb, line 111
    def clioptions(help)
      oparser = Optionparser.new({:verbose => false, :progress_bar => true}, "filter", application_options[:exclude_arg_sections])

      options = oparser.parse do |parser, options|
        if block_given?
          yield(parser, options)
        end

        RPC::Helpers.add_simplerpc_options(parser, options) unless application_options[:exclude_arg_sections].include?("rpc")
      end

      return oparser.parser.help if help

      validate_cli_options

      post_option_parser(configuration) if respond_to?(:post_option_parser)

      return options
    rescue Exception => e
      application_failure(e)
    end

configuration() click to toggle source

The application configuration built from CLI arguments

    # File lib/mcollective/application.rb, line 88
    def configuration
      @application_configuration ||= {}
      @application_configuration
    end

disconnect() click to toggle source

    # File lib/mcollective/application.rb, line 293
    def disconnect
      MCollective::PluginManager["connector_plugin"].disconnect
    rescue
    end

halt(stats) click to toggle source

A helper that creates a consistent exit code for applications by looking at an instance of MCollective::RPC::Stats

Exit with 0 if nodes were discovered and all passed Exit with 0 if no discovery were done and > 0 responses were received Exit with 1 if no nodes were discovered Exit with 2 if nodes were discovered but some RPC requests failed Exit with 3 if nodes were discovered, but not responses received Exit with 4 if no discovery were done and no responses were received

    # File lib/mcollective/application.rb, line 314
    def halt(stats)
      request_stats = {:discoverytime => 0,
                       :discovered => 0,
                       :failcount => 0}.merge(stats.to_hash)

      # was discovery done?
      if request_stats[:discoverytime] != 0
        # was any nodes discovered
        if request_stats[:discovered] == 0
          exit 1

        # nodes were discovered, did we get responses
        elsif request_stats[:responses] == 0
          exit 3

        else
          # we got responses and discovery was done, no failures
          if request_stats[:failcount] == 0
            exit 0
          else
            exit 2
          end
        end
      else
        # discovery wasnt done and we got no responses
        if request_stats[:responses] == 0
          exit 4
        else
          exit 0
        end
      end
    end

help() click to toggle source

    # File lib/mcollective/application.rb, line 271
    def help
      application_parse_options(true)
    end

main() click to toggle source

Fake abstract class that logs if the user tries to use an application without supplying a main override method.

    # File lib/mcollective/application.rb, line 300
    def main
      STDERR.puts "Applications need to supply a 'main' method"
      exit 1
    end

options() click to toggle source

The active options hash used for MC::Client and other configuration

    # File lib/mcollective/application.rb, line 94
    def options
      @options
    end

rpcclient(agent, flags = {}) click to toggle source

Wrapper around MC::RPC#rpcclient that forcably supplies our options hash if someone forgets to pass in options in an application the filters and other cli options wouldnt take effect which could have a disasterous outcome

    # File lib/mcollective/application.rb, line 350
    def rpcclient(agent, flags = {})
      flags[:options] = options unless flags.include?(:options)
      flags[:exit_on_failure] = false

      super
    end

run() click to toggle source

The main logic loop, builds up the options, validate configuration and calls the main as supplied by the user. Disconnects when done and pass any exception onto the #application_failure helper

    # File lib/mcollective/application.rb, line 278
    def run
      application_parse_options

      validate_configuration(configuration) if respond_to?(:validate_configuration)

      Util.setup_windows_sleeper if Util.windows?

      main

      disconnect

    rescue Exception => e
      application_failure(e)
    end

validate_cli_options() click to toggle source

    # File lib/mcollective/application.rb, line 205
    def validate_cli_options
      # Check all required parameters were set
      validation_passed = true
      application_cli_arguments.each do |carg|
        # Check for required arguments
        if carg[:required]
          unless configuration[ carg[:name] ]
            validation_passed = false
            STDERR.puts "The #{carg[:name]} option is mandatory"
          end
        end
      end

      unless validation_passed
        STDERR.puts "\nPlease run with --help for detailed help"
        exit 1
      end

    end

validate_option(blk, name, value) click to toggle source

Calls the supplied block in an option for validation, an error raised will log to STDERR and exit the application

    # File lib/mcollective/application.rb, line 100
    def validate_option(blk, name, value)
      validation_result = blk.call(value)

      unless validation_result == true
        STDERR.puts "Validation of #{name} failed: #{validation_result}"
        exit 1
      end
    end