Paul Michali 7d9980f7ca API validators and converters
This brings over the validation and convert_to methods from Neutron.
Additional tests were added to improve coverage, and some supporting
methods were added for these.

Renamed validators to remove underscore, so that they can be imported
into neutron/api/v2/attributes.py.

Added devref docs to help developers in creating and using validators
and converters.

Change-Id: I81394dff69b816146e521bcd3e9641761178d6fd
Implements: blueprint neutron-lib
2016-01-15 12:44:09 +00:00

3.4 KiB

API Validators

For the REST API, attributes may have custom validators defined. Each validator will have a method to perform the validation, and a type definition string, so that the validator can be referenced.

Defining A Validator Method

The validation method will have a positional argument for the data to be validated, and may have additional (optional) keyword arguments that can be used during validation. The method must handle any exceptions and either return None (success) or a i18n string indicating the validation failure message. By convention, the method name is prefixed with validate_ and then includes the data type. For example:

def validate_uuid(data, valid_values=None):
   if not uuidutils.is_uuid_like(data):
       msg = _("'%s' is not a valid UUID") % data
       LOG.debug(msg)
       return msg

There is a validation dictionary that maps the method to a validation type that can be referred to in REST API definitions. An entry in the dictionary would look like the following:

'type:uuid': validate_uuid,

Using Validators

In client code, the valdiator can be used in a REST API by using the dictionary key for the validator. For example:

RESOURCE_ATTRIBUTE_MAP = {
    NETWORKS: {
        'id': {'allow_post': False, 'allow_put': False,
               'validate': {'type:uuid': None},
               'is_visible': True,
               'primary_key': True},
        'name': {'allow_post': True, 'allow_put': True,
                 'validate': {'type:string': NAME_MAX_LEN},
                 'default': '', 'is_visible': True},

Here, the networks resource has an 'id' attribute with a UUID validator, as seen by the 'validate' key containing a dictionary with a key of 'type:uuid'.

Any addition arguments for the validator can be specified as values for the dictionary entry (None in this case, NAME_MAX_LEN in the 'name' attribute that uses a string validator). In a IP version attribute, one could have a validator defined as follows:

'ip_version': {'allow_post': True, 'allow_put': False,
               'convert_to': conversions.convert_to_int,
               'validate': {'type:values': [4, 6]},
               'is_visible': True},

Here, the valdiate_values() method will take the list of values as the allowable values that can be specified for this attribute.

Test The Validator

Do the right thing, and make sure you've created a unit test for any validator that you add to verify that it works as expected, even for simple validators.