class MCollective::Applications

Public Class Methods

[](appname) click to toggle source
  # File lib/mcollective/applications.rb
3 def self.[](appname)
4   load_application(appname)
5   PluginManager["#{appname}_application"]
6 end
filter_extra_options(opts) click to toggle source

Filters a string of opts out using Shellwords keeping only things related to –config and -c

   # File lib/mcollective/applications.rb
49 def self.filter_extra_options(opts)
50   res = ""
51   words = Shellwords.shellwords(opts)
52   words.each_with_index do |word,idx|
53     if word == "-c"
54       return "--config=#{words[idx + 1]}"
55     elsif word == "--config"
56       return "--config=#{words[idx + 1]}"
57     elsif word =~ /\-c=/
58       return word
59     elsif word =~ /\-\-config=/
60       return word
61     end
62   end
63 
64   return ""
65 end
list() click to toggle source

Returns an array of applications found in the lib dirs

   # File lib/mcollective/applications.rb
36 def self.list
37   load_config
38 
39   PluginManager.find("application")
40 rescue SystemExit
41   exit 1
42 rescue Exception => e
43   STDERR.puts "Failed to generate application list: #{e.class}: #{e}"
44   exit 1
45 end
load_application(appname) click to toggle source
   # File lib/mcollective/applications.rb
26 def self.load_application(appname)
27   return if PluginManager.include?("#{appname}_application")
28 
29   load_config
30 
31   PluginManager.loadclass "MCollective::Application::#{appname.capitalize}"
32   PluginManager << {:type => "#{appname}_application", :class => "MCollective::Application::#{appname.capitalize}"}
33 end
load_config() click to toggle source

We need to know the config file in order to know the libdir so that we can find applications.

The problem is the CLI might be stuffed with options only the app in the libdir might understand so we have a chicken and egg situation.

We're parsing and filtering MCOLLECTIVE_EXTRA_OPTS removing all but config related options and parsing the options looking just for the config file.

We're handling failures gracefully and finally restoring the ARG and MCOLLECTIVE_EXTRA_OPTS to the state they were before we started parsing.

This is mostly a hack, when we're redoing how config works this stuff should be made less sucky

    # File lib/mcollective/applications.rb
 84 def self.load_config
 85   return if Config.instance.configured
 86 
 87   original_argv = ARGV.clone
 88   original_extra_opts = ENV["MCOLLECTIVE_EXTRA_OPTS"].clone rescue nil
 89   configfile = nil
 90 
 91   parser = OptionParser.new
 92   parser.on("--config CONFIG", "-c", "Config file") do |f|
 93     configfile = f
 94   end
 95 
 96   parser.program_name = $0
 97 
 98   parser.on("--help")
 99 
100   # avoid option parsers own internal version handling that sux
101   parser.on("-v", "--verbose")
102 
103   if original_extra_opts
104     begin
105       # optparse will parse the whole ENV in one go and refuse
106       # to play along with the retry trick I do below so in
107       # order to handle unknown options properly I parse out
108       # only -c and --config deleting everything else and
109       # then restore the environment variable later when I
110       # am done with it
111       ENV["MCOLLECTIVE_EXTRA_OPTS"] = filter_extra_options(ENV["MCOLLECTIVE_EXTRA_OPTS"].clone)
112       parser.environment("MCOLLECTIVE_EXTRA_OPTS")
113     rescue Exception => e
114       Log.error("Failed to parse MCOLLECTIVE_EXTRA_OPTS: #{e}")
115     end
116 
117     ENV["MCOLLECTIVE_EXTRA_OPTS"] = original_extra_opts.clone
118   end
119 
120   begin
121     parser.parse!
122   rescue OptionParser::InvalidOption => e
123     retry
124   end
125 
126   ARGV.clear
127   original_argv.each {|a| ARGV << a}
128 
129   configfile = Util.config_file_for_user unless configfile
130 
131   Config.instance.loadconfig(configfile)
132 end
run(appname) click to toggle source
   # File lib/mcollective/applications.rb
 8 def self.run(appname)
 9   load_config
10 
11   begin
12     load_application(appname)
13   rescue Exception => e
14     e.backtrace.first << Util.colorize(:red, "  <----")
15     STDERR.puts "Application '#{appname}' failed to load:"
16     STDERR.puts
17     STDERR.puts Util.colorize(:red, "   #{e} (#{e.class})")
18     STDERR.puts
19     STDERR.puts "       %s" % [e.backtrace.join("\n       ")]
20     exit 1
21   end
22 
23   PluginManager["#{appname}_application"].run
24 end