Class | MCollective::Applications |
In: |
lib/mcollective/applications.rb
|
Parent: | Object |
# File lib/mcollective/applications.rb, line 3 3: def self.[](appname) 4: load_application(appname) 5: PluginManager["#{appname}_application"] 6: end
Filters a string of opts out using Shellwords keeping only things related to —config and -c
# File lib/mcollective/applications.rb, line 60 60: def self.filter_extra_options(opts) 61: res = "" 62: words = Shellwords.shellwords(opts) 63: words.each_with_index do |word,idx| 64: if word == "-c" 65: return "--config=#{words[idx + 1]}" 66: elsif word == "--config" 67: return "--config=#{words[idx + 1]}" 68: elsif word =~ /\-c=/ 69: return word 70: elsif word =~ /\-\-config=/ 71: return word 72: end 73: end 74: 75: return "" 76: end
Returns an array of applications found in the lib dirs
# File lib/mcollective/applications.rb, line 36 36: def self.list 37: load_config 38: 39: applist = [] 40: 41: Config.instance.libdir.each do |libdir| 42: applicationdir = "#{libdir}/mcollective/application" 43: next unless File.directory?(applicationdir) 44: 45: Dir.entries(applicationdir).grep(/\.rb$/).each do |application| 46: applist << File.basename(application, ".rb") 47: end 48: end 49: 50: applist 51: rescue SystemExit 52: exit 1 53: rescue Exception => e 54: STDERR.puts "Failed to generate application list: #{e.class}: #{e}" 55: exit 1 56: end
# File lib/mcollective/applications.rb, line 26 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
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, line 95 95: def self.load_config 96: return if Config.instance.configured 97: 98: original_argv = ARGV.clone 99: original_extra_opts = ENV["MCOLLECTIVE_EXTRA_OPTS"].clone rescue nil 100: configfile = nil 101: 102: parser = OptionParser.new 103: parser.on("--config CONFIG", "-c", "Config file") do |f| 104: configfile = f 105: end 106: 107: parser.program_name = $0 108: 109: parser.on("--help") 110: 111: # avoid option parsers own internal version handling that sux 112: parser.on("-v", "--verbose") 113: 114: if original_extra_opts 115: begin 116: # optparse will parse the whole ENV in one go and refuse 117: # to play along with the retry trick I do below so in 118: # order to handle unknown options properly I parse out 119: # only -c and --config deleting everything else and 120: # then restore the environment variable later when I 121: # am done with it 122: ENV["MCOLLECTIVE_EXTRA_OPTS"] = filter_extra_options(ENV["MCOLLECTIVE_EXTRA_OPTS"].clone) 123: parser.environment("MCOLLECTIVE_EXTRA_OPTS") 124: rescue Exception => e 125: Log.error("Failed to parse MCOLLECTIVE_EXTRA_OPTS: #{e}") 126: end 127: 128: ENV["MCOLLECTIVE_EXTRA_OPTS"] = original_extra_opts.clone 129: end 130: 131: begin 132: parser.parse! 133: rescue OptionParser::InvalidOption => e 134: retry 135: end 136: 137: ARGV.clear 138: original_argv.each {|a| ARGV << a} 139: 140: configfile = Util.config_file_for_user unless configfile 141: 142: Config.instance.loadconfig(configfile) 143: end
# File lib/mcollective/applications.rb, line 8 8: def self.run(appname) 9: load_config 10: 11: begin 12: load_application(appname) 13: rescue Exception => e 14: e.backtrace.first << RPC::Helpers.colorize(:red, " <----") 15: STDERR.puts "Application '#{appname}' failed to load:" 16: STDERR.puts 17: STDERR.puts RPC::Helpers.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