Governance/Proposed/APIGuidelines

API Guidelines for Projects (DRAFT)
The intent of this page is to provide guidelines for OpenStack projects for the look and feel of their REST API interfaces in order that we have a consistent look and feel across all the projects. Changing the APIs of older projects is a long term process as need to retain backwards compatibility for users, but over time we can all slowly converge to a more consistent API. The initial version of the document is broadly based on the discussions at the cross project API consistency session at the Juno Design summit https://etherpad.openstack.org/p/juno-cross-project-consistency-across-rest-apis

'''Note: This documentation is currently very much in development - an alpha version for discussion amongst those from the various projects who are interested in cross project API consistency. Feel free to add comments and guidelines you think we need to standardise on.'''

API Terminology
Common Issues
 * tenant vs project
 * We should always use project.
 * instances vs servers
 * We should always use servers.

Extensions
Use of API extensions is generally discouraged, though historically many projects have them. Where we have extensions we should from the API client point of view have them look the same. If a project supports extensions they should support the following features:


 * Versioning
 * All extensions should have client visible versioning to be able to signal changes to the API (both backwards compatible and backwards incompatible changes. Versioning may be of the form of versions on individual extensions or an api-wide microversion which allows clients to select a specific version of an API.
 * Discoverability mechanism
 * Ceilometer capabilities http://docs.openstack.org/developer/ceilometer/webapi/v2.html#capabilities
 * Marconi use of home doc and JSON Schema https://wiki.openstack.org/wiki/Marconi/specs/api/v1.1#Get_Home_Document
 * Extensions should be kept to a minimum. The core API should be reviewed regularly to incorporate features which were formerly extensions
 * Too many extensions results in portability issues
 * Naming.
 * Should follow the following format flavor-manage
 * Eg [a-z-]+
 * No contractions

(jaypipes) I personally feel that API extensions should no longer be allowed in any new APIs in any OpenStack projects. Instead, response object schema and request payload schema discoverability should be implemented and the contributor community should do the HARD work of deciding on how to expose a certain resource to users of the API, instead of punting and adding in the ability to have different vendors implement the exact same resource in different API extensions. The more extensions we add to our APIs, the less interoperable we make our clouds. And we should be striving for MORE interoperability, not less.

API Namespace
This section is intended to provide guidelines for the specific parts of an HTTP request and/or response which an OpenStack API may and may not define. The behavior when an element outside the API namespace is included in a request is unspecified in general, but defined for official OpenStack implementations of the API specification.

HTTP Headers
HTTP request and response headers starting with X-OS- are reserved for use in OpenStack API specifications.

JSON Properties
All JSON properties which do not contain a : character in the property name are reserved for use in OpenStack API specifications. In addition, all JSON properties which begin with os: or os- are reserved for use in OpenStack API specifications. All other JSON properties are unreserved; their values are not specified, and should be silently ignored by official OpenStack implementations of an API.

Reserved JSON properties containing a : character should only be used by API extensions and/or optional functionality.

Query Parameters
Query parameters which do not contain a . character in the name are reserved for use in OpenStack API specifications. In addition, all query parameters which begin with os., os_, or os-</tt> are reserved for use in OpenStack API specifications. All other query parameters are unreserved; their values are not specified, and should be silently ignored by official OpenStack implementations of an API.

URIs
URIs are reserved according to the path segment immediately following the last path segment provided in the base address for the service in the user's service catalog. All path segments (in this location) which do not contain a -</tt> character are reserved for use in OpenStack API specifications. In addition, path segments (in this location) which begin with os-</tt> are reserved for use in OpenStack API specifications. All other path segments (in this location) are unreserved; official OpenStack implementations of an API should return a 401 or 404 for any request sent to such a URI (no other status code in the range [200, 499] is allowed for such a request).

The specification for individual resources within an API may further restrict the reserved URI space for the API by explicitly stating the restriction using the following form.


 * The ResourceName resource, identified by URIs starting with the form Form, only reserves URIs for use in OpenStack API specifications which [meet the specified rules / are characterized by / other?].

API Compatibility
Whether a change is considered backwards compatible or backwards incompatible is described here: https://wiki.openstack.org/wiki/APIChangeGuidelines

(jaypipes) The above page isn't guidance. It shows a bunch of things that are examples of mistakes that we've made with our current implementation of the APIs that rely on API extensions to convey changes to resources exposed in the API. However, that isn't guidance. Instead, we should have specific examples that show HOW to make a change to a future API in a backwards-compatible and discoverable way. We should provide guidance on, for instance:


 * How do I add a field to a resource exposed in a `GET /resources/$resource_id` API call?
 * How do I tell the client that there are additional fields possible in the request body to a `POST /resources` API call in a new version of the API?
 * How do I tell the client where to find information on available HTTP methods that can be used against a particular resource in the API?
 * How do I change a field name for a resource?
 * How do I change the name of a resource itself?
 * How do I remove a field from a resource?
 * How do I change the data type(s) that a field can take?

Accessing resources
Can we get some guidelines around when to use GET/PUT/POST/PATCH. And when to use URL parameters, HTTP headers or as data in the request body.


 * GET and HEAD must return the same exact information with exception of the body data (HEAD request does not return a body).
 * HEAD should not return a 204 if GET returns a 200 (for example)

HTTP Status Codes
Projects should follow RFC 2616 http://tools.ietf.org/html/rfc2616

However there has been some ambiguity or misinterpretation. Below are some OpenStack specific guidelines:

Success Codes

 * For async like calls where the action is not completed before returning a response use 202 Accepted.

Failure Codes

 * Out of quota errors (403 Forbidden). Do not use 413 Entity too large.
 * Do not use 422 Unprocessable Entity. Use 400 Bad Request instead

Error documents
What to return in the response body when a request fails. This was proposed:

{ "error": { "id": "<id of the error, a short string like user_not_found>", "operation": "<short name for the operation, like add_user_to_group>", "message": "Human language description of the problem.", "data": { "id": " ", ... }      }

Pagination and Filtering
TBD

POST/PUT body

 * snake_case rather than CamelCase should be used
 * when a parameter is dependent on an extension being loaded it should be prefixed with the extension name.
 * eg extension-name:parameter_name
 * This will avoid namespace clashes

POST/PUT body validation

 * have common validation patterns across OpenStack projects
 * Each project needs to use the other project resources like project-id, image-id, etc.
 * For consistent OpenStack interfaces, better to define common validation patterns for these resources and share them in whole OpenStack projects.

Resource naming

 * resources should be formed of lower case characters and hyphens between words.
 * No contractions.

Sam Harwell (talk): Can you clarify where these names apply? In particular, HYPHEN-MINUS is a challenge for resource names within an RFC 6570 URI Template because they must appear in their escaped form %2D</tt>. The "special characters" allowed in the names of variables in a URI template are LOW LINE (_</tt>) and FULL STOP (.</tt>).

Synchronous vs. Asynchronous APIs
Where possible, calls that trigger asynchronous actions—e.g., booting a new server—should return a handle for the operation itself, probably in addition to a handle for any newly created resource, such as the server in the example. The operation is what you would query for detailed status, and querying the resource should really only yield information for the state of the resource itself, as well as links to pending operations. This would also allow operations to be queued for later, and allow them to be canceled.