22 KiB
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.
Operation | URL | Description |
---|---|---|
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.
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.
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
Type | Description | Associated Properties |
---|---|---|
integer | Integer number |
|
number | Floating point number | n/a |
string | Text String |
|
boolean | Boolean value (true/false) | n/a |
uuid | Text string in UUID format | n/a |
enum | Text string from a list of values |
|
File Structure
The API is defined by a single file. The Root Object is defined by the ProtonDef object. See the complete Example at the end of this page for an example of the ProtonDef syntax.
ProtonDef
Fixed Field | Type | Required | Description |
---|---|---|---|
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
Fixed Field | Type | Required | Description |
---|---|---|---|
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
Fixed Field | Type | Required | Description |
---|---|---|---|
name | string | true | Name of the author |
url | string | false | URL to author website |
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
Pattern Field | Type | Required | Description |
---|---|---|---|
[_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
Fixed Field | Type | Required | Description |
---|---|---|---|
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
Fixed Field | Type | Required | Description |
---|---|---|---|
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
Fixed Field | Type | Required | Description |
---|---|---|---|
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.
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
Pattern Field | Type | Required | Description |
---|---|---|---|
[_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
Fixed Field | Type | Required | Description |
---|---|---|---|
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
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"