Commit c7db2923 authored by Xavier Thompson's avatar Xavier Thompson

slapconfiguration:jsonschema: Add set-default

Add `set-default` options to slapconfiguration:jsonschema.
Accepted values are `all|main|shared|none`.
Default value is `none`.

These allow controlling whether default values of parameters that
where not provided by the user are set from the defaults given in
the JSON schema. The default behavior of the recipe is now not to
add any defaults. The new option allows adding all defaults, only
the defaults of the main instance, or only the defaults of shared
instances.
parent df2bc8bc
......@@ -276,6 +276,16 @@ class Serialised(Recipe):
return {}
class BasicValidator(object):
def __init__(self, schema):
self.schema = schema
self.validator = jsonschema.validators.validator_for(schema)(schema)
def validate(self, instance):
for error in self.validator.iter_errors(instance):
yield error
class DefaultValidator(object):
def __init__(self, schema):
self.schema = schema
......@@ -347,6 +357,20 @@ class JsonSchema(Recipe):
All instance schemas must be available at the advertised relative paths.
Example:
${buildout:directory}/software.cfg.json
set-default
Enum to control adding defaults specified by the JSON schema
to both/neither/either-of main and shared instance parameters.
Accepted values: all|main|shared|none.
Default value: none.
Example:
shared
Example:
true
set-shared-default
Flag to add defaults specified by the JSON schema for shared instances.
False by default; any value makes this flag behave as true.
Example:
true
"""
def _schema(self, options):
path = options['jsonschema']
......@@ -367,7 +391,7 @@ class JsonSchema(Recipe):
def _parseParameterDict(self, software_schema, parameter_dict):
instance_schema = software_schema.getInstanceRequestParameterSchema()
instance = parameter_dict if isinstance(parameter_dict, dict) else {}
validator = DefaultValidator(instance_schema)
validator = self.Validator(instance_schema)
errors = list(validator.validate(instance))
if errors:
err = SoftwareReleaseSchemaValidationError(errors).format_error(indent=2)
......@@ -380,7 +404,7 @@ class JsonSchema(Recipe):
if not shared_list:
return
shared_schema = self._getSharedSchema(software_schema)
validator = DefaultValidator(shared_schema)
validator = self.SharedValidator(shared_schema)
valid, invalid = [], []
for instance in shared_list:
reference = instance.pop('slave_reference')
......@@ -397,7 +421,23 @@ class JsonSchema(Recipe):
options['valid-shared-instance-list'] = valid
options['invalid-shared-instance-list'] = invalid
def _parseOption(self, options, key, default):
value = options.get(key, default)
accepted = ('none', 'main', 'shared', 'all')
try:
index = accepted.index(value)
except ValueError:
raise UserError(
"%r is not a valid value for option %r"
"Accepted values are %r" % (value, key, accepted)
)
# return: value in ('main', 'all'), value in ('shared', 'all')
return index & 1, index & 2
def _expandParameterDict(self, options, parameter_dict):
set_main, set_shared = self._parseOption(options, 'set-default', 'none')
self.Validator = DefaultValidator if set_main else BasicValidator
self.SharedValidator = DefaultValidator if set_shared else BasicValidator
software_schema = self._schema(options)
serialisation = software_schema.getSerialisation(strict=True)
if serialisation == SoftwareReleaseSerialisation.JsonInXml:
......
......@@ -183,11 +183,11 @@ class SlapConfigurationTest(unittest.TestCase):
slapconfiguration.JsonSchema(self.buildout, "slapconfiguration", options)
return options
def receiveParameters(self, options=()):
def receiveParameters(self, options=(('set-default', 'all'),)):
options = self.runJsonSchemaRecipe(options)
return options['configuration']
def receiveSharedParameters(self, options=()):
def receiveSharedParameters(self, options=(('set-default', 'all'),)):
options = self.runJsonSchemaRecipe(options)
self.assertNotIn('slave-instance-list', options)
valid = options['valid-shared-instance-list']
......@@ -215,6 +215,27 @@ class SlapConfigurationTest(unittest.TestCase):
received = self.receiveParameters()
self.checkParametersWithDefaults(received, parameters)
def test_jsonschema_json_in_xml_valid_input_without_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
with self.patchSlap(parameters, True):
received = self.receiveParameters(options=())
self.assertEqual(received, parameters)
def test_jsonschema_json_in_xml_valid_input_with_only_shared_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
with self.patchSlap(parameters, True):
received = self.receiveParameters({'set-default': 'shared'})
self.assertEqual(received, parameters)
def test_jsonschema_json_in_xml_valid_input_with_only_main_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
with self.patchSlap(parameters, True):
received = self.receiveParameters({'set-default': 'main'})
self.checkParametersWithDefaults(received, parameters)
def test_jsonschema_json_in_xml_valid_xml_input_full(self):
self.writeJsonSchema()
parameters = {"letter": "b", "number": 1}
......@@ -270,7 +291,7 @@ class SlapConfigurationTest(unittest.TestCase):
parameters = {"number": 1}
shared = [{"kind": 1}]
with self.patchSlap(parameters, True, shared):
valid, invalid = self.receiveParameters(shared=True)
valid, invalid = self.receiveSharedParameters()
self.assertEqual(invalid, {})
self.assertEqual(list(valid.values()), [{"kind": 1, "thing": "hello"}])
......@@ -302,6 +323,30 @@ class SlapConfigurationTest(unittest.TestCase):
invalid_values = list(invalid.values())
self.assertEqual(invalid_values, [{"kind": 2, "thing": "forty-two"}])
def test_jsonschema_shared_2_valid_without_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
shared = [{"kind": 2}]
with self.patchSlap(parameters, True, shared):
valid, _ = self.receiveSharedParameters(options=())
self.assertEqual(list(valid.values()), shared)
def test_jsonschema_shared_2_valid_with_only_main_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
shared = [{"kind": 2}]
with self.patchSlap(parameters, True, shared):
valid, _ = self.receiveSharedParameters({'set-default': 'main'})
self.assertEqual(list(valid.values()), shared)
def test_jsonschema_shared_2_valid_with_only_shared_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
shared = [{"kind": 2}]
with self.patchSlap(parameters, True, shared):
valid, _ = self.receiveSharedParameters({'set-default': 'shared'})
self.assertEqual(list(valid.values()), [{"kind": 2, "thing": 42}])
def test_jsonschema_shared_1_and_2_valid_defaults(self):
self.writeJsonSchema()
parameters = {"number": 1}
......@@ -344,6 +389,6 @@ class SlapConfigurationTest(unittest.TestCase):
parameters = {"number": 1}
shared = [{"kind": 1}, {"kind": 2, "thing": "hello"}]
with self.patchSlap(parameters, True, shared):
valid, invalid = self.receiveParameters(shared=True)
valid, invalid = self.receiveSharedParameters()
self.assertEqual(list(valid.values()), [{"kind": 1, "thing": "hello"}])
self.assertEqual(list(invalid.values()), [{"kind": 2, "thing": "hello"}])
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment