..
      Licensed under the Apache License, Version 2.0 (the "License"); you may
      not use this file except in compliance with the License. You may obtain
      a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
      License for the specific language governing permissions and limitations
      under the License.


      Convention for heading levels in Neutron devref:
      =======  Heading 0 (reserved for the title in a document)
      -------  Heading 1
      ~~~~~~~  Heading 2
      +++++++  Heading 3
      '''''''  Heading 4
      (Avoid deeper levels because they do not render well.)


API Attributes
==============

Neutron's resource attributes are defined in dictionaries
in ``api/definitions``.

The map containing all installed resources (for core and active extensions)
is in ``api/attributes.py``.


Attribute map structure
-----------------------

Example attribute definitions for ``dns_name``:

.. code-block:: python

        'dns_name': {
            'allow_post': True,
            'allow_put': True,
            'default': '',
            'convert_to': convert_to_lowercase,
            'validate': {'type:dns_name': FQDN_MAX_LEN},
            'is_visible': True
        },


The ``validate`` item specifies rules for `validating <api_validators.html>`_
the attribute.

The ``convert_to`` item specifies rules for `converting <api_converters.html>`_
the attribute.

Example attribute definitions for ``gateway_ip``:

.. code-block:: python

        'gateway_ip': {
            'allow_post': True,
            'allow_put': True,
            'default': constants.ATTR_NOT_SPECIFIED,
            'validate': {'type:ip_address_or_none': None},
            'is_visible': True
        }

Note: a default of ``ATTR_NOT_SPECIFIED`` indicates that an attribute is not
required, but will be generated by the plugin if it is not specified.
Particularly, a value of ``ATTR_NOT_SPECIFIED`` is different from an
attribute that has been specified with a value of ``None``.  For example,
if ``gateway_ip`` is omitted in a request to create a subnet, the plugin
will receive ``ATTR_NOT_SPECIFIED`` and the default gateway IP will be
generated.  However, if ``gateway_ip`` is specified as ``None``, this means
that the subnet does not have a gateway IP.

The following are the defined keys for attribute maps:

==========================  ======
``default``                 default value of the attribute (if missing, the attribute becomes mandatory)
``allow_post``              the attribute can be used on ``POST`` requests
``allow_put``               the attribute can be used on ``PUT`` requests
``validate``                specifies rules for validating data in the attribute
``convert_to``              transformation to apply to the value before it is returned
``convert_list_to``         if the value is a list, apply this transformation to the value before it is returned
``is_filter``               the attribute can be used in ``GET`` requests as filter
``is_sort_key``             the attribute can be used in ``GET`` requests as sort_key
``is_visible``              the attribute is returned in ``GET`` responses
``required_by_policy``      the attribute is required by the policy engine and should therefore be filled by the API layer even if not present in request body
``enforce_policy``          the attribute is actively part of the policy enforcing mechanism, ie: there might be rules which refer to this attribute
``primary_key``             Mark the attribute as a unique key.
``default_overrides_none``  if set, if the value passed is None, it will be replaced by the ``default`` value
``dict_populate_defaults``  if set, the ``default`` values of keys inside dict attributes, will be filled if not specified
==========================  ======

When extending existing sub-resources, the sub-attribute map must define all
extension attributes under the ``parameters`` object. This instructs the API
internals to add the attributes to the existing sub-resource rather than
overwrite its existing definition. For example:

.. code-block:: python

        SUB_RESOURCE_ATTRIBUTE_MAP: SubResourceAttributeMap = {
            'existing_subresource_to_extend': {
                'parameters': {
                    'new_attr1': {
                        'allow_post': False,
                        # etc..
                    }
                }
            }
        }
