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 47 47: def self.filter_extra_options(opts) 48: res = "" 49: words = Shellwords.shellwords(opts) 50: words.each_with_index do |word,idx| 51: if word == "-c" 52: return "--config=#{words[idx + 1]}" 53: elsif word == "--config" 54: return "--config=#{words[idx + 1]}" 55: elsif word =~ /\-c=/ 56: return word 57: elsif word =~ /\-\-config=/ 58: return word 59: end 60: end 61: 62: return "" 63: end
Returns an array of applications found in the lib dirs
# File lib/mcollective/applications.rb, line 25 25: def self.list 26: load_config 27: 28: applist = [] 29: 30: Config.instance.libdir.each do |libdir| 31: applicationdir = "#{libdir}/mcollective/application" 32: next unless File.directory?(applicationdir) 33: 34: Dir.entries(applicationdir).grep(/\.rb$/).each do |application| 35: applist << File.basename(application, ".rb") 36: end 37: end 38: 39: applist 40: rescue Exception => e 41: STDERR.puts "Failed to generate application list: #{e.class}: #{e}" 42: exit 1 43: end
# File lib/mcollective/applications.rb, line 15 15: def self.load_application(appname) 16: return if PluginManager.include?("#{appname}_application") 17: 18: load_config 19: 20: PluginManager.loadclass "MCollective::Application::#{appname.capitalize}" 21: PluginManager << {:type => "#{appname}_application", :class => "MCollective::Application::#{appname.capitalize}"} 22: 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 82 82: def self.load_config 83: return if Config.instance.configured 84: 85: original_argv = ARGV.clone 86: original_extra_opts = ENV["MCOLLECTIVE_EXTRA_OPTS"].clone rescue nil 87: configfile = nil 88: 89: parser = OptionParser.new 90: parser.on("--config CONFIG", "-c", "Config file") do |f| 91: configfile = f 92: end 93: 94: parser.program_name = $0 95: 96: parser.on("--help") 97: 98: # avoid option parsers own internal version handling that sux 99: parser.on("-v", "--verbose") 100: 101: if original_extra_opts 102: begin 103: # optparse will parse the whole ENV in one go and refuse 104: # to play along with the retry trick I do below so in 105: # order to handle unknown options properly I parse out 106: # only -c and --config deleting everything else and 107: # then restore the environment variable later when I 108: # am done with it 109: ENV["MCOLLECTIVE_EXTRA_OPTS"] = filter_extra_options(ENV["MCOLLECTIVE_EXTRA_OPTS"].clone) 110: parser.environment("MCOLLECTIVE_EXTRA_OPTS") 111: rescue Exception => e 112: Log.error("Failed to parse MCOLLECTIVE_EXTRA_OPTS: #{e}") 113: end 114: 115: ENV["MCOLLECTIVE_EXTRA_OPTS"] = original_extra_opts.clone 116: end 117: 118: begin 119: parser.parse! 120: rescue OptionParser::InvalidOption => e 121: retry 122: end 123: 124: ARGV.clear 125: original_argv.each {|a| ARGV << a} 126: 127: configfile = Util.config_file_for_user unless configfile 128: 129: Config.instance.loadconfig(configfile) 130: end