+1

I agree with Jonathan but, I ran into my issue going from one TC release to the next. I want to have the API not break as long as that API is supported.

I also don't want to have to use multiple versions of the API in my script unless I absolutely have to for some reason on my end. I want to be able to define the API version at the top of my script and use that version all the way through my script.

I don't really care if more fields are returned. I may not be using all of the fields anyway. I do care if some of the fields disappear but, the API version I am using is supposed to not have changed.

I guess what I am realizing is my issues with the API may not be about how it is versioned at all but, about testing to make sure the supported versions have not changed in the way they work. I brought up versioning because it seemed that would help with the breaking changes issue.

There used to be a matrix of the API routes (that I can't seem to find now). When API version 1.3 came out, why could I not call 1.3 for every API route even if the route didn't change? Why not point the 1.3 to the 1.1 for example?

Perhaps part of the issue is not deprecating things fast enough and not incrementing the major version fast enough? If we release a new major version of TC every 6 mos. as we are trying for but, not always succeeding, we could deprecate faster and scripts would be supported for a year. If we could get to a point where we could support a 2 major release versions of TC this would mean a script would be supported for 2 years.

Which brings me back to my original thoughts on API versioning:

1. The URL for the API should follow the TC major version (e.g. http://.../api/v3/...) 2. TC 3.x.x would support v2 (with a warning message that it is obsolete) and v3 of the API. 3. TC 4.x.x would support v3 (with a warning message that it is obsolete) and v4 of the API. 4. A user of the API should not have to call v1.2, v1.3, and v1.4 in the same script. This would be taken care of with 1, 2, and 3 above. 5. In the documentation, define "backward compatible" as new fields will be introduced within a major version and will be presented in a GET but, not available for a POST (and specify a default in the documentation). 6. If a user really wants to know the specific version (x.x.x) of the API there should be an API route (e.g. https://.../api/v3/version).

I changed 5 a bit from my original thoughts.

I am not helping to develop the API, unfortunately. This is what I see as a user of the API.

-Hank

On 4/18/19 12:37 PM, Gray, Jonathan wrote:
At the end of the day, what I want is a consistent API that I can code against 
in the head of master that's treated like a contract.  As an API user outside 
of the ATC repo it's incredibly frustrating to have my stuff break all the 
time.  It basically encourages never developing using the latest API versions 
(regardless of how they're defined and even then things still break 
retroactively) or a non-official OSS release alltogether.  It's a catch22 to be 
forced to either not vendor the go/python/bash libraries which leads to 
constant develop/recompile/deploys in lockstep with ATC or vendor and still 
have to do these things when stuff breaks anyway in the API.  Really debating 
the native client libraries at all is just a red herring because the root issue 
is the HTTP API itself which is the real thing to care about since not all 
integrations use one of the client libraries, nor can be forced to do so, and 
may require a rigid API definition.

Jonathan G


On 4/18/19, 10:12 AM, "Rawlin Peters" <[email protected]> wrote:

     > The UPDATE statements need modified to fix #3497 even if we get rid of
     > versioning. Unless we decide to permanently break all clients older than
     > the newest server field, with every new server upgrade. The only other
     > option is to fix the updates. Unless you know of a way to fix missing
     > fields without changing the update statements, that I'm not seeing?
By removing minor versioning, only certain clients that don't handle
     new unknown fields would potentially be broken, and I believe only the
     TO Go client has that problem in our repo. However, the TO Go client
     happens to use the same Go structs as traffic_ops_golang, so whenever
     new fields are added to the API, all the client has to do is recompile
     with the up-to-date structs. Unless we made breaking changes to the
     client, in most cases all that would be needed for those clients is a
     recompile. Traffic Portal, the Python TO client, and I'm pretty sure
     the Java TO client all handle unknown fields properly.
Without minor versions, #3497 would not even an issue. It's only an
     issue because of the attempt to support minor versioning. If we just
     support the major version, all client requests would be treated as v1,
     and there would only ever be one SQL UPDATE statement per major
     version. We wouldn't need to "upgrade" 1.2 requests into a 1.4 struct
     (thus preventing the bug in #3497) by selecting and inserting all 1.4
     values from the DB into the struct before handling the request or
     dynamically generating the SQL UPDATE statement to use based on the
     requested minor version.
> So, this solution actually gives us
     > this bug fix almost for free. All that's required is another small 
function
     > to iterate over the object fields to create the update query. It's by far
     > the easiest and simplest fix for #3497; unless we also permanently break
     > all older clients on every server upgrade along with the minor version
     > removal.
Switching all the endpoints over to your "apiver" library would not be
     as trivial to implement or remove as you make it sound. It would
     require lots of added API test coverage and a non-trivial amount of
     code modifications to all API endpoints. Certain UPDATE queries might
     be easy to generate from a given struct if the struct only uses a
     single table, but I don't think something like that would work for a
     field like `cachegroup.LocalizationMethods` which doesn't come from
     the cachegroups table and is updated separately from the rest of the
     cachegroup fields.
- Rawlin

Reply via email to