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 <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits