Giuseppe Lavagetto has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/405302 )
Change subject: Add preemptive validation. ...................................................................... Add preemptive validation. When writing to the backend, let's check that all the new values are valid before writing. Bug: T185080 Change-Id: I17c8e5cebd71369e27f78f05db1aaac31165467c --- M conftool/action.py M conftool/cli/syncer.py M conftool/kvobject.py M conftool/tests/integration/__init__.py M conftool/tests/unit/test_kvobject.py 5 files changed, 33 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/operations/software/conftool refs/changes/02/405302/1 diff --git a/conftool/action.py b/conftool/action.py index 92313ae..1870435 100644 --- a/conftool/action.py +++ b/conftool/action.py @@ -8,6 +8,10 @@ pass +class ActionValidationError(ActionError): + pass + + class Action(object): def __init__(self, obj, act): @@ -80,6 +84,12 @@ elif self.action == 'set': if not self.entity.exists: raise ActionError("Entity %s doesn't exist" % self.entity.name) + # Validate the new data *before* updating the object + try: + self.entity.validate(self.args) + except Exception as e: + raise ActionValidationError("The provided data is not valid: %s" % e) + desc = [] for (k, v) in self.args.items(): curval = getattr(self.entity, k) diff --git a/conftool/cli/syncer.py b/conftool/cli/syncer.py index 2debe94..fc3b430 100644 --- a/conftool/cli/syncer.py +++ b/conftool/cli/syncer.py @@ -135,6 +135,7 @@ obj = self.cls(*tags) if obj.static_values: _log.info("Syncing static object %s:%s", self.entity, key) + obj.validate(self.data[key]) obj.from_net(self.data[key]) else: if obj.exists: diff --git a/conftool/kvobject.py b/conftool/kvobject.py index 45ab060..e45ec5f 100644 --- a/conftool/kvobject.py +++ b/conftool/kvobject.py @@ -121,6 +121,20 @@ self._set_value(k, self._schema[k], {k: v}, set_defaults=False) self.write() + def validate(self, values): + """ + Validate a set of proposed values against the schema. + Returns True on success, raises an exception otherwise + """ + for k, v in values.items(): + if k not in self._schema: + if self.strict_schema: + raise TypeError("Key %s not in the schema" % k) + continue + validator = self._schema[k] + validator(v) + return True + @classmethod def from_yaml(cls, data): if cls.static_values: @@ -232,6 +246,7 @@ General-purpose entity with a strict schema """ depends = [] + strict_schema = True def __init__(self, *tags): if len(tags) != (len(self._tags) + 1): @@ -266,6 +281,7 @@ class FreeSchemaEntity(Entity): + strict_schema = False def __init__(self, *tags, **kwargs): self._schemaless = kwargs diff --git a/conftool/tests/integration/__init__.py b/conftool/tests/integration/__init__.py index a207875..4dc3a8b 100644 --- a/conftool/tests/integration/__init__.py +++ b/conftool/tests/integration/__init__.py @@ -60,6 +60,7 @@ def stop(self): self.proc.kill() self.proc = None + time.sleep(2) class IntegrationTestBase(unittest.TestCase): diff --git a/conftool/tests/unit/test_kvobject.py b/conftool/tests/unit/test_kvobject.py index 494c810..d503ab6 100644 --- a/conftool/tests/unit/test_kvobject.py +++ b/conftool/tests/unit/test_kvobject.py @@ -133,6 +133,11 @@ set_defaults=False) self.entity.write.assert_called_with() + def test_validate(self): + self.assertTrue(self.entity.validate({'a': 1, 'b': 'testtest'})) + self.assertRaises(TypeError, self.entity.validate, {'a': 1, 'b': 'testtest', 'c': True}) + self.assertRaises(ValueError, self.entity.validate, {'a': 'test'}) + def test_to_net(self): self.entity.a = 100 self.entity.b = 'meoow' -- To view, visit https://gerrit.wikimedia.org/r/405302 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I17c8e5cebd71369e27f78f05db1aaac31165467c Gerrit-PatchSet: 1 Gerrit-Project: operations/software/conftool Gerrit-Branch: master Gerrit-Owner: Giuseppe Lavagetto <glavage...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits