diff --git a/keystone/catalog/controllers.py b/keystone/catalog/controllers.py index 40b6fc7a7d..76abd86a97 100644 --- a/keystone/catalog/controllers.py +++ b/keystone/catalog/controllers.py @@ -56,6 +56,7 @@ class Service(controller.V2Controller): @controller.v2_deprecated def create_service(self, request, OS_KSADM_service): + validation.lazy_validate(schema.service_create_v2, OS_KSADM_service) self.assert_admin(request) service_id = uuid.uuid4().hex service_ref = OS_KSADM_service.copy() diff --git a/keystone/catalog/schema.py b/keystone/catalog/schema.py index b9643131e5..a9965327e9 100644 --- a/keystone/catalog/schema.py +++ b/keystone/catalog/schema.py @@ -13,6 +13,11 @@ from keystone.common import validation from keystone.common.validation import parameter_types +_service_properties_type = { + 'type': 'string', + 'minLength': 1, + 'maxLength': 255 +} _region_properties = { 'description': { @@ -42,21 +47,37 @@ region_update = { 'additionalProperties': True } +# Schema for Service v2 + +_service_properties_v2 = { + 'enabled': parameter_types.boolean, + 'description': { + 'type': ['string', 'null'] + }, + 'name': parameter_types.name, + 'type': _service_properties_type +} + +service_create_v2 = { + 'type': 'object', + 'properties': _service_properties_v2, + 'required': ['type'], + 'additionalProperties': True +} + +# Schema for Service v3 + _service_properties = { 'enabled': parameter_types.boolean, 'name': parameter_types.name, - 'type': { - 'type': 'string', - 'minLength': 1, - 'maxLength': 255 - } + 'type': _service_properties_type } service_create = { 'type': 'object', 'properties': _service_properties, 'required': ['type'], - 'additionalProperties': True, + 'additionalProperties': True } service_update = { diff --git a/keystone/tests/unit/test_v2_validation.py b/keystone/tests/unit/test_v2_validation.py index c89d1f93b9..00ceb7d5f0 100644 --- a/keystone/tests/unit/test_v2_validation.py +++ b/keystone/tests/unit/test_v2_validation.py @@ -14,6 +14,7 @@ import uuid from keystone.assignment import schema as assignment_schema +from keystone.catalog import schema as catalog_schema from keystone.common.validation import validators from keystone import exception from keystone.resource import schema as resource_schema @@ -229,3 +230,75 @@ class TenantValidationTestCase(unit.BaseTestCase): self.assertRaises(exception.SchemaValidationError, self.update_validator.validate, request) + + +class ServiceValidationTestCase(unit.BaseTestCase): + """Test for V2 Service API Validation.""" + + def setUp(self): + super(ServiceValidationTestCase, self).setUp() + + schema_create = catalog_schema.service_create + self.create_validator = validators.SchemaValidator(schema_create) + + def test_validate_service_create_succeeds(self): + request = { + 'name': uuid.uuid4().hex, + 'type': uuid.uuid4().hex, + 'description': uuid.uuid4().hex + } + self.create_validator.validate(request) + + def test_validate_service_create_fails_with_invalid_params(self): + request = { + 'bogus': uuid.uuid4().hex + } + self.assertRaises(exception.SchemaValidationError, + self.create_validator.validate, + request) + + def test_validate_service_create_fails_with_invalid_name(self): + for invalid_name in _INVALID_NAMES: + request = { + 'type': uuid.uuid4().hex, + 'name': invalid_name + } + self.assertRaises(exception.SchemaValidationError, + self.create_validator.validate, + request) + + def test_validate_service_create_with_enabled(self): + """Validate `enabled` as boolean-like values.""" + for valid_enabled in _VALID_ENABLED_FORMATS: + request = { + 'type': uuid.uuid4().hex, + 'enabled': valid_enabled + } + self.create_validator.validate(request) + + def test_validate_service_create_with_invalid_enabled_fails(self): + """Exception is raised when `enabled` isn't a boolean-like value.""" + for invalid_enabled in _INVALID_ENABLED_FORMATS: + request = { + 'type': uuid.uuid4().hex, + 'enabled': invalid_enabled + } + self.assertRaises(exception.SchemaValidationError, + self.create_validator.validate, + request) + + def test_validate_service_create_with_invalid_type(self): + request = { + 'type': -42 + } + self.assertRaises(exception.SchemaValidationError, + self.create_validator.validate, + request) + + def test_validate_service_create_with_type_too_large(self): + request = { + 'type': 'a' * 256 + } + self.assertRaises(exception.SchemaValidationError, + self.create_validator.validate, + request)