diff --git a/nailgun/nailgun/api/v1/handlers/cluster.py b/nailgun/nailgun/api/v1/handlers/cluster.py index 1c29e5024b..f646f1a002 100644 --- a/nailgun/nailgun/api/v1/handlers/cluster.py +++ b/nailgun/nailgun/api/v1/handlers/cluster.py @@ -28,7 +28,7 @@ from nailgun.api.v1.handlers.base import DeferredTaskHandler from nailgun.api.v1.handlers.base import DeploymentTasksHandler from nailgun.api.v1.handlers.base import SingleHandler -from nailgun.api.v1.validators.cluster import AttributesValidator +from nailgun.api.v1.validators.cluster import ClusterAttributesValidator from nailgun.api.v1.validators.cluster import ClusterChangesValidator from nailgun.api.v1.validators.cluster import ClusterStopDeploymentValidator from nailgun.api.v1.validators.cluster import ClusterValidator @@ -121,7 +121,7 @@ class ClusterAttributesHandler(BaseHandler): "editable", ) - validator = AttributesValidator + validator = ClusterAttributesValidator @content def GET(self, cluster_id): diff --git a/nailgun/nailgun/api/v1/handlers/node.py b/nailgun/nailgun/api/v1/handlers/node.py index 0713d28741..b832dfd0e9 100644 --- a/nailgun/nailgun/api/v1/handlers/node.py +++ b/nailgun/nailgun/api/v1/handlers/node.py @@ -27,7 +27,7 @@ from nailgun.api.v1.handlers.base import CollectionHandler from nailgun.api.v1.handlers.base import content from nailgun.api.v1.handlers.base import SingleHandler from nailgun.api.v1.validators.network import NetAssignmentValidator -from nailgun.api.v1.validators.node import NodeValidator +from nailgun.api.v1.validators import node as node_validators from nailgun import consts from nailgun.errors import errors @@ -48,7 +48,7 @@ from nailgun import notifier class NodeHandler(SingleHandler): single = objects.Node - validator = NodeValidator + validator = node_validators.NodeValidator @content def DELETE(self, obj_id): @@ -76,7 +76,7 @@ class NodeHandler(SingleHandler): class NodeCollectionHandler(CollectionHandler): """Node collection handler""" - validator = NodeValidator + validator = node_validators.NodeValidator collection = objects.NodeCollection @content @@ -159,7 +159,7 @@ class NodeCollectionHandler(CollectionHandler): class NodeAgentHandler(BaseHandler): collection = objects.NodeCollection - validator = NodeValidator + validator = node_validators.NodeValidator @content def PUT(self): @@ -328,7 +328,7 @@ class NodesAllocationStatsHandler(BaseHandler): class NodeAttributesHandler(BaseHandler): """Node attributes handler""" - # TODO(asvechnikov): Add validator + validator = node_validators.NodeAttributesValidator @content def GET(self, node_id): diff --git a/nailgun/nailgun/api/v1/validators/base.py b/nailgun/nailgun/api/v1/validators/base.py index 5cb69e51d0..29f285809b 100644 --- a/nailgun/nailgun/api/v1/validators/base.py +++ b/nailgun/nailgun/api/v1/validators/base.py @@ -13,14 +13,17 @@ # License for the specific language governing permissions and limitations # under the License. +import copy + import jsonschema -from jsonschema.exceptions import ValidationError +from jsonschema import exceptions +from oslo_serialization import jsonutils import six -from oslo_serialization import jsonutils - +from nailgun.api.v1.validators.json_schema import base_types from nailgun.errors import errors from nailgun import objects +from nailgun.utils import restrictions class BasicValidator(object): @@ -60,7 +63,7 @@ class BasicValidator(object): try: jsonschema.validate(json_req, use_schema) - except ValidationError as exc: + except exceptions.ValidationError as exc: if len(exc.path) > 0: raise errors.InvalidData( # NOTE(ikutukov): here was a exc.path.pop(). It was buggy @@ -121,3 +124,80 @@ class BaseDefferedTaskValidator(BasicValidator): @classmethod def validate(cls, cluster): pass + + +class BasicAttributesValidator(BasicValidator): + + @classmethod + def validate(cls, data): + attrs = cls.validate_json(data) + + cls.validate_attributes(attrs) + + return attrs + + @classmethod + def validate_attributes(cls, data): + """Validate attributes.""" + for attrs in six.itervalues(data): + if not isinstance(attrs, dict): + continue + for attr_name, attr in six.iteritems(attrs): + cls.validate_attribute(attr_name, attr) + + return data + + @classmethod + def validate_attribute(cls, attr_name, attr): + """Validates a single attribute from settings.yaml. + + Dict is of this form:: + + description: + label: