Project

General

Profile

« Previous | Next » 

Revision 2f1c6b5b

Added by Marc Dequènes almost 14 years ago

  • ID 2f1c6b5bfb3ebbadde902db6e5d540530976de36

[evol] configuration defaults and schema checking (closes 21)

View differences:

lib/cyborghood/base/config.rb
#++
require 'singleton'
require 'yaml'
require 'cyborghood/base/config_setup'
require 'yaml'
require 'kwalify'
module CyborgHood
class Config
......
def self.load(name = nil)
# load all config parts
config = fetch_config
g_config_raw = load_config_raw()
g_def = parse('config', 'global', g_config_raw)
g_default_config = load_default_config()
config = merge_into_default_config(g_default_config, g_def)
unless name.nil?
config_spc = fetch_config(name)
config = merge_configs(config, config_spc) if config_spc
config_spc_raw = load_config_raw(name)
spc_def = parse('config', name, config_spc_raw)
default_config_spc = load_default_config(name)
spc_config = merge_into_default_config(default_config_spc, spc_def)
config = merge_into_default_config(config, spc_config)
end
# create config object for easier access
......
end
end
private
protected
def self.merge_into_default_config(conf_default, conf)
new_conf = conf_default.dup
conf.each_pair do |k, v|
if conf_default.has_key?(k) and conf_default[k].is_a?(Hash) and v.is_a?(Hash)
new_conf[k] = merge_into_default_config(conf_default[k], v)
elsif conf_default.has_key?(k) and conf_default[k].is_a?(Hash) and v.nil?
new_conf[k] = conf_default[k]
else
new_conf[k] = v
end
end
return new_conf
end
def self.fetch_config(name = nil)
def self.load_config_raw(name = nil)
begin
if name.nil?
filename = CONFFILE_GLOBAL
else
filename = sprintf(CONFFILE_BOT, name)
filename = CONFFILE_BOT % name
end
filepath = File.join(File.expand_path(CFG_DIR), filename)
str = File.read(filepath)
YAML.load(str)
File.read(filepath)
rescue
logger.fatal "Problems fetching configuration file '" + filepath + "': " + $!
exit 1
end
end
def self.merge_configs(conf1, conf2)
new_conf = conf1.dup
conf2.each_pair do |k, v|
if conf1.has_key?(k) and conf1[k].is_a?(Hash) and v.is_a?(Hash)
new_conf[k] = merge_configs(conf1[k], v)
def self.parse(def_name, type, def_data_raw, validate = true, extra_data = nil)
schema = load_schema(type)
if validate
validator_klass = case type
when 'global'
GlobalValidator
else
new_conf[k] = v
klass_name = type.capitalize + "Validator"
if self.const_defined? klass_name
self.const_get klass_name
else
CyborgHoodValidator
end
end
validator = validator_klass.new(schema)
validator.extra_data = extra_data
else
validator = nil
end
# validate config with schema
parser = Kwalify::Yaml::Parser.new(validator)
def_data = parser.parse(def_data_raw, :filename => def_name, :untabify => true)
raise_if_validation_errors("#{type.capitalize} '#{def_name}'", parser.errors)
def_data
rescue
logger.fatal "Problems parsing %s file for '%s': %s" % [def_name, type, $!]
exit 1
end
def self.load_default_config(type = "global")
filename = File.join(DATA_DIR, "default_config", type + ".yaml")
default_config_raw = File.read(filename)
default_config = parse(':defaults:', type, default_config_raw, false)
default_config
rescue
logger.fatal "Could not load default config for '%s': %s" % [type, $!]
exit 1
end
def self.load_schema(type = "global")
schema_file = File.join(DATA_DIR, "schema", type + ".yaml")
schema = YAML.load_file(schema_file)
# validate schema
metavalidator = Kwalify::MetaValidator.instance
errors = metavalidator.validate(schema)
raise_if_validation_errors("'#{type}' schema", errors)
schema
rescue
logger.fatal "Could not load schema for '%s': %s" % [type, $!]
exit 1
end
protected
class CyborgHoodValidator < Kwalify::Validator
attr_accessor :extra_data
## hook method called by Validator#validate()
def validate_hook(value, rule, path, errors)
msg_list = []
validate_hook_in(value, rule, path, msg_list)
msg_list.each do |msg|
errors << Kwalify::ValidationError.new(msg, path)
end
end
def validate_hook_in(value, rule, path, msg_list)
end
end
class GlobalValidator < CyborgHoodValidator
def validate_hook_in(value, rule, path, msg_list)
case rule.name
when 'LogPath'
unless File.directory? value
msg_list << "Log path must be an existing directory"
end
end
end
end
def self.raise_if_validation_errors(name, errors)
if errors and not errors.empty?
err_msg = []
for e in errors
err_msg << "[#{e.path}] #{e.message}"
end
logger.fatal "%s is not valid:\n%s" % [name, err_msg.join("\n")]
exit 1
end
return new_conf
end
end
end

Also available in: Unified diff