+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