lib/kafo/kafo_configure.rb in kafo-0.1.0 vs lib/kafo/kafo_configure.rb in kafo-0.2.0

- old
+ new

@@ -11,30 +11,39 @@ require 'kafo/puppet_command' require 'kafo/progress_bar' class KafoConfigure < Clamp::Command include StringHelper - attr_reader :logger class << self attr_accessor :config, :root_dir, :config_file, :gem_root, :temp_config_file, - :modules_dir, :kafo_modules_dir, :verbose + :modules_dir, :kafo_modules_dir, :verbose, :app_options, :logger end def initialize(*args) + self.class.logger = Logger.new self.class.config_file = config_file self.class.config = Configuration.new(self.class.config_file) self.class.root_dir = File.expand_path(self.class.config.app[:installer_dir]) modules_dir = self.class.config.app[:module_dir] || (self.class.config.app[:installer_dir] + '/modules') self.class.modules_dir = File.expand_path(modules_dir) self.class.gem_root = File.join(File.dirname(__FILE__), '../../') self.class.kafo_modules_dir = self.class.config.app[:kafo_modules_dir] || (self.class.gem_root + '/modules') - Logger.setup - @logger = Logging.logger.root @progress_bar = nil + super - set_parameters + + set_app_options + allowed = self.class.app_options.map(&:switches).flatten + allowed.map! { |s| s.include?('[no-]') ? [s.sub('[no-]', ''), s.sub('[no-]', 'no-')] : s }.flatten! + # we need to parse app config params using clamp even before run method does it + # so we limit parsing only to app config options (because of --help and later defined params) + parse ARGV.select { |a| a =~ /([a-zA-Z0-9_-]*)([= ].*)?/ && allowed.include?($1) } + parse_app_arguments + Logger.setup + + set_parameters # here the params gets parsed and we need app config populated set_options end def config self.class.config @@ -43,13 +52,13 @@ def execute catch :exit do parse_cli_arguments if (self.class.verbose = verbose?) - logger.appenders = logger.appenders << ::Logging.appenders.stdout(:layout => Logger::COLOR_LAYOUT) + Logger.setup_verbose else - @progress_bar = ProgressBar.new + @progress_bar = self.class.config.app[:colors] ? ProgressBars::Colored.new : ProgressBars::BlackWhite.new end unless SystemChecker.check puts "Your system does not meet configuration criteria" exit(:invalid_system) @@ -109,19 +118,25 @@ else raise "Unknown code #{code}" end end + def self.app_option(*args, &block) + self.app_options ||= [] + self.app_options.push self.option(*args, &block) + self.app_options.last + end + def params @params ||= modules.map(&:params).flatten rescue ModuleName => e puts e exit(:unknown_module) end def modules - config.modules + config.modules.sort end def module(name) modules.detect { |m| m.name == name} end @@ -130,10 +145,14 @@ params.detect { |p| p.name == name && p.module.name == mod } end private + def logger + self.class.logger + end + def exit(code) self.class.exit(code) end def set_parameters @@ -143,31 +162,51 @@ # set values based on YAML param.set_value_by_config(config) end end - def set_options - self.class.option ['-i', '--interactive'], :flag, 'Run in interactive mode' - self.class.option ['-v', '--verbose'], :flag, 'Display log on STDOUT instead of progressbar' - self.class.option ['-n', '--noop'], :flag, 'Run puppet in noop mode?', :default => false - self.class.option ['-d', '--dont-save-answers'], :flag, 'Skip saving answers to answers.yaml?', - :default => !!config.app[:dont_save_answers] + def set_app_options + self.class.app_option ['--[no-]colors'], :flag, 'Use color output on STDOUT', + :default => !!config.app[:colors] + self.class.app_option ['-d', '--dont-save-answers'], :flag, 'Skip saving answers to answers.yaml?', + :default => !!config.app[:dont_save_answers] + self.class.app_option '--ignore-undocumented', :flag, 'Ignore inconsistent parameters documentation', + :default => false + self.class.app_option ['-i', '--interactive'], :flag, 'Run in interactive mode' + self.class.app_option '--log-level', 'LEVEL', 'Log level for log file output', + :default => config.app[:log_level] + self.class.app_option ['-n', '--noop'], :flag, 'Run puppet in noop mode?', + :default => false + self.class.app_option ['-v', '--verbose'], :flag, 'Display log on STDOUT instead of progressbar' + self.class.app_option ['-l', '--verbose-log-level'], 'LEVEL', 'Log level for verbose mode output', + :default => 'info' + end - config.modules.each do |mod| + def set_options + modules.each do |mod| self.class.option d("--[no-]enable-#{mod.name}"), :flag, "Enable puppet module #{mod.name}?", :default => mod.enabled? end - params.each do |param| + params.sort.each do |param| doc = param.doc.nil? ? 'UNDOCUMENTED' : param.doc.join("\n") self.class.option parametrize(param), '', doc, :default => param.value, :multivalued => param.multivalued? end end + def parse_app_arguments + self.class.app_options.each do |option| + name = option.attribute_name + name = "#{name}?" if option.flag? + value = send(name) + config.app[name.to_sym] = value.nil? ? option.default_value : value + end + end + def parse_cli_arguments # enable/disable modules according to CLI config.modules.each { |mod| send("enable_#{mod.name}?") ? mod.enable : mod.disable } # set values coming from CLI arguments @@ -186,18 +225,19 @@ def validate_all(logging = true) logger.info 'Running validation checks' results = params.map do |param| result = param.valid? - logger.error "Parameter #{param.name} invalid" if logging && !result + progress_log(:error, "Parameter #{with_prefix(param)} invalid") if logging && !result result end results.all? end def run_installation exit_code = 0 + exit_status = nil options = [ '--verbose', '--debug', '--color=false', '--show_diff', @@ -207,33 +247,37 @@ begin command = PuppetCommand.new('include kafo_configure', options).command PTY.spawn(command) do |stdin, stdout, pid| begin stdin.each do |line| - puppet_log(*puppet_parse(line)) + progress_log(*puppet_parse(line)) @progress_bar.update(line) if @progress_bar end - rescue Errno::EIO - if PTY.respond_to?(:check) # ruby >= 1.9.2 - exit_code = PTY.check(pid, true).exitstatus - else # ruby < 1.9.2 - Process.wait(pid) rescue Errno::ECHILD - exit_code = $?.exitstatus + rescue Errno::EIO # we reach end of input + exit_status = PTY.check(pid, true) if PTY.respond_to?(:check) # ruby >= 1.9.2 + if exit_status.nil? # process is still running or we have old ruby so we don't know + begin + Process.wait(pid) + rescue Errno::ECHILD # process could exit meanwhile so we rescue + end + exit_code = $?.exitstatus # after check $? should be set correctly + else # this should never happen (unless they change PTY.check behavior) in new ruby + exit_code = exit_code.exitstatus end end end - rescue PTY::ChildExited => e + rescue PTY::ChildExited => e # could be raised by Process.wait on older ruby or by PTY.check exit_code = e.status.exitstatus end @progress_bar.close if @progress_bar logger.info "Puppet has finished, bye!" FileUtils.rm(temp_config_file, :force => true) exit(exit_code) end - def puppet_log(method, message) - @progress_bar.print ANSI::Code.red { message + "\n" } if method == :error && @progress_bar - Logging.logger['puppet'].send(method, message) + def progress_log(method, message) + @progress_bar.print_error(message + "\n") if method == :error && @progress_bar + logger.send(method, message) end def puppet_parse(line) method, message = case when line =~ /^Error:(.*)/i || line =~ /^Err:(.*)/i