Added config schema right into Configuration

This commit is contained in:
Maxim Kulkin 2013-11-07 17:36:37 +04:00
parent 452648b434
commit e77e3c88d9
3 changed files with 149 additions and 40 deletions

View File

@ -1,5 +1,7 @@
import string
from rubick.schema import TypeValidatorRegistry, InvalidValueError
class ConfigurationSection(object):
@ -74,12 +76,14 @@ class ConfigurationWrapper(object):
class Configuration(object):
def __init__(self):
def __init__(self, schema=None):
super(Configuration, self).__init__()
self._defaults = dict()
self._normal = dict()
self._cli = dict()
self._env = dict()
self._cache = dict()
self.schema = schema
def _normalize_name(self, name):
if name.find('.') == -1:
@ -95,8 +99,11 @@ class Configuration(object):
return '%s.%s' % (section, param)
def get(self, name, default=None, raw=False, _state=[]):
section, name = self._normalize_name(name)
def get(self, fullname, default=None, raw=False, _state=[]):
if not raw and fullname in self._cache:
return self._cache[fullname]
section, name = self._normalize_name(fullname)
if section in self._cli and name in self._cli[section]:
value = self._cli[section][name]
@ -116,9 +123,43 @@ class Configuration(object):
return value
tmpl = string.Template(value)
return (
tmpl.safe_substitute(ConfigurationWrapper(self, _state + [name]))
)
value = tmpl.safe_substitute(
ConfigurationWrapper(self, _state + [name]))
if self.schema:
param_schema = self.schema.get_parameter(name, section=section)
type_validator = TypeValidatorRegistry.get_validator(
param_schema.type)
type_validation_result = type_validator.validate(value)
if not isinstance(type_validation_result, InvalidValueError):
value = type_validation_result
self._cache[fullname] = value
return value
def validate(self, fullname):
if not self.schema:
return None
section, name = self._normalize_name(fullname)
value = self.get(fullname, raw=True)
tmpl = string.Template(value)
value = tmpl.safe_substitute(
ConfigurationWrapper(self, [name]))
param_schema = self.schema.get_parameter(name, section=section)
type_validator = TypeValidatorRegistry.get_validator(
param_schema.type)
type_validation_result = type_validator.validate(value)
if not isinstance(type_validation_result, InvalidValueError):
return None
return type_validation_result
def contains(self, name, ignoreDefault=False):
section, name = self._normalize_name(name)
@ -148,26 +189,40 @@ class Configuration(object):
(section in self._defaults and name in self._defaults[section])
)
def set_env(self, name, value):
section, name = self._normalize_name(name)
def set_env(self, fullname, value):
section, name = self._normalize_name(fullname)
self._env.setdefault(section, {})[name] = value
def set_cli(self, name, value):
section, name = self._normalize_name(name)
self._invalidate_cache(fullname)
def set_cli(self, fullname, value):
section, name = self._normalize_name(fullname)
self._cli.setdefault(section, {})[name] = value
def set_default(self, name, value):
section, name = self._normalize_name(name)
self._invalidate_cache(fullname)
def set_default(self, fullname, value):
section, name = self._normalize_name(fullname)
self._defaults.setdefault(section, {})[name] = value
def set(self, name, value):
section, name = self._normalize_name(name)
self._invalidate_cache(fullname)
def set(self, fullname, value):
section, name = self._normalize_name(fullname)
self._normal.setdefault(section, {})[name] = value
self._invalidate_cache(fullname)
def _invalidate_cache(self, fullname):
# We need to invalidate not only value of given parameter
# but also values that depend on that parameter
# Since this is hard, we'll just invalidate all cached values
self._cache = dict()
def section(self, section):
return ConfigurationSection(self, section)

View File

@ -133,7 +133,7 @@ class OpenstackComponent(Service):
return self._parse_config_resources(self.config_files, schema)
def _parse_config_resources(self, resources, schema=None):
config = Configuration()
config = Configuration(schema)
# Apply defaults
if schema:
@ -147,21 +147,14 @@ class OpenstackComponent(Service):
for resource in reversed(resources):
self._parse_config_file(
Mark(resource.path),
resource.contents,
config,
schema,
Mark(resource.path), resource.contents, config, schema,
issue_reporter=resource)
return config
def _parse_config_file(
self,
base_mark,
config_contents,
config=Configuration(),
schema=None,
issue_reporter=None):
def _parse_config_file(self, base_mark, config_contents,
config=Configuration(), schema=None,
issue_reporter=None):
if issue_reporter:
def report_issue(issue):
issue_reporter.report_issue(issue)
@ -250,9 +243,8 @@ class OpenstackComponent(Service):
type_validation_result.message)
report_issue(type_validation_result)
config.set(
parameter_fullname,
parameter.value.text)
config.set(parameter_fullname,
parameter.value.text)
else:
value = type_validation_result
@ -283,16 +275,6 @@ class KeystoneComponent(OpenstackComponent):
name = 'keystone'
class GlanceApiComponent(OpenstackComponent):
component = 'glance_api'
name = 'glance-api'
class GlanceRegistryComponent(OpenstackComponent):
component = 'glance_registry'
name = 'glance-registry'
class NovaApiComponent(OpenstackComponent):
component = 'nova'
name = 'nova-api'

View File

@ -1,6 +1,8 @@
import unittest
from rubick.config_model import Configuration
from rubick.schema import ConfigSchema, ConfigParameterSchema, \
InvalidValueError
class ConfigurationTests(unittest.TestCase):
@ -165,7 +167,7 @@ class ConfigurationTests(unittest.TestCase):
self.assertEqual(self.value, c.get(self.fullparam))
def test_contains(self):
def test_section_in(self):
c = Configuration()
self.assertFalse(self.section in c)
@ -210,3 +212,73 @@ class ConfigurationTests(unittest.TestCase):
c.set('b', 'x')
self.assertEqual('$b', c.get('a', raw=True))
def test_typed_params(self):
schema = ConfigSchema('test', '1.0', 'ini', [
ConfigParameterSchema('param1', type='integer', section='DEFAULT')
])
c = Configuration(schema)
c.set('param1', '123')
self.assertEqual(123, c.get('param1'))
def test_typed_params_update(self):
schema = ConfigSchema('test', '1.0', 'ini', [
ConfigParameterSchema('param1', type='integer', section='DEFAULT')
])
c = Configuration(schema)
c.set('param1', '123')
self.assertEqual(123, c.get('param1'))
c.set('param1', '456')
self.assertEqual(456, c.get('param1'))
def test_typed_param_with_invalid_value_returns_string_value(self):
schema = ConfigSchema('test', '1.0', 'ini', [
ConfigParameterSchema('param1', type='integer', section='DEFAULT')
])
c = Configuration(schema)
c.set('param1', '123a')
self.assertEqual('123a', c.get('param1'))
def test_getting_typed_param_raw_value(self):
schema = ConfigSchema('test', '1.0', 'ini', [
ConfigParameterSchema('param1', type='integer', section='DEFAULT')
])
c = Configuration(schema)
c.set('param1', '123')
self.assertEqual('123', c.get('param1', raw=True))
def test_validate_returns_none_if_value_is_valid(self):
schema = ConfigSchema('test', '1.0', 'ini', [
ConfigParameterSchema('param1', type='integer', section='DEFAULT')
])
c = Configuration(schema)
c.set('param1', '123')
self.assertIsNone(c.validate('param1'))
def test_validate_returns_error_if_valid_is_invalid(self):
schema = ConfigSchema('test', '1.0', 'ini', [
ConfigParameterSchema('param1', type='integer', section='DEFAULT')
])
c = Configuration(schema)
c.set('param1', 'abc')
self.assertTrue(isinstance(c.validate('param1'), InvalidValueError))