Actually, we haven't broken (on purpose) the API in a long time. Let's make
sure we're clear on what "breaking" changes are NOT.

They are NOT:


   - Adding new endpoints to the API
   - Adding new attributes to the response of an existing endpoint

^^ In my experience, this tends to be the bulk of our API changes which
just warrants a minor upgrade...

And I hope we're not changing the datatype of a minor field 13 times :)

On Thu, Oct 19, 2017 at 3:50 PM, Chris Lemmons <alfic...@gmail.com> wrote:

> I thought about that. But I'd like to reserve the major version of TC
> for actually major things. Making the API control the TC version
> number feels like the tail wagging the dog. Most other projects don't
> do it that way, either.
>
> It might not be so bad, except that we make breaking changes on a
> fairly regular basis. It would feel weird revving TC to version 14
> simply because we changed the datatype of a minor field for the 13th
> time.
>
> And likewise, sometimes we don't change the API. At the moment, we're
> pretty API-focused. But focuses change and we might have whole
> releases focused on UI or integrations. It would be strange to rev the
> API when it didn't change. The point of Semantic Versioning is to
> communicate changes to the API in a way that is consistent, easy to
> apply, and grokkable by humans and computers alike.
>
> I think I'm still -1 on locking the API version to the TC version.
>
> On Thu, Oct 19, 2017 at 3:39 PM, Robert Butts <robert.o.bu...@gmail.com>
> wrote:
> > @alficles What if we do both Semantic Versioning, and tying the API
> version
> > to the TC version? So, we would have to increase the TC major version
> with
> > any breaking API changes (which may inconveniently be minor to the rest
> of
> > TC).
> >
> > But, that has the big advantage of letting us programmatically tie the TC
> > version to every client. So, with a small upfront cost writing the code
> to
> > read the `/VERSION` file into the client binaries when the RPM is
> > built--for example, in Go with ```-ldflags "-X lib.Version=`cat
> > ../VERSION`"``, and then concatenating that string into the endpoint
> > request---we could synchronise all our versions, and essentially not have
> > to think about versions, not have to manually update clients, not have to
> > worry about what endpoint was added in what version.
> >
> > That alleviates a huge percentage of the brain and keyboard work we
> > currently have to do surrounding versioning.
> >
> >> Our API version should have 3 numbers, though: major, minor, patch
> >
> > -1 on putting the patch in the URI, it's verbose and unnecessary, bug
> fixes
> > don't make things incompatible and are unlikely to cause confusion.
> > +1 on putting the patch in a header, e.g. `X-API-Version: 1.3.deadbeef`.
> > Header makes it easy to debug, in the rare event it's necessary, without
> > cluttering the URI or Body.
> >
> >
> > On Thu, Oct 19, 2017 at 3:14 PM, Chris Lemmons <alfic...@gmail.com>
> wrote:
> >
> >> Heh, I agree on the arguing about API versions, but I just want to
> >> hand the task to Semantic Versioning, so we can just ask some simple
> >> questions like "did we break backward compatibility" and "did we add
> >> something" and figure out what number to put on the route. And we
> >> avoid arguments entirely. (We have to get used to the idea of revving
> >> the top version, though, because we break compatibility a lot.)
> >>
> >> On Thu, Oct 19, 2017 at 3:01 PM, Jeremy Mitchell <mitchell...@gmail.com
> >
> >> wrote:
> >> > In reality, we really did break the API when we went from mysql (TC
> 1.8)
> >> to
> >> > postgres (TC 2.0) and strings became ints, for example, so the api
> should
> >> > really be 2.x anyhow imo.
> >> >
> >> > Anyhow, the real reason i like syncing the api version to the TC
> version
> >> is
> >> > for simplicity and we don't have to argue all day about api versions.
> :)
> >> >
> >> >
> >> >
> >> >
> >> >
> >> > On Thu, Oct 19, 2017 at 2:54 PM, Chris Lemmons <alfic...@gmail.com>
> >> wrote:
> >> >
> >> >> Interesting idea. I think, though, it's better to keep API versions
> >> >> separate from TC versions. Many versions of TC won't rev the API at
> >> >> all. I'd prefer to go all in on Semantic Versioning.
> >> >>
> >> >> I think it could work like this. For a given route, use the route
> >> >> defined for the most recent version not later than the requested
> >> >> version. So, if the quux endpoint is introduced at 1.2, and changed
> at
> >> >> 1.4, these requests would be served by these routes:
> >> >>
> >> >> GET /api/1.1/quux → 404
> >> >> GET /api/1.2/quux → Served by 1.2.
> >> >> GET /api/1.3/quux → Served by 1.2.
> >> >> GET /api/1.4/quux → Served by 1.4.
> >> >> GET /api/1.5/quux → Served by 1.4.
> >> >>
> >> >> The advantage of this is that it's relatively easy to implement in
> the
> >> >> router, though there are admittedly some challenges on the Perl side
> >> >> of things. If we want to be clever, we can allow a client to elide
> >> >> later values and just assume they meant the latest. But we don't need
> >> >> to start out clever.
> >> >>
> >> >> Our API version should have 3 numbers, though: major, minor, patch.
> We
> >> >> should expose these versions in a new /version endpoint that will
> >> >> allow clients to self-configure and detect new versions.
> >> >>
> >> >> As an alternative to strict semantic versioning, we could consider
> the
> >> >> first two numbers to be the "major" number for Semantic Versioning
> >> >> purposes. I think this hurts discoverability in the community, but it
> >> >> matches our current practice, for the most part. I think this would
> be
> >> >> a reasonable compromise, if people aren't comfortable increasing the
> >> >> first number every time we break compatibility in a revision.
> >> >>
> >> >> Lastly, we should recognize that we may need to retire API versions.
> >> >> Eventually, we may make changes to the DB that mean the information
> >> >> provided in a prior version simply does not exist. To that end, we
> >> >> should provide a /minversion (or similar) endpoint that returns the
> >> >> lowest API version supported by that server. Queries below that value
> >> >> cannot be guaranteed to succeed. (Or would it be better to cut it off
> >> >> an say that no queries for previous versions are permitted?)
> >> >>
> >> >> I'm +1 on Semantic Versioning. I'm a lukewarm +1 on a variant that
> >> >> uses the first two numbers as "major" and the last as "minor". I'm -1
> >> >> on locking it to the version of TC. I'm +1 on providing /version and
> >> >> /minversion endpoints to allow clients to auto-detect
> incompatibility.
> >> >>
> >> >> On Thu, Oct 19, 2017 at 12:54 PM, Jeremy Mitchell <
> >> mitchell...@gmail.com>
> >> >> wrote:
> >> >> > With the Golang API rewrite, we were not planning to break any APIs
> >> but
> >> >> > rather simply port them to Golang thus we did not see the need to
> rev
> >> the
> >> >> > API version from 1.2. However, maybe this is good opportunity to
> get
> >> our
> >> >> > API version inline with the TC version.
> >> >> >
> >> >> > So, my thought is that our Golang API's look like this:
> >> >> >
> >> >> > GET /api/v2.2/foos <-- this would return foos served by golang
> because
> >> >> > we've ported this endpoint
> >> >> > GET /api/v2.2/bars <-- this would return a 404 served by golang
> >> because
> >> >> > we've have NOT yet ported this endpoint
> >> >> >
> >> >> > and our perl apis are still acessible in 1.2
> >> >> >
> >> >> > GET /api/1.2/foos <-- this would return foos served by perl
> >> >> > GET /api/1.2/bars <-- this would return bars served by perl
> >> >> >
> >> >> > This has 3 benefits:
> >> >> >
> >> >> > 1. by revving the version, it signals the community that something
> has
> >> >> > actually changed in our API and in this case, the change may
> simply be
> >> >> the
> >> >> > fact that we now have nifty golang implemented APIs that you might
> >> want
> >> >> to
> >> >> > explore.
> >> >> > 2. it provides the ability to stay on the perl apis by specifying
> 1.2
> >> if
> >> >> > that is what you want to do. maybe you are not much of a risk
> taker...
> >> >> > 3. it does actually provide license to break the new golang apis if
> >> >> needed
> >> >> > (to make them better) because the major version has incremented.
> it's
> >> >> nice
> >> >> > to have that option if needed.
> >> >> >
> >> >> > Also, going forward, I propose the TO API version follows in
> lockstep
> >> >> with
> >> >> > the TC version...which means the minor version will keep
> >> >> incrementing...GET
> >> >> > /api/v2.2/foos...GET /api/v2.3/foos..which means functionality can
> be
> >> >> added
> >> >> > to the API "in a backwards-compatible manner"
> >> >> >
> >> >> > Remember, at some point TO will only be the TO API so why wouldn't
> >> this
> >> >> > component follow the versioning that the other components do? Just
> my
> >> >> > thoughts.
> >> >> >
> >> >> > Jeremy
> >> >> >
> >> >> > On Tue, Oct 17, 2017 at 12:02 PM, Robert Butts <
> >> robert.o.bu...@gmail.com
> >> >> >
> >> >> > wrote:
> >> >> >
> >> >> >> I'm fully +1 on Semantic Versioning. We discussed it briefly on
> the
> >> >> list a
> >> >> >> long time ago, but we haven't really been doing it.
> >> >> >>
> >> >> >> That said, versioning requires a lot of code/work that simply
> doesn't
> >> >> exist
> >> >> >> today. That's the reason we haven't been doing it properly.
> >> >> >>
> >> >> >> The Go Traffic Ops has Semantic Versioning built-in to the
> Routing,
> >> but
> >> >> >> Perl support is close to nil. Perl currently has an easy way to
> say
> >> >> >> "include all the routes in this version number", But there's no
> way
> >> to
> >> >> say
> >> >> >> "this route is 1.2 only, and this route is 1.3 only" -- we'd have
> to
> >> >> >> duplicate TrafficOpsRoutes.pm, with only a few lines changed, and
> >> >> likewise
> >> >> >> duplicate changed functions. It needs a framework. Or we could
> just
> >> wait
> >> >> >> until Perl goes away.
> >> >> >>
> >> >> >> That said, Go, especially the client, doesn't completely support
> >> Minor
> >> >> >> Versions like it should, either. Consider adding a new field to
> >> Delivery
> >> >> >> Services. Per Semantic Versioning, that field MUST not be
> returned by
> >> >> the
> >> >> >> old version `GET`, and MUST not be set if passed by a `POST`. The
> Go
> >> >> server
> >> >> >> supports that in the Routing, via different endpoints, but
> there's no
> >> >> >> Struct framework or pattern. And the client completely doesn't
> >> support
> >> >> it.
> >> >> >> In Go, we probably need a set of anonymously-nested structs, `type
> >> >> >> DeliveryServices12 struct { Foo int }; type DeliveryServices13
> struct
> >> >> >> {DeliveryServices12; Bar string}`. But that simply doesn't exist
> >> today,
> >> >> and
> >> >> >> will take development time to write.
> >> >> >>
> >> >> >> Option 2: Absolute Versioning. Instead of Semantic Versioning, we
> >> could
> >> >> >> have a single version, and break compatibility with each new
> version.
> >> >> So,
> >> >> >> all new features (breaking or not) would go in a new version, and
> all
> >> >> >> clients must check the version, and refuse to operate on a
> different
> >> >> >> version. So you'd be required to have a client version matching
> the
> >> >> server
> >> >> >> version; users are not allowed to talk to new servers with old
> >> clients.
> >> >> >>
> >> >> >> Option 3: No Versioning. We get rid of the version number.
> Endpoints
> >> >> are at
> >> >> >> `/api/foo`. Over the last few years, we have _repeatedly_ broken
> the
> >> API
> >> >> >> for the same version. A 1.2 client from three years ago will fail
> >> >> >> catastrophically if connected to a Traffic Ops serving `/api/1.2`
> >> >> today. In
> >> >> >> practice, as we've been developing, we have no version, the
> version
> >> >> number
> >> >> >> is meaningless and confusing. If we're going to continue breaking
> >> >> >> compatibility without updating the version number, we should get
> rid
> >> of
> >> >> it.
> >> >> >> Then at least the version itself won't be confusing and painful.
> >> >> >>
> >> >> >> What's the consensus here? Does everyone agree with Semantic
> >> >> Versioning? Do
> >> >> >> we want to commit to requiring it? Is there a consensus? Or
> should we
> >> >> take
> >> >> >> a vote, whether to require Semantic Versioning, Absolute
> Versioning,
> >> or
> >> >> No
> >> >> >> Version?
> >> >> >>
> >> >> >>
> >> >> >> On Thu, Oct 12, 2017 at 7:39 AM, Dave Neuman <neu...@apache.org>
> >> wrote:
> >> >> >>
> >> >> >> > Traffic ops currently does not handle versioning very well.  I
> >> think
> >> >> we
> >> >> >> do
> >> >> >> > support 1.1 and 1.2 versions of the API, but I think there are
> >> only a
> >> >> few
> >> >> >> > (maybe asns and deliveryservices) that are actually different.
> >> >> >> > Versioning is something we look to improve as we move to the
> golang
> >> >> >> version
> >> >> >> > of the API.
> >> >> >> >
> >> >> >> > On Thu, Oct 12, 2017 at 6:50 AM, Eric Friedrich (efriedri) <
> >> >> >> > efrie...@cisco.com> wrote:
> >> >> >> >
> >> >> >> > > Does Traffic Ops expose a semantic version number as part of
> its
> >> >> API?
> >> >> >> > >
> >> >> >> > > http://semver.org/
> >> >> >> > > "Given a version number MAJOR.MINOR.PATCH, increment the:
> >> >> >> > >
> >> >> >> > >   1.  MAJOR version when you make incompatible API changes,
> >> >> >> > >   2.  MINOR version when you add functionality in a
> >> >> >> backwards-compatible
> >> >> >> > > manner, and
> >> >> >> > >   3.  PATCH version when you make backwards-compatible bug
> fixes.
> >> >> >> > >
> >> >> >> > > “
> >> >> >> > >
> >> >> >> > > We have some TO clients and would like to improve their
> backwards
> >> >> >> > > compatibility. Without this version number, it is not easy to
> >> >> determine
> >> >> >> > > which fields in the API are supported by any given version.
> >> >> >> > >
> >> >> >> > > Thanks,
> >> >> >> > > Eric
> >> >> >> > >
> >> >> >> > >
> >> >> >> >
> >> >> >>
> >> >>
> >>
>

Reply via email to