[openstack-dev] [api] [Nova] [Ironic] [Magnum] Microversion guideline in API-WG
dtantsur at redhat.com
Mon Jun 22 07:51:00 UTC 2015
On 06/20/2015 02:14 AM, Devananda van der Veen wrote:
> Almost all of our discussions so far on this topic have left something
> out, which Monty pointed out to me last week. I'm following up now
> because E_TRAVEL...
> What we're versioning here are API's, not packages. It's not a question
> of numbering and dependency ordering, but of communicating
> support[ed|able] interfaces between running services. Libtool is more
> relevant than semver.
> Right now we lack a means to express that the API response is
> "compatible-with" a particular previously-released version of the API.
> If we had that, instead of "current-version", I believe we would have
> much happier users (and a happier Dmitry and jroll).
> Long version...
> Every HTTP response from Ironic today includes three headers: min, max,
> and version. The service can present an older API version, as long as it
> is greater-than-or-equal-to the minimum supported version, even if that
> version is incompatible with the maximum supported version. It does
> this by rewriting responses to match what was expected in the requested
> (older) version.
> When the newer version is identical *for all interfaces present* in the
> older version, this can be called compatible. Dmitry's point is that we
> don't need to hide newer interfaces from users who request an older API
> version, because the client won't know or care about things that weren't
> in the version it requested.
> However, we *do* need to signal their presence, and we don't have a good
> means for that right now. We also need to signal to the client that the
> response given is "compatible with" a certain "age" of API, even if it's
> not exactly the same. And we don't have any means for that, either.
> Time for an example....
> Let's say that an incompatible change was made in v1.3. Let's also say
> that a change was made in v1.5 that added a new endpoint. Today, this is
> what the response headers would look like when calling a server running
> a) client requests v1.2, receives headers (min: 1.1, max: 1.5, current:
> 1.2) b) client requests v1.4, receives headers (min: 1.1, max: 1.5,
> current 1.4) c) client requests v1.5, receives headers (min: 1.1, max:
> 1.5, current: 1.5)
> What we have implemented today is that in case (b), the service will
> *hide* any changes that we introduced in v1.5. But those changes did not
> affect any functionality of the v1.4 API, so Dmitry objects to this. So
> do I.
> The issue at hand is the response in case (b) ... though after spending
> the last several months working on api versioning, I actually think all
> of those are poor responses.
> What I believe we should have:
> a) client requests v1.2, receives headers (min: 1.1, max: 1.5,
> compatible-with: 1.1)
> b) client requests v1.4, receives headers (min: 1.1, max: 1.5,
> compatible-with: 1.3)
> b) client requests v1.5, receives headers (min: 1.1, max: 1.5,
> compatible-with: 1.3)
That sounds really like something people actually want from us.
Just one clarifying question: shouldn't b) and c) be compatible-with:
1.4, as 1.4 was a breaking change?
> Yes -- (b) and (c) are identical responses.
> On Tue, Jun 16, 2015 at 7:13 AM Dmitry Tantsur <dtantsur at redhat.com
> <mailto:dtantsur at redhat.com>> wrote:
> On 06/16/2015 03:47 PM, Jim Rollenhagen wrote:
> > On Tue, Jun 16, 2015 at 08:56:37AM +0200, Dmitry Tantsur wrote:
> >> On 06/04/2015 08:58 AM, Xu, Hejie wrote:
> >>> Hi, guys,
> >>> I’m working on adding Microversion into the API-WG’s guideline
> >>> make sure we have consistent Microversion behavior in the API
> for user.
> >>> The Nova and Ironic already have Microversion implementation,
> and as I
> >>> know Magnum _https://review.openstack.org/#/c/184975/_ is going to
> >>> implement Microversion also.
> >>> Hope all the projects which support( or plan to) Microversion
> can join
> >>> the review of guideline.
> >>> The Mircoversion specification(this almost copy from nova-specs):
> >>> _https://review.openstack.org/#/c/187112_
> >>> And another guideline for when we should bump Mircoversion
> >>> _https://review.openstack.org/#/c/187896/_
> >>> As I know, there already have a little different between Nova and
> >>> Ironic’s implementation. Ironic return min/max version when the
> >>> version doesn’t support in server by http-headers. There isn’t such
> >>> thing in nova. But that is something for version negotiation we
> need for
> >>> nova also.
> >>> Sean have pointed out we should use response body instead of http
> >>> headers, the body can includes error message. Really hope
> ironic team
> >>> can take a
> >>> look at if you guys have compelling reason for using http headers.
> >>> And if we think return body instead of http headers, we
> probably need
> >>> think about back-compatible also. Because Microversion itself isn’t
> >>> versioned.
> >>> So I think we should keep those header for a while, does make
> >>> Hope we have good guideline for Microversion, because we only
> can change
> >>> Mircoversion itself by back-compatible way.
> >>> Thanks
> >>> Alex Xu
> >> Hi all!
> >> I'd like to try put in feedback based on living with
> microversions in Kilo
> >> release of Ironic.
> > And here's my take, based on my experiences. Keep in mind I'm a core
> > reviewer, a developer, and an operator of Ironic.
> Thanks Jim, much appreciated!
> > From an ops perspective, our team has built our fair share of
> tooling to
> > help us run Ironic. Some of it uses the REST API via python or
> > and of course we all use the CLI client often.
> > We also continuously deploy Ironic, for full transparency. My
> > is not with how this works every 6 months, but in the day-to-day.
> >> First of all, after talking to folks off-list, I realized that
> we all, and
> >> the spec itself, confuse 3 aspects of microversion usage:
> >> 1. protecting from breaking changes.
> >> This is clearly a big win from user's point of view, and it
> allowed us to
> >> conduct painful change with renaming an important node state in
> our state
> >> machine. It will allows us even worse change this cycle: change
> of the
> >> default state.
> > +1. Good stuff. My tooling doesn't break when I upgrade. Yay.
> >> 2. API discoverability.
> >> While I believe that there maybe be better implementation of
> this idea, I
> >> think I got it now. People want services to report API versions they
> >> support. People want to be able to request a specific version,
> and fail
> >> early if it is not present. Also +1 from me.
> > I don't tend to personally do this. I usually am aware of what
> > of Ironic I'm running against. However I see how this could be useful
> > for other folks.
> > I do, however, use the versions to say, "Oh, I can now request
> 1.5 which
> > has logical names! That's useful, let's set those to the names in our
> > CMDB." Now my tooling that interacts with the CMDB and Ironic can
> > at the version and decide to use node.name <http://node.name>
> instead of the old hack we
> > used to use.
> >> 3. hiding new features from older clients
> >> This is not directly stated by the spec, but many people imply
> it, and Nova
> >> and Ironic did it in Kilo. I want us to be clear: it is not the
> same as #2.
> >> You can report versions, but still allow new features to be used.
> > This is still totally useful. If you know what version you are
> > against, you know exactly what features are available.
> "You know" is about #2 - that's where confusion is :)
> so if you know, that moving to inspection state is disallowed for your
> tooling (but not for the whole system!), what does it give you?
> > I think the disconnect here is that we don't expect users
> (whether those
> > are people or computers) to explicitly request a version. We need to
> > message better that if you are using Ironic or building a tool
> > Ironic's API, you should be pinning the version. We also need to take
> > this comment block and put it in our docs, so users know what each
> > version does.
> > Knowing that I get feature X when I upgrade to version Y is useful.
> >> It is this particular thing that gets -2 from me, after I've
> seen how it
> >> worked in practice, and that's why.
> >> First of all, I don't believe anyone needs it. Seriously, I
> can't imagine a
> >> user asking "please prevent me from using non-breaking changes".
> And attempt
> >> to implement it was IMO a big failure for the following reasons:
> >> a) It's hard to do. Even we, the core team, got confused, and
> for non-core
> >> people it took several iteration to do right. It's a big load on
> >> developers and reviewers.
> > I do agree with this. It's been painful. However, I think we're
> > past that pain at this point. Does this patch look like developer
> > pain?
> It's not that painful to write. Now. When we have 10-20 version, it
> probably will :)
> anyway, it's hard to explain newcomers how to do it, and it's hard to
> review the result. we failed at it, e.g. with error codes.
> >> b) It's incomplete (at least for Ironic). We have several
> API-exposed things
> >> that are just impossible to hide. Good example are node states:
> if node is
> >> in a new state, we can't but expose it to older tooling. Our
> free-form JSON
> >> fields properties, instance_info, driver_info and
> driver_internal_info are
> >> examples as well. It's useless to speak about API contract,
> while we have
> >> those.
> > I somewhat agree here.
> > With node states, there are cases where we were able to hide it
> > (NOSTATE -> AVAILABLE), and cases where we were not (adding
> > However, this list of states is (AIUI) not part of the API contract;
> > rather the verbs available to move between states are.
> What's the point in contract, if there are things not covered by it that
> drastically change the system behavior?
> > As far as JSON fields, we've never had a contract around what
> keys are
> > available. Only the semantics of working with those fields, and which
> > fields exist.
> ditto as above: you can request new features by modifying driver_info.
> >> c) It gives additional push back to making (required) breaking
> changes. We
> >> already got suggestions to have ONE MORE feature gating for breaking
> >> changes. Reason: people will need to increase microversions to
> get features,
> >> and your breaking change will prevent it.
> > This is just silly. If 1.10 breaks a user, and the user wants 1.11,
> > they'll need to fix that breakage.
> ++ but not everyone agreed on the summit, when I was talking about
> ENROLL state
> >> d) It requires a hard compromise on the CLI tool. You either
> default it to
> >> 1.0 forever, and force all the people to get used to figuring
> out version
> >> numbers and using `ironic --ironic-api-version x.y` every time
> >> user experience), or you default it to some known good version,
> bumping it
> >> from time to time. This, in turn, has 2 more serious problems:
> > I disagree that pinning a version all the time is a terrible
> > We already require a number of options for authentication
> > OS_PASSWORD, etc etc). How many folks do you think type these in
> > time? Solution is simple: add IRONIC_API_VERSION to whatever
> exports the
> > other environment variables.
> It's not that bad, especially if devstack/tripleo will provide some
> reasonable default for you.
> I remember, however, Devananda didn't like the idea.
> And it definitely makes a quick start guide a bit harder to follow. I
> already imagine how many people will forget about this pinning (either
> to do it, or do update when they need new features).
> > The version depends on the environment you are running against -
> why not
> > treat it as such?
> >> d.1) you start to break people \o/ that's not a theoretical
> concern: our
> >> downstream tooling did get broken by updating to newer
> ironicclient from git
> > As I said before, we need to encourage folks to pin client
> versions if
> > they don't want to break. I'm probably alone here, but I would even
> > propose making the version *required*. Force people to think
> about what
> > they are doing. If folks are okay with being broken, they can pass
> > "latest".
> Could be a good default for devstack btw
> >> d.2) you require complex version negotiations on the client
> side. Otherwise
> >> imaging CLI tool defaulting to 1.6 will issue `node-create` to
> >> supporting only 1.5. Guess what? It will fail despite
> node-create being very
> >> old feature. Again, that's not something theoretical: that's how
> we broke
> >> TripleO CI.
> > Again, pin it.
> >> e) Every microversion should be fully tested separately. Which
> ended up in
> >> Ironic having 4 versions 1.2-1.5 that were never ever gate
> tested. Even
> >> worse, initially, our gate tested only the oldest version 1.1,
> but we solved
> >> it (though it took time to realize). The only good thing here is
> that these
> >> versions 1.2-1.5 were probably never used by anyone.
> > Hi. I've used some of these. :)
> You didn't tell me last time we talked :) note, that you didn't use
> them, unless you explicitly requested, because IIRC we never defaulted
> our client to any of these. So for most people, even deploying from
> master, it was 1.1 -> 1.6.
> > // jim
> > 
> > 
> >> To sum this long post up, I'm seeing that hiding new features
> based on
> >> microversions brings much more problems, than it solves (I'm not
> aware of
> >> the latter at all). I'm very opposed to continuing doing it in
> Ironic, and
> >> I'm going to propose patch stopping gating Kilo changes
> >> obviously).
> >> Hope that helps,
> >> Dmitry
> OpenStack Development Mailing List (not for usage questions)
> Unsubscribe: OpenStack-dev-request at lists.openstack.org?subject:unsubscribe
More information about the OpenStack-dev