| Class | MCollective::Application |
| In: |
lib/mcollective/application.rb
|
| Parent: | Object |
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
28: def description(descr)
29: self[:description] = descr
30: end
# 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
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]
# 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
Returns an array of all the arguments built using calls to optin
# File lib/mcollective/application.rb, line 247
247: def application_cli_arguments
248: application_options[:cli_arguments]
249: end
Retrieve the current application description
# File lib/mcollective/application.rb, line 234
234: def application_description
235: application_options[:description]
236: end
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 253
253: def application_failure(e, err_dest=STDERR)
254: # peole can use exit() anywhere and not get nasty backtraces as a result
255: if e.is_a?(SystemExit)
256: disconnect
257: raise(e)
258: end
259:
260: if e.is_a?(CodedError)
261: err_dest.puts "\nThe %s application failed to run: %s: %s\n" % [ Util.colorize(:bold, $0), Util.colorize(:bold, e.code), Util.colorize(:red, e.to_s)]
262:
263: err_dest.puts
264: if options[:verbose]
265: err_dest.puts "Use the 'mco doc %s' command for details about this error" % e.code
266: else
267: err_dest.puts "Use the 'mco doc %s' command for details about this error, use -v for full error backtrace details" % e.code
268: end
269: else
270: if options[:verbose]
271: err_dest.puts "\nThe %s application failed to run: %s\n" % [ Util.colorize(:bold, $0), Util.colorize(:red, e.to_s)]
272: else
273: err_dest.puts "\nThe %s application failed to run, use -v for full error backtrace details: %s\n" % [ Util.colorize(:bold, $0), Util.colorize(:red, e.to_s)]
274: end
275: end
276:
277: if options.nil? || options[:verbose]
278: e.backtrace.first << Util.colorize(:red, " <----")
279: err_dest.puts "\n%s %s" % [ Util.colorize(:red, e.to_s), Util.colorize(:bold, "(#{e.class.to_s})")]
280: e.backtrace.each{|l| err_dest.puts "\tfrom #{l}"}
281: end
282:
283: disconnect
284:
285: exit 1
286: end
Builds an ObjectParser config, parse the CLI options and validates based on the option config
# 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.separator "Application Options" unless application_cli_arguments.empty?
153:
154: parser.define_tail ""
155: parser.define_tail "The Marionette Collective #{MCollective.version}"
156:
157:
158: application_cli_arguments.each do |carg|
159: opts_array = []
160:
161: opts_array << :on
162:
163: # if a default is set from the application set it up front
164: if carg.include?(:default)
165: configuration[carg[:name]] = carg[:default]
166: end
167:
168: # :arguments are multiple possible ones
169: if carg[:arguments].is_a?(Array)
170: carg[:arguments].each {|a| opts_array << a}
171: else
172: opts_array << carg[:arguments]
173: end
174:
175: # type was given and its not one of our special types, just pass it onto optparse
176: opts_array << carg[:type] if carg[:type] && ![:boolean, :bool, :array].include?(carg[:type])
177:
178: opts_array << carg[:description]
179:
180: # Handle our special types else just rely on the optparser to handle the types
181: if [:bool, :boolean].include?(carg[:type])
182: parser.send(*opts_array) do |v|
183: validate_option(carg[:validate], carg[:name], v)
184:
185: configuration[carg[:name]] = v
186: end
187:
188: elsif carg[:type] == :array
189: parser.send(*opts_array) do |v|
190: validate_option(carg[:validate], carg[:name], v)
191:
192: configuration[carg[:name]] = [] unless configuration.include?(carg[:name])
193: configuration[carg[:name]] << v
194: end
195:
196: else
197: parser.send(*opts_array) do |v|
198: validate_option(carg[:validate], carg[:name], v)
199:
200: configuration[carg[:name]] = v
201: end
202: end
203: end
204: end
205: end
Creates a standard options hash, pass in a block to add extra headings etc see Optionparser
# 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
# File lib/mcollective/application.rb, line 88
88: def configuration
89: @application_configuration ||= {}
90: @application_configuration
91: end
# File lib/mcollective/application.rb, line 310
310: def disconnect
311: MCollective::PluginManager["connector_plugin"].disconnect
312: rescue
313: 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 received Exit with 4 if no discovery were done and no responses were received
# File lib/mcollective/application.rb, line 331
331: def halt(stats)
332: request_stats = {:discoverytime => 0,
333: :discovered => 0,
334: :failcount => 0}.merge(stats.to_hash)
335:
336: # was discovery done?
337: if request_stats[:discoverytime] != 0
338: # was any nodes discovered
339: if request_stats[:discovered] == 0
340: exit 1
341:
342: # nodes were discovered, did we get responses
343: elsif request_stats[:responses] == 0
344: exit 3
345:
346: else
347: # we got responses and discovery was done, no failures
348: if request_stats[:failcount] == 0
349: exit 0
350: else
351: exit 2
352: end
353: end
354: else
355: # discovery wasnt done and we got no responses
356: if request_stats[:responses] == 0
357: exit 4
358: else
359: exit 0
360: end
361: end
362: end
# File lib/mcollective/application.rb, line 288
288: def help
289: application_parse_options(true)
290: end
The active options hash used for MC::Client and other configuration
# 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
# File lib/mcollective/application.rb, line 367
367: def rpcclient(agent, flags = {})
368: flags[:options] = options unless flags.include?(:options)
369: flags[:exit_on_failure] = false
370:
371: super
372: 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
# File lib/mcollective/application.rb, line 295
295: def run
296: application_parse_options
297:
298: validate_configuration(configuration) if respond_to?(:validate_configuration)
299:
300: Util.setup_windows_sleeper if Util.windows?
301:
302: main
303:
304: disconnect
305:
306: rescue Exception => e
307: application_failure(e)
308: end
# File lib/mcollective/application.rb, line 207
207: def validate_cli_options
208: # Check all required parameters were set
209: validation_passed = true
210: application_cli_arguments.each do |carg|
211: # Check for required arguments
212: if carg[:required]
213: unless configuration[ carg[:name] ]
214: validation_passed = false
215: STDERR.puts "The #{carg[:name]} option is mandatory"
216: end
217: end
218: end
219:
220: unless validation_passed
221: STDERR.puts "\nPlease run with --help for detailed help"
222: exit 1
223: end
224:
225:
226: end
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
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