Class MCollective::Application
In: lib/mcollective/application.rb
Parent: Object

Methods

Included Modules

RPC

Public Class methods

retrieves a specific option

[Source]

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

set an option in the options hash

[Source]

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

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

[Source]

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

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

[Source]

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

[Source]

    # File lib/mcollective/application.rb, line 38
38:       def exclude_argument_sections(*sections)
39:         sections = [sections].flatten
40: 
41:         sections.each do |s|
42:           raise "Unknown CLI argument section #{s}" unless ["rpc", "common", "filter"].include?(s)
43:         end
44: 
45:         intialize_application_options unless @application_options
46:         self[:exclude_arg_sections] = sections
47:       end

Creates an empty set of options

[Source]

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

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[:foo]

[Source]

    # File lib/mcollective/application.rb, line 65
65:       def option(name, arguments)
66:         opt = {:name => name,
67:                :description => nil,
68:                :arguments => [],
69:                :type => String,
70:                :required => false,
71:                :validate => Proc.new { true }}
72: 
73:         arguments.each_pair{|k,v| opt[k] = v}
74: 
75:         self[:cli_arguments] << opt
76:       end

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

[Source]

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

Public Instance methods

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

[Source]

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

Retrieve the current application description

[Source]

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

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

[Source]

     # File lib/mcollective/application.rb, line 251
251:     def application_failure(e, err_dest=STDERR)
252:       # peole can use exit() anywhere and not get nasty backtraces as a result
253:       if e.is_a?(SystemExit)
254:         disconnect
255:         raise(e)
256:       end
257: 
258:       err_dest.puts "#{$0} failed to run: #{e} (#{e.class})"
259: 
260:       if options.nil? || options[:verbose]
261:         e.backtrace.each{|l| err_dest.puts "\tfrom #{l}"}
262:       end
263: 
264:       disconnect
265: 
266:       exit 1
267:     end

Retrieves the full hash of application options

[Source]

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

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

[Source]

     # File lib/mcollective/application.rb, line 135
135:     def application_parse_options(help=false)
136:       @options ||= {:verbose => false}
137: 
138:       @options = clioptions(help) do |parser, options|
139:         parser.define_head application_description if application_description
140:         parser.banner = ""
141: 
142:         if application_usage
143:           parser.separator ""
144: 
145:           application_usage.each do |u|
146:             parser.separator "Usage: #{u}"
147:           end
148: 
149:           parser.separator ""
150:         end
151: 
152:         parser.define_tail ""
153:         parser.define_tail "The Marionette Collective #{MCollective.version}"
154: 
155: 
156:         application_cli_arguments.each do |carg|
157:           opts_array = []
158: 
159:           opts_array << :on
160: 
161:           # if a default is set from the application set it up front
162:           if carg.include?(:default)
163:             configuration[carg[:name]] = carg[:default]
164:           end
165: 
166:           # :arguments are multiple possible ones
167:           if carg[:arguments].is_a?(Array)
168:             carg[:arguments].each {|a| opts_array << a}
169:           else
170:             opts_array << carg[:arguments]
171:           end
172: 
173:           # type was given and its not one of our special types, just pass it onto optparse
174:           opts_array << carg[:type] if carg[:type] and ! [:bool, :array].include?(carg[:type])
175: 
176:           opts_array << carg[:description]
177: 
178:           # Handle our special types else just rely on the optparser to handle the types
179:           if carg[:type] == :bool
180:             parser.send(*opts_array) do |v|
181:               validate_option(carg[:validate], carg[:name], v)
182: 
183:               configuration[carg[:name]] = true
184:             end
185: 
186:           elsif carg[:type] == :array
187:             parser.send(*opts_array) do |v|
188:               validate_option(carg[:validate], carg[:name], v)
189: 
190:               configuration[carg[:name]] = [] unless configuration.include?(carg[:name])
191:               configuration[carg[:name]] << v
192:             end
193: 
194:           else
195:             parser.send(*opts_array) do |v|
196:               validate_option(carg[:validate], carg[:name], v)
197: 
198:               configuration[carg[:name]] = v
199:             end
200:           end
201:         end
202:       end
203:     end

Return the current usage text false if nothing is set

[Source]

     # File lib/mcollective/application.rb, line 237
237:     def application_usage
238:       usage = application_options[:usage]
239: 
240:       usage.empty? ? false : usage
241:     end

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

[Source]

     # File lib/mcollective/application.rb, line 111
111:     def clioptions(help)
112:       oparser = Optionparser.new({:verbose => false, :progress_bar => true}, "filter", application_options[:exclude_arg_sections])
113: 
114:       options = oparser.parse do |parser, options|
115:         if block_given?
116:           yield(parser, options)
117:         end
118: 
119:         RPC::Helpers.add_simplerpc_options(parser, options) unless application_options[:exclude_arg_sections].include?("rpc")
120:       end
121: 
122:       return oparser.parser.help if help
123: 
124:       validate_cli_options
125: 
126:       post_option_parser(configuration) if respond_to?(:post_option_parser)
127: 
128:       return options
129:     rescue Exception => e
130:       application_failure(e)
131:     end

The application configuration built from CLI arguments

[Source]

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

[Source]

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

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 receivedif Exit with 4 if no discovery were done and no responses were received

[Source]

     # File lib/mcollective/application.rb, line 312
312:     def halt(stats)
313:       request_stats = {:discoverytime => 0,
314:                        :discovered => 0,
315:                        :failcount => 0}.merge(stats.to_hash)
316: 
317:       # was discovery done?
318:       if request_stats[:discoverytime] != 0
319:         # was any nodes discovered
320:         if request_stats[:discovered] == 0
321:           exit 1
322: 
323:         # nodes were discovered, did we get responses
324:         elsif request_stats[:responses] == 0
325:           exit 3
326: 
327:         else
328:           # we got responses and discovery was done, no failures
329:           if request_stats[:failcount] == 0
330:             exit 0
331:           else
332:             exit 2
333:           end
334:         end
335:       else
336:         # discovery wasnt done and we got no responses
337:         if request_stats[:responses] == 0
338:           exit 4
339:         else
340:           exit 0
341:         end
342:       end
343:     end

[Source]

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

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

[Source]

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

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

[Source]

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

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

[Source]

     # File lib/mcollective/application.rb, line 348
348:     def rpcclient(agent, flags = {})
349:       flags[:options] = options unless flags.include?(:options)
350: 
351:       super
352:     end

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

[Source]

     # File lib/mcollective/application.rb, line 276
276:     def run
277:       application_parse_options
278: 
279:       validate_configuration(configuration) if respond_to?(:validate_configuration)
280: 
281:       Util.setup_windows_sleeper if Util.windows?
282: 
283:       main
284: 
285:       disconnect
286: 
287:     rescue Exception => e
288:       application_failure(e)
289:     end

[Source]

     # File lib/mcollective/application.rb, line 205
205:     def validate_cli_options
206:       # Check all required parameters were set
207:       validation_passed = true
208:       application_cli_arguments.each do |carg|
209:         # Check for required arguments
210:         if carg[:required]
211:           unless configuration[ carg[:name] ]
212:             validation_passed = false
213:             STDERR.puts "The #{carg[:name]} option is mandatory"
214:           end
215:         end
216:       end
217: 
218:       unless validation_passed
219:         STDERR.puts "\nPlease run with --help for detailed help"
220:         exit 1
221:       end
222: 
223: 
224:     end

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

[Source]

     # File lib/mcollective/application.rb, line 100
100:     def validate_option(blk, name, value)
101:       validation_result = blk.call(value)
102: 
103:       unless validation_result == true
104:         STDERR.puts "Validation of #{name} failed: #{validation_result}"
105:         exit 1
106:       end
107:     end

[Validate]