lib/kafo/configuration.rb in kafo-0.6.12 vs lib/kafo/configuration.rb in kafo-0.7.0

- old
+ new

@@ -1,45 +1,45 @@ # encoding: UTF-8 require 'yaml' require 'tmpdir' require 'kafo/puppet_module' require 'kafo/password_manager' +require 'kafo/color_scheme' module Kafo class Configuration attr_reader :config_file, :answer_file - def self.colors_possible? - !`which tput 2> /dev/null`.empty? && `tput colors`.to_i > 0 - end - DEFAULT = { + :name => '', + :description => '', :log_dir => '/var/log/kafo', :log_name => 'configuration.log', :log_level => 'info', :no_prefix => false, :mapping => {}, :answer_file => './config/answers.yaml', :installer_dir => '.', - :modules_dir => './modules', + :module_dirs => ['./modules'], :default_values_dir => '/tmp', - :colors => Configuration.colors_possible?, + :colors => Kafo::ColorScheme.colors_possible?, :color_of_background => :dark, :hook_dirs => [], :custom => {}, :low_priority_modules => [], + :verbose_log_level => 'info' } def initialize(file, persist = true) @config_file = file @persist = persist configure_application @logger = KafoConfigure.logger @answer_file = app[:answer_file] begin - @data = YAML.load_file(@answer_file) + @data = load_yaml_file(@answer_file) rescue Errno::ENOENT => e puts "No answer file at #{@answer_file} found, can not continue" KafoConfigure.exit(:no_answer_file) end @@ -60,17 +60,19 @@ end def app @app ||= begin begin - configuration = YAML.load_file(@config_file) + configuration = load_yaml_file(@config_file) rescue => e configuration = {} end result = DEFAULT.merge(configuration || {}) result[:password] ||= PasswordManager.new.password + result[:module_dirs] = result[:modules_dir] || result[:module_dirs] + result.delete(:modules_dir) result end end def get_custom(key) @@ -80,15 +82,35 @@ def set_custom(key, value) custom_storage[key.to_sym] = value end def modules - @modules ||= @data.keys.map { |mod| PuppetModule.new(mod).parse }.sort + @modules ||= @data.keys.map { |mod| PuppetModule.new(mod, KafoParsers::PuppetModuleParser, self).parse }.sort end + def root_dir + File.expand_path(app[:installer_dir]) + end + + def check_dirs + [app[:check_dirs] || File.join(root_dir, 'checks')].flatten + end + + def module_dirs + [app[:module_dirs] || (app[:installer_dir] + '/modules')].flatten.map { |dir| File.expand_path(dir) } + end + + def gem_root + File.join(File.dirname(__FILE__), '../../') + end + + def kafo_modules_dir + app[:kafo_modules_dir] || (gem_root + '/modules') + end + def add_module(name) - mod = PuppetModule.new(name).parse + mod = PuppetModule.new(name, KafoParsers::PuppetModuleParser, self).parse unless modules.map(&:name).include?(mod.name) mod.enable @modules << mod end end @@ -96,17 +118,29 @@ def add_mapping(module_name, mapping) app[:mapping][module_name] = mapping save_configuration(app) end + def migrate_configuration(from_config, options={}) + keys_to_skip = options.fetch(:skip, []) + keys = [:log_dir, :log_name, :log_level, :no_prefix, :default_values_dir, + :colors, :color_of_background, :custom, :password, :verbose_log_level] + keys += options.fetch(:with, []) + keys.each do |key| + next if keys_to_skip.include?(key) + app[key] = from_config.app[key] + end + save_configuration(app) + end + def params_default_values @params_default_values ||= begin @logger.debug "Creating tmp dir within #{app[:default_values_dir]}..." temp_dir = Dir.mktmpdir(nil, app[:default_values_dir]) KafoConfigure.exit_handler.register_cleanup_path temp_dir @logger.info 'Loading default values from puppet modules...' - command = PuppetCommand.new("$temp_dir=\"#{temp_dir}\" #{includes} dump_values(#{params})").append('2>&1').command + command = PuppetCommand.new("$temp_dir=\"#{temp_dir}\" #{includes} dump_values(#{params_to_dump})", ['--noop'], self).append('2>&1').command result = `#{command}` @logger.debug result unless $?.exitstatus == 0 log = app[:log_dir] + '/' + app[:log_name] puts "Could not get default values, check log file at #{log} for more information" @@ -114,11 +148,11 @@ @logger.error result @logger.error 'Could not get default values, cannot continue' KafoConfigure.exit(:defaults_error) end @logger.info "... finished" - YAML.load_file(File.join(temp_dir, 'default_values.yaml')) + load_yaml_file(File.join(temp_dir, 'default_values.yaml')) end end # if a value is a true we return empty hash because we have no specific options for a # particular puppet module @@ -131,11 +165,11 @@ value = @data[mod.is_a?(String) ? mod : mod.identifier] !!value || value.is_a?(Hash) end def config_header - files = [app[:config_header_file], File.join(KafoConfigure.gem_root, '/config/config_header.txt')].compact + files = [app[:config_header_file], File.join(gem_root, '/config/config_header.txt')].compact file = files.select { |f| File.exists?(f) }.first @config_header ||= file.nil? ? '' : File.read(file) end def store(data, file = nil) @@ -143,30 +177,113 @@ FileUtils.touch filename File.chmod 0600, filename File.open(filename, 'w') { |file| file.write(config_header + format(YAML.dump(data))) } end + def params + @params ||= modules.map(&:params).flatten + end + + def param(mod, name) + params.detect { |p| p.name == name && p.module.name == mod } + end + + def preset_defaults_from_puppet + # set values based on default_values + params.each do |param| + param.set_default(params_default_values) + end + end + + def preset_defaults_from_yaml + # set values based on YAML + params.each do |param| + param.set_value_by_config(self) + end + end + + def preset_defaults_from_other_config(other_config) + params_changed(other_config).each do |par| + param(par.module.class_name, par.name).value = other_config.param(par.module.class_name, par.name).value + end + end + + def params_changed(old_config) + # finds params that had different value in the old config + params.select do |par| + next unless par.module.enabled? + old_param = old_config.param(par.module.class_name, par.name) + old_param && old_param.value != par.value + end + end + + def params_missing(old_config) + # finds params that are present but will be missing in the new config + old_config.params.select do |par| + next if !par.module.enabled? || !module_enabled?(par.module.name) + param(par.module.class_name, par.name).nil? + end + end + + def temp_config_file + @temp_config_file ||= "/tmp/kafo_answers_#{rand(1_000_000)}.yaml" + end + + def log_file + File.join(app[:log_dir], app[:log_name]) + end + + def log_exists? + File.exists?(log_file) && File.size(log_file) > 0 + end + + def answers + @data + end + + def run_migrations + migrations = Kafo::Migrations.new(migrations_dir) + @app, @data = migrations.run(app, answers) + if migrations.migrations.count > 0 + @modules = nil # force the lazy loaded modules to reload next time they are used + save_configuration(app) + store(answers) + migrations.store_applied + @logger.info("#{migrations.migrations.count} migration/s were applied. Updated configuration was saved.") + end + end + + def migrations_dir + @config_file.gsub(/\.yaml$/, '.migrations') + end + private def custom_storage app[:custom] end def includes modules.map do |mod| - params_file = File.join(KafoConfigure.modules_dir, mod.params_path) - @logger.debug "checking presence of #{params_file}" - File.exist?(params_file) ? "include #{mod.dir_name}::#{mod.params_class_name}" : nil + module_dir = module_dirs.find do |dir| + params_file = File.join(dir, mod.params_path) + @logger.debug "checking presence of #{params_file}" + File.exist?(params_file) + end + module_dir ? "include #{mod.dir_name}::#{mod.params_class_name}" : nil end.uniq.compact.join(' ') end - def params - params = modules.map(&:params).flatten - params = params.select { |p| p.default != 'UNSET' } - params.map { |param| "#{param.dump_default}" }.join(',') + def params_to_dump + parameters = params.select { |p| p.default != 'UNSET' } + parameters.map { |param| "#{param.dump_default}" }.join(',') end def format(data) data.gsub('!ruby/sym ', ':') + end + + def load_yaml_file(filename) + YAML.load_file(filename) end end end