diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2014-03-26 16:47:51 +0000 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2014-03-26 16:47:51 +0000 |
commit | f5e856e41f5b360cecc9314178fe2bc6e60766b4 (patch) | |
tree | 995e1d8808dbd11036ee497d0f8362ead73e7ff6 | |
parent | 1d04f87b31a03930bcbc96c8bf7f8a9d6b7075b4 (diff) | |
download | lorry-controller-f5e856e41f5b360cecc9314178fe2bc6e60766b4.tar.gz |
Add rudimentary validation
-rw-r--r-- | lorrycontroller/readconf.py | 43 | ||||
-rw-r--r-- | yarns.webapp/060-validation.yarn | 12 | ||||
-rw-r--r-- | yarns.webapp/900-implementations.yarn | 28 |
3 files changed, 83 insertions, 0 deletions
diff --git a/lorrycontroller/readconf.py b/lorrycontroller/readconf.py index 64599e4..cd89a49 100644 --- a/lorrycontroller/readconf.py +++ b/lorrycontroller/readconf.py @@ -48,6 +48,11 @@ class ReadConfiguration(lorrycontroller.LorryControllerRoute): conf_obj = self.read_config_file() except LorryControllerConfParseError as e: return str(e) + + error = self.validate_config(conf_obj) + if error: + return 'ERROR: %s: %r' % (error, conf_obj) + self.fix_up_parsed_fields(conf_obj) statedb = self.open_statedb() @@ -130,6 +135,10 @@ class ReadConfiguration(lorrycontroller.LorryControllerRoute): except ValueError as e: raise LorryControllerConfParseError(filename, e) + def validate_config(self, obj): + validator = LorryControllerConfValidator() + return validator.validate_config(obj) + def fix_up_parsed_fields(self, obj): for item in obj: item['interval'] = self.fix_up_interval(item.get('interval')) @@ -220,3 +229,37 @@ class ReadConfiguration(lorrycontroller.LorryControllerRoute): ls_interval=section['ls-interval'], prefixmap=json.dumps(section['prefixmap']), ignore=json.dumps(section['ignore'])) + + +class LorryControllerConfValidator(object): + + def validate_config(self, conf_obj): + for check in self._find_checks(): + error = check(conf_obj) + if error: + return error + return None + + def _find_checks(self): + return [ + getattr(self, name) + for name in dir(self) + if name.startswith('_check_')] + + def _check_is_list(self, conf_obj): + if type(conf_obj) is not list: + return 'is not a JSON list' + + def _check_is_list_of_dicts(self, conf_obj): + for item in conf_obj: + if type(item) is not dict: + return 'all items must be dicts' + + def _check_sections_have_known_type(self, conf_obj): + allowed_types = ['lorries', 'trove', 'troves'] + + for item in conf_obj: + if 'type' not in conf_obj: + return 'must have a type field' + if conf_obj['type'] not in allowed_types: + return ('must have a known type, not %r' % conf_obj['type']) diff --git a/yarns.webapp/060-validation.yarn b/yarns.webapp/060-validation.yarn index b7b1a66..4d2ce3b 100644 --- a/yarns.webapp/060-validation.yarn +++ b/yarns.webapp/060-validation.yarn @@ -83,6 +83,18 @@ non-sensical value? THEN response matches "ERROR" AND STATEDB is empty +Now we're getting to real sections. A `troves` section must have +`trovehost`, `interval`, `ls-interval`, and `prefixmap` set, and may +optionally have `ignore` set. Test each of those with good and bad +values. + + GIVEN an empty lorry-controller.conf in CONFGIT + AND lorry-controller.conf in CONFGIT adds trove example-trove + AND lorry-controller.conf in CONFGIT sets interval to "blah" for trove example-trove + WHEN admin makes request POST /1.0/read-configuration with dummy=value + THEN response matches "ERROR" + AND STATEDB is empty + Clean up at the end. FINALLY WEBAPP terminates diff --git a/yarns.webapp/900-implementations.yarn b/yarns.webapp/900-implementations.yarn index c88b6fa..39c4a63 100644 --- a/yarns.webapp/900-implementations.yarn +++ b/yarns.webapp/900-implementations.yarn @@ -173,6 +173,34 @@ most of the configuration. json.dump(obj, f, indent=4) ' +Set a specific field for a `troves` section. + + IMPLEMENTS GIVEN (\S+) in (\S+) sets (\S+) to (\S+) for trove (\S+) + python -c ' + import os + import json + + DATADIR = os.environ["DATADIR"] + MATCH_1 = os.environ["MATCH_1"] + MATCH_2 = os.environ["MATCH_2"] + MATCH_3 = os.environ["MATCH_3"] + MATCH_4 = os.environ["MATCH_3"] + MATCH_5 = os.environ["MATCH_3"] + + filename = os.path.join(DATADIR, MATCH_2, MATCH_1) + + with open(filename, "r") as f: + obj = json.load(f) + + for section in obj: + if section["type"] in ["trove", "troves"]: + if section["trovehost"] == MATCH_5: + section[MATCH_3] = json.loads(MATCH_4) + + with open(filename, "w") as f: + json.dump(obj, f, indent=4) + ' + Set the prefixmap for a Trove in a Lorry Controller configuration file. Note that the Trove must already be in the configuration file. |