Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Break params into three distinct files #339

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 84 additions & 36 deletions lib/kafo/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,42 @@ class Configuration
attr_reader :config_file, :answer_file, :scenario_id

DEFAULT = {
ScenarioOption::NAME => '',
ScenarioOption::DESCRIPTION => '',
ScenarioOption::ENABLED => true,
ScenarioOption::LOG_DIR => '/var/log/kafo',
ScenarioOption::LOG_OWNER => nil,
ScenarioOption::LOG_GROUP => nil,
ScenarioOption::STORE_DIR => '',
ScenarioOption::LOG_NAME => 'configuration.log',
ScenarioOption::LOG_LEVEL => 'notice',
ScenarioOption::NO_PREFIX => false,
ScenarioOption::MAPPING => {},
ScenarioOption::ANSWER_FILE => './config/answers.yaml',
ScenarioOption::INSTALLER_DIR => '.',
ScenarioOption::MODULE_DIRS => ['./modules'],
ScenarioOption::COLORS => Kafo::ColorScheme.colors_possible?,
ScenarioOption::COLOR_OF_BACKGROUND => :dark,
ScenarioOption::HOOK_DIRS => [],
ScenarioOption::CHECK_DIRS => nil,
ScenarioOption::CUSTOM => {},
ScenarioOption::FACTS => {},
ScenarioOption::LOW_PRIORITY_MODULES => [],
ScenarioOption::VERBOSE => false,
ScenarioOption::VERBOSE_LOG_LEVEL => 'notice',
ScenarioOption::SKIP_PUPPET_VERSION_CHECK => false,
ScenarioOption::PARSER_CACHE_PATH => nil,
ScenarioOption::IGNORE_UNDOCUMENTED => nil,
ScenarioOption::ORDER => nil,
ScenarioOption::HIERA_CONFIG => nil,
ScenarioOption::KAFO_MODULES_DIR => nil,
ScenarioOption::CONFIG_HEADER_FILE => nil,
ScenarioOption::DONT_SAVE_ANSWERS => nil,
ScenarioOption::NAME => '',
ScenarioOption::DESCRIPTION => '',
ScenarioOption::ENABLED => true,
ScenarioOption::LOG_DIR => '/var/log/kafo',
ScenarioOption::LOG_OWNER => nil,
ScenarioOption::LOG_GROUP => nil,
ScenarioOption::STORE_DIR => '',
ScenarioOption::LOG_NAME => 'configuration.log',
ScenarioOption::LOG_LEVEL => 'notice',
ScenarioOption::NO_PREFIX => false,
ScenarioOption::MAPPING => {},
ScenarioOption::ANSWER_FILE => './config/answers.yaml',
ScenarioOption::INSTALLER_DIR => '.',
ScenarioOption::MODULE_DIRS => ['./modules'],
ScenarioOption::COLORS => Kafo::ColorScheme.colors_possible?,
ScenarioOption::COLOR_OF_BACKGROUND => :dark,
ScenarioOption::HOOK_DIRS => [],
ScenarioOption::CHECK_DIRS => nil,
ScenarioOption::CUSTOM => {},
ScenarioOption::FACTS => {},
ScenarioOption::LOW_PRIORITY_MODULES => [],
ScenarioOption::VERBOSE => false,
ScenarioOption::VERBOSE_LOG_LEVEL => 'notice',
ScenarioOption::SKIP_PUPPET_VERSION_CHECK => false,
ScenarioOption::PARSER_CACHE_PATH => nil,
ScenarioOption::IGNORE_UNDOCUMENTED => nil,
ScenarioOption::ORDER => nil,
ScenarioOption::HIERA_CONFIG => nil,
ScenarioOption::KAFO_MODULES_DIR => nil,
ScenarioOption::CONFIG_HEADER_FILE => nil,
ScenarioOption::DONT_SAVE_ANSWERS => nil,
ScenarioOption::PARAMS_FILES => {
ScenarioOption::DEFAULT_PARAMS_FILE => nil,
ScenarioOption::USER_PARAMS_FILE => nil,
ScenarioOption::SCENARIO_DEFAULT_PARAMS_FILE => nil,
},
}

def self.get_scenario_id(filename)
Expand Down Expand Up @@ -128,9 +133,16 @@ def has_custom_fact?(key)
end

def modules
@modules ||= begin
register_data_types
@data.keys.map { |mod| PuppetModule.new(mod, configuration: self).parse }.sort
if scenario_params_file
@modules ||= begin
register_data_types
scenario_params.keys.map { |mod| PuppetModule.new(mod, configuration: self).parse }.sort
end
else
@modules ||= begin
register_data_types
@data.keys.map { |mod| PuppetModule.new(mod, configuration: self).parse }.sort
end
end
end

Expand Down Expand Up @@ -247,11 +259,11 @@ def config_header
@config_header ||= file.nil? ? '' : File.read(file)
end

def store(data, file = nil)
def store(data, file = nil, header: config_header)
filename = file || answer_file
FileUtils.touch filename
File.chmod 0600, filename
File.open(filename, 'w') { |f| f.write(config_header + format(YAML.dump(data))) }
File.open(filename, 'w') { |f| f.write((header ? header : '') + format(YAML.dump(data))) }
end

def params
Expand Down Expand Up @@ -320,6 +332,42 @@ def answers
@data
end

def params_files
app[ScenarioOption::PARAMS_FILES]
end

def default_params_file
params_files[ScenarioOption::DEFAULT_PARAMS_FILE]
end

def scenario_params_file
params_files[ScenarioOption::SCENARIO_DEFAULT_PARAMS_FILE]
end

def user_params_file
params_files[ScenarioOption::USER_PARAMS_FILE]
end

def scenario_params
return unless scenario_params_file

begin
load_yaml_file(scenario_params_file)
rescue Errno::ENOENT
{}
end
end

def user_params
return unless user_params_file

begin
load_yaml_file(user_params_file)
rescue Errno::ENOENT
{}
end
end

def run_migrations
migrations = Kafo::Migrations.new(migrations_dir)
@app, @data = migrations.run(app, answers)
Expand Down
69 changes: 66 additions & 3 deletions lib/kafo/kafo_configure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,45 @@ def initialize(*args)

self.class.hooking.execute(:init)
set_parameters # here the params gets parsed and we need app config populated
migrate_answers_to_user_params_file
set_options
end

def migrate_answers_to_user_params_file
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my approach to how to migrate an answers file to this new approach. Right now this is "automatic" if an answers file is found and no user params file. This could instead also be triggered by setting a version in the configuration file or some other flag.

return unless config.app[:answer_file]
return if config.user_params_file.nil?
return if File.exist?(config.user_params_file)

enabled_modules = config.modules.select(&:enabled?)
default_params = Hash[enabled_modules.map { |mod| [mod.identifier, mod.default_params_hash] }]
default_params = default_params.reject { |key, value| !value.is_a?(Hash) }

user_params = Hash[config.modules.map { |mod| [mod.identifier, {}] }]

config.answers.each do |puppet_class, values|
if values.is_a?(Hash)
values.each do |param, value|
user_params[puppet_class][param] = value unless default_params[puppet_class][param] == value
end
else
user_params[puppet_class] = values unless default_params[puppet_class] == values
end
end

config.scenario_params.each do |puppet_class, values|
if values.is_a?(Hash)
values.each do |param, value|
user_params[puppet_class].delete(param) if user_params[puppet_class][param] == value
end
else
user_params.delete(puppet_class) if user_params[puppet_class] == values
end
end

config.store(user_params, config.user_params_file)
config.app[:answer_file].delete
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the notion of the answers file from the config but do not delete the answers file. We can leave that on the system as a safety mechanism and user reference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean that there remains an answers file on disk, which over time gets out of date, as we don't update it anymore? Or do I miss-read the code and it's still getting updated.

I'm mostly concerned that -- while we preach that the file is not to be consumed -- it is used by other tools to look things up, and could lead to unexpected results.

If it's not getting updated anymore, I think we should consider renaming it to something like asnwers.yml.obsolete or so, so that users still can manually read it, but tools that expect a certain path, fail explicitly.

end

def config
self.class.config
end
Expand Down Expand Up @@ -210,6 +246,8 @@ def execute
self.class.hooking.execute(:pre_commit)
unless dont_save_answers? || noop?
config.configure_application
store_default_params
store_user_params
store_params
self.class.scenario_manager.link_last_scenario(self.class.config_file) if self.class.scenario_manager.configured?
end
Expand Down Expand Up @@ -253,8 +291,8 @@ def modules
config.modules.sort
end

def module(name)
modules.detect { |m| m.name == name }
def module(identifier)
modules.detect { |m| m.identifier == identifier }
end

def param(mod, name)
Expand Down Expand Up @@ -457,6 +495,7 @@ def parse_cli_arguments
self.class.exit(:missing_argument)
end
param.value = cli_value unless cli_value.nil?
param.user_value = cli_value unless cli_value.nil?
end
end

Expand All @@ -466,7 +505,31 @@ def argument_missing?(value)

def store_params(file = nil)
data = Hash[config.modules.map { |mod| [mod.identifier, mod.enabled? ? mod.params_hash : false] }]
config.store(data, file)
config.store(data, config.answer_file)
end

def store_default_params
return unless config.default_params_file

data = Hash[enabled_params.map { |param| [param.identifier, param.default] }]
config.store(data, config.default_params_file, header: nil)
end

def store_user_params
return unless config.user_params_file
user_params = {}

config.scenario_params.each do |mod_name, params|
mod = self.module(mod_name)

next if mod.user_params_hash == false && params == false
next if mod.user_params_hash.empty? && params != false
next if mod.user_params_hash == params

user_params[mod.identifier] = mod.user_params_hash
end

config.store(user_params, config.user_params_file)
end

def validate_all(logging = true)
Expand Down
2 changes: 1 addition & 1 deletion lib/kafo/param.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Param
UNSET_VALUES = ['UNSET', :undef]

attr_reader :name, :module, :type, :manifest_default
attr_accessor :doc, :value_set, :condition
attr_accessor :doc, :value_set, :condition, :user_value
attr_writer :groups

def initialize(builder, name, type)
Expand Down
10 changes: 10 additions & 0 deletions lib/kafo/puppet_module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ def params_hash
Hash[params.map { |param| [param.name, param.value] }]
end

def default_params_hash
Hash[params.map { |param| [param.name, param.default] }]
end

def user_params_hash
return false unless enabled?
user_params = params.reject { |param| param.user_value.nil? }
Hash[user_params.map { |param| [param.name, param.user_value] }]
end

def <=>(other)
@configuration.app[:low_priority_modules].each do |module_name|
return 1 if self.name.include?(module_name) && !other.name.include?(module_name)
Expand Down
12 changes: 12 additions & 0 deletions lib/kafo/scenario_option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ class ScenarioOption
# Path to answer file, if the file does not exist a $pwd/config/answers.yaml is used as a fallback
ANSWER_FILE = :answer_file

# Hash containing different params files and their paths
PARAMS_FILES = :params_files

# Path to file that will store the default params
DEFAULT_PARAMS_FILE = :default_params_file

# Path to file that will store the user input params from the CLI
USER_PARAMS_FILE = :user_params_file

# Path to file that will store the user input params from the CLI
SCENARIO_DEFAULT_PARAMS_FILE = :scenario_default_params_file

# Enable colors? If you don't touch this, we'll autodetect terminal capabilities
COLORS = :colors
# Color scheme, we support :bright and :dark (first is better for white background, dark for black background)
Expand Down