gluon/doc/source/devref/gluon_api_spec.inc

713 lines
22 KiB
PHP

=======================
Gluon API Specification
=======================
Gluon supports the processing of a specification document to define an
object-oriented API. The gluon API specification uses YAML syntax to define
the structure and relationships of the objects that are manipulated by the
API. This specification also includes metadata definitions that can be used
for the automatic generation of human readable API documentation.
The specification allows for the definition of two types of objects: base
objects and API objects. A base object is an object specification that does
not have an API definition field. An object with an API definition field is
an API object. A base object is used to define a set of attributes that can be
included in other object definitions. Base objects can extend other base
objects but not API objects. An API object can only extend base objects. No
code is created for base objects. The gluon framework will generate code for
API objects.
For each API object, the gluon framework will generate code for database
storage and code to support a REST API to manipulate the object. The API
endpoints created will support the basic CRUD operations on the object. Each
API object will have a corresponding database table. Each API object is
required to have a primary key field. The primary key field is used as the
identifier in the generated API endpoints. For example, if we define an API
object for a Port with a path name of *ports* the following API URL endpoints
will be generated where <port_id> is the primary key.
.. csv-table::
:header: "Operation", "URL", "Description"
:widths: 5, 15, 15
POST, /proton/<api_name>/ports, Create Port object
PUT, /proton/<api_name>/ports/<port_id>, Modify Port object
GET, /proton/<api_name>/ports, Get all Port objects
GET, /proton/<api_name>/ports/<port_id>, Get one Port object
DELETE, /proton/<api_name>/ports/<port_id>, Delete a Port object
The content type for all of the operations is *application/json*.
The API objects can have pointer relationships and parent/child relationships
to other API objects. A pointer relationship can be created by defining a
field that uses the object name of another object as its type. When this type
of relationship is specified, the primary key of the referenced object becomes
a foreign key in the object's database table. A parent/child relationship can
be created at the API level by specifying the parent object name in an
object's API definition (see ApiDef_). When a parent/child relationship is
specified, a pointer relationship from the child object to the parent object
is automatically created using the primary key of the parent.
In addition, different API endpoints are generated to manipulate the child
object. For example, assume we define an API object for Port and another API
object for Interface where the Interface is a child of the Port. If the path
names are *ports* and *interfaces*, the following API URL endpoints for the
Interface object would be generated.
.. list-table::
:widths: 5 15 16
:header-rows: 1
* - Operation
- URL
- Description
* - POST
- /proton/<api_name>/ports/<port_id>/interfaces
- Create Interface object
* - PUT
- /proton/<api_name>/ports/<port_id>/interfaces/<interface_id>
- Modify Interface object
* - GET
- /proton/<api_name>/ports/<port_id>/interfaces
- Get all Interface objects for Port
* - GET
- /proton/<api_name>/ports/<port_id>/interfaces/<interface_id>
- Get one Interface object
* - DELETE
- /proton/<api_name>/ports/<port_id>/interfaces/<interface_id>
- Delete an Interface object
This document describes the specification for defining an API. Further
guidance on how to design an API using the Service Binding Model can be found
`here <https://github.com/openstack/gluon/blob/master/doc/source/devref/service_binding_model.rst>`_.
Schema Definition
-----------------
The schema exposes two types of fields. Fixed fields, which have a declared
name, and Patterned fields, which declare a regex pattern for the field name.
Patterned fields can have multiple occurrences as long as each has a unique
name. Each field will have a value that is defined as a primitive type or as
an JSON object. The JSON objects are very similar to the Schema Object found
in Swagger. However, some extensions are added and only a small subset of the
properties are supported.
Primitive Data Types
---------------------
.. list-table::
:widths: 15 20 30
:header-rows: 1
* - Type
- Description
- Associated Properties
* - integer
- Integer number
- - format: int32, int64 (default: int32)
- min: *integer*
- max: *integer*
* - number
- Floating point number
- n/a
* - string
- Text String
- - length: *integer* (default: 255)
- format: date-time, json, ipv4, ipv6, mac, url, email
* - boolean
- Boolean value (true/false)
- n/a
* - uuid
- Text string in UUID format
- n/a
* - enum
- Text string from a list of values
- - values: [*string*]
File Structure
--------------
The API is defined by a single file. The Root Object is defined by the
ProtonDef object. See the complete Example_Specs_ at the end of this page for an
example of the ProtonDef syntax.
ProtonDef
~~~~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
file_version, string, true, Proton File Version
imports, string, false, File path to common base object definitions
info, InfoDef_, true, Metadata for this API specification that is useful in the generation of human readable API documentation.
objects, ObjectsDef_, true, Object definitions for this API
**Example**
::
file_version: 1.0
imports: base/base.yaml
info:
name: net-l3vpn
version: 1.0
description "L3VPN API Specification"
author:
name: "Gluon Team"
url: https://wiki.openstack.org/wiki/Gluon
email: bh526r@att.com
objects:
Port:
api:
name: port
plural_name: ports
extends: BasePort
attributes:
alarms:
type: string
length: 255
description: "Alarm summary for port"
...
The ProtonDef is the root object for the API specification. The *file_version*
is used to identify the format used to create this file. The *info* field
contains the metadata about the API. The *objects* field contains the base
and API object definitions for the API.
InfoDef
~~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
name, string, true, Name of the API
version, string, true, Version of the API
description, string, false, Description of the API
author, AuthorDef_, false, Information about API authorship
The InfoDef is where metadata about the API can be specified. At a minimum the
*name* and *version* of the API must be specified.
**Example**
::
name: net-l3vpn
version: 1.0
description "L3VPN API Specification"
author:
name: "Gluon Team"
url: https://wiki.openstack.org/wiki/Gluon
email: bh526r@att.com
AuthorDef
~~~~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
name, string, true, Name of the author
url, string, false, URL to author website
email, string, false, Email address of author
The AuthorDef allows authorship information about the API to be specified.
This information is optional.
**Example**
::
name: "Gluon Team"
url: https://wiki.openstack.org/wiki/Gluon
email: bh526r@att.com
ObjectsDef
~~~~~~~~~~
.. csv-table::
:header: "Pattern Field", "Type", "Required", "Description"
:widths: 10, 5, 3, 20
[_a-zA-Z][_a-zA-Z0-9]*, ObjectDef_, true, Field/Value Object definitions
The ObjectsDef allows one or more objects to be specified for the API. The
field name should follow the lexical definitions for a Python identifier.
**Example**
::
VpnService:
api:
name: vpn
plural_name: vpns
extends: BaseService
attributes:
ipv4_family:
type: string
length: 255
description: "Comma separated list of route target strings"
ipv6_family:
type: string
length: 255
description: "Comma separated list of route target strings"
route_distinguishers:
type: string
length: 32
description: "Route distinguisher for this VPN"
ObjectDef
~~~~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
api, ApiDef_, false, API path information for object
extends, string, false, Name of a base object definition to extend
attributes, AttributesDef_, true, Attribute definitions of object
policies, PolicyDef_, false, Access rules for this API object
The ObjectDef defines either a base object or an API object. If the *api*
field is present, it is an API object. If the *api* field is omitted, it is a
base object. The *extends* field (if present) must specify the ObjectDef name
of another base object. The *policies* field is only allowed for an API
object. If the *policies* field is omitted, no access control is applied to
the object.
**Example**
::
api:
name: port
plural_name: ports
extends: BasePort
attributes:
alarms:
type: string
length: 255
description: "Alarm summary for port"
policies:
create: "rule:admin_or_network_owner"
delete: "rule:admin_or_network_owner"
get: "rule:admin_or_owner"
get_one: "rule:admin_or_owner"
update: "rule:admin_or_network_owner"
ApiDef
~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
name, string, true, Singular path name for the object
plural_name, string, false, Plural path name for the object
parent, string, false, Name of an ObjectDef specification
The ApiDef defines the API path and optionally a parent/child relationship for
the object. The *parent* field (if present) must specify the ObjectDef name
of another API object. The *name* field is used by the generated CLI code to
identify the object to be manipulated. The *plural_name* field is used by the
generated API code as part of the path to identify the object to be manipulated.
If the *plural_name* field is omitted, an 's' character is added to the name
for the API path during code generation.
**Example**
::
name: interface
plural_name: interfaces
parent: Port
PolicyDef
~~~~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
create, string, false, Rule specifier string
delete, string, false, Rule specifier string
get, string, false, Rule specifier string
get_one, string, false, Rule specifier string
update, string, false, Rule specifier string
The PolicyDef defines the Role-Based Access Control (RBAC) for the object. The
access to the object can be controlled for each generated action. The syntax
of the rule specifier string is defined in the Openstack Policy
`document <http://docs.openstack.org/newton/config-reference/policy-json-file.html>`_.
**Example**
::
create: "rule:admin_or_network_owner"
delete: "rule:admin_or_network_owner"
get: "rule:admin_or_owner"
get_one: "rule:admin_or_owner"
update: "rule:admin_or_network_owner"
AttributesDef
~~~~~~~~~~~~~
.. csv-table::
:header: "Pattern Field", "Type", "Required", "Description"
:widths: 10, 5, 3, 20
[_a-zA-Z][_a-zA-Z0-9]*, AttributeSchemaDef_, true, Field/Value Attribute definitions
The AttributesDef allows one or more attributes to be specified for the
object. The field name should follow the lexical definitions for a Python
identifier.
**Example**
::
id:
type: uuid
required: true
primary: true
description: "UUID of Interface instance"
AttributeSchemaDef
~~~~~~~~~~~~~~~~~~
.. csv-table::
:header: "Fixed Field", "Type", "Required", "Description"
:widths: 5, 5, 3, 20
type, string, true, Primitive data type or ObjectDef name
primary, boolean, false, Primary key for object (if true)
description, string, false, Description of the attribute
required, boolean, false, Required flag for object creation (default: false)
length, integer, false, Length if type is string (default: 255)
values, [string], false, Array of strings (required if type is enum)
format, string, false, Format if type is integer or string
min, integer, false, Min value if type is integer
max, integer, false, Max value if type is integer
Each attribute is defined by an AttributeSchemaDef. The *type* field is
mandatory and can specify a primitive data type or it can be the name of an
ObjectDef. The ObjectDef name must be for an API object. One attribute for
an object must have the *primary* field specified. The *required* field is
used to specify if the attribute must be present when creating an object. If
the *type* is enum, the *values* field must be present and define an array of
valid strings for the enumeration.
If the *type* is integer:
* The *format* field can specify if the integer is 32 or 64 bit. Default is int32
* The *min* field can specify the valid minimum value
* The *max* field can specify the valid maximum value
If the *type* is string:
* The *format* field can specify the formatting that will be validated for the string. The string formatting validations supported are:
* date-time - Validated according to Date_Time_
* json - Valid JSON string
* ipv4 - Validated according to IPV4_
* ipv6 - Validated according to IPV6_
* mac - Valid MAC address according to IEEE 802
* uri - Validated according to URI_
* email - Validated according to EMAIL_
* The *length* field can specify the size of the string. Default is 255
**Example**
The following example shows the AttributeSchemaDef definitions for ipaddress,
subnet_prefix, status, and profile.
::
ipaddress:
type: string
length: 23
description: "IP Address of port"
format: ipv4
subnet_prefix:
type: integer
description: "Subnet mask"
format: int32
min: 1
max: 31
status:
type: enum
required: true
description: "Operational status of Port"
values:
- 'ACTIVE'
- 'DOWN'
profile:
type: string
length: 128
description: "JSON string for binding profile dictionary"
format: json
References
~~~~~~~~~~
`Date_Time <https://tools.ietf.org/html/draft-wright-json-schema-validation-00#section-7.3.1>`_
`IPV4 <https://tools.ietf.org/html/draft-wright-json-schema-validation-00#section-7.3.4>`_
`IPV6 <https://tools.ietf.org/html/draft-wright-json-schema-validation-00#section-7.3.5>`_
`URI <https://tools.ietf.org/html/draft-wright-json-schema-validation-00#section-7.3.6>`_
`EMAIL <https://tools.ietf.org/html/draft-wright-json-schema-validation-00#section-7.3.2>`_
.. _Example_Specs:
Complete Example Specification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This section shows the L3VPN API defined using this specification. The base
objects that would be defined in base/base.yaml are in the Base Objects
section and the API is defined in the API Specification section.
Base Objects
************
::
file_version: 1.0
objects:
BasePort:
attributes:
id:
type: uuid
primary: true:
description: "UUID of Port instance"
name:
type: string
length: 64
description: "Descriptive name for Port"
tenant_id:
type: uuid
required: true
description: "UUID of Tenant owning this Port"
mac_address:
type: string
length: 17
required: true
description: "MAC address for Port"
validate: mac_address
admin_state_up:
type: boolean
required: true
description: "Admin state of Port"
status:
type: enum
required: true
description: "Operational status of Port"
values:
- 'ACTIVE'
- 'DOWN'
vnic_type:
type: enum
required: true
description: "Port should be attache to this VNIC type"
values:
- 'normal'
- 'virtual'
- 'direct'
- 'macvtap'
- 'sriov'
- 'whole-dev'
mtu:
type: integer
description: "MTU"
required: true
vlan_transparency:
type: boolean
description: "Allow VLAN tagged traffic on Port"
required: true
profile:
type: string # JSON Format
length: 128
description: "JSON string for binding profile dictionary"
format: json
device_id:
type: uuid
description: "UUID of bound VM"
device_owner:
type: string
length: 128
description: "Name of compute or network service (if bound)"
host_id:
type: string
length: 32
description: "binding:host_id: Name of bound host"
vif_details:
type: string # JSON Format
length: 128
description: "binding:vif_details: JSON string for VIF details"
format: json
vif_type:
type: string
length: 32
description: "binding:vif_type: binding type for VIF"
BaseInterface:
attributes:
id:
type: uuid
required: true
primary: true
description: "UUID of Interface instance"
port_id:
type: uuid
required: true
description: "Pointer to Port instance"
segmentation_type:
type: enum
required: true
description: "Type of segmentation for this interface"
values:
- 'none'
- 'vlan'
- 'tunnel_vxlan'
- 'tunnel_gre'
- 'mpls'
segmentation_id:
type: integer
required: true
description: "Segmentation identifier"
BaseService:
attributes:
id:
type: uuid
required: true
primary: true
description: "UUID of Service instance"
name:
type: string
length: 64
description: "Descriptive name of Service"
description:
type: string
length: 256
description: "Description of Service"
BaseServiceBinding:
attributes:
interface_id:
type: uuid
required: true
primary: true
description: "Pointer to Interface instance"
service_id:
type: uuid
required: true
description: "Pointer to Service instance"
API Specification
*****************
::
file_version: 1.0
imports: base/base.yaml
info:
name: net-l3vpn
version: 1.0
description "L3VPN API Specification"
author:
name: "Gluon Team"
url: https://wiki.openstack.org/wiki/Gluon
email: bh526r@att.com
objects:
Port:
api:
name: port
plural_name: ports
extends: BasePort
attributes:
alarms:
type: string
length: 255
description: "Alarm summary for port"
Interface:
api:
name: interface
plural_name: interfaces
parent: Port
extends: BaseInterface
VpnService:
api:
name: vpn
plural_name: vpns
extends: BaseService
attributes:
ipv4_family:
type: string
length: 255
description: "Comma separated list of route target strings"
ipv6_family:
type: string
length: 255
description: "Comma separated list of route target strings"
route_distinguishers:
type: string
length: 32
description: "Route distinguisher for this VPN"
VpnBinding:
extends: BaseServiceBinding
api:
name: vpnbinding
plural_name: vpnbindings
attributes:
service_id: # Override from base object for specific Service type
type: VpnService
required: true
primary: true
description: "Pointer to VpnService instance"
ipaddress:
type: string
length: 23
description: "IP Address of port"
format: ipv4
subnet_prefix:
type: integer
description: "Subnet mask"
format: int32
min: 1
max: 31
gateway:
type: string
length: 32
description: "Default gateway"
format: ipv4
VpnAfConfig:
api:
name: vpnafconfig
plural_name: vpnafconfigs
attributes:
vrf_rt_value:
required: True
type: string
length: 32
primary: 'True'
description: "Route target string"
vrf_rt_type:
type: enum
required: True
description: "Route target type"
values:
- export_extcommunity
- import_extcommunity
- both
import_route_policy:
type: string
length: 32
description: "Route target import policy"
export_route_policy:
type: string
length: 32
description: "Route target export policy"