← Back to team overview

openstack team mailing list archive

Re: OpenStack API Versioning Conventions

 

On 13/10/2011, at 5:42 PM, Bryan Taylor wrote:

> On 10/12/2011 07:55 PM, Mark Nottingham wrote:
>>> The duplication of effort can be solved by having an intermediary do the translation. Repose already does this.
>>> 
>> That's where there be dragons. Inferring that the user wants to go to version N of the resource because they request version M of the representation conflates format versioning with API versioning. They are not the same.
>> 
> What do you mean by "version N of the resource"? We version languages to describe things, not the things themselves. Usually the resources are real world instances in our business domain that only know their current real-world state. We come up with different recipes to project that state onto to a representation if it makes sense. 

I mean that, over time, the resources themselves may change; e.g., adding new parameters, adding new methods, changing the semantics of POST, etc. This is different than versioning the format of a representation of a resource. 

Of course, some of these changes may be backwards compatible -- in which case no versioning is necessary. On top of that, most other backwards-incompatible changes can be transformed into backwards-compatible ones by minting them as new resources; e.g., instead of changing the semantics of /foo, create /foo/a (or /bar) to encapsulate the new semantics.

All of that said, there will come a time when the evolution of the API gets "messy", and it's desirable to mint a new API version number; e.g., /v2/. That's what I'm talking about.


>>>  We deal with the correspondence between versioned URIs and media types by adopting a single structure rule that is non-RESTful: /v1/foo and /v2/foo are implicitly understood to be variants of /foo .
>>> 
>> Why? If you wipe the slate clean and start a /v2 API, the whole idea is that it's not backwards-compatible with v1. Predicating it on v1 just ties your hands.
>> 
> The API may break backwards compatibility as a whole, but contain resources that continue to make sense. Breaking backwards compatibility does not require a burn-the-bridges break with the past. Here's an example:
> 
> Lets say in v1 of my API I have servers and they have IPs . Resources are like so:
> http://cloud.net/servers/456
> http://cloud.net/servers/456/ips
> http://cloud.net/ip/200.100.99.98
> 
> I realize I want to model multiple NICs and that a server's IPs aren't direct children of the server any more, but require their NIC:
> http://cloud.net/servers/456
> http://cloud.net/servers/456/eth0/ips
> http://cloud.net/servers/456/eth1/ips
> http://cloud.net/ips/200.100.99.98
> 
> This breaks backwards compatibility of the API as servers with multiple NICs no longer  honor the WADL template http://cloud.net/server/{server_number}/ips . Such servers would also only support the v2 media type app/vnd.server;version=2 at http://cloud.net/server/{server_number} as now we split the IP list up under each listed NIC .Note if I have a server with one NIC, it can continue to work fine with either v1 or v2.

Are you saying that the server is changing the layout of URIs based upon the Accept header? Why would you put that information in the media type, of all places? Representation formats and resources are fundamentally orthogonal on the Web. 

A sensible way of addressing that would be to still support /456/ips, but to also allow /456/eth0 et al. Even better, find a way to structure your URIs where there isn't a (very small) potential of collision.


Cheers,


--
Mark Nottingham   http://www.mnot.net/





References