openservicebrokerapi / servicebroker

Open Service Broker API Specification
https://openservicebrokerapi.org/
Apache License 2.0
1.19k stars 433 forks source link

Support async binding operations #137

Closed bmelville closed 6 years ago

bmelville commented 7 years ago

Binding to an instance may encapsulate a long running workflow, similar to creating an instance. This might include provisioning new user accounts in a service, setting up firewalls, etc. It seems like the Bind API would benefit from the same last_operation model that Provision uses, and I'd like to get feedback from others who may have more context around this.

Latest proposal: https://github.com/mattmcneeney/servicebroker/blob/async-bindings/spec.md#binding

duglin commented 7 years ago

@vaikas-google I agree that returning it on the 202 makes little sense, but having the spec say it SHOULD be there is going to be problematic - because SHOULD is a soft-MUST. I'd like to get @shalako's take on why it isn't a MUST to better understand the original intent - that might provide some insight into whether we can change it to a MAY instead - which I think is the best we can do on that.

My reasons for allowing the creds to flow back on the final last_operation response is that it just feels like a waste of effort to force all platforms to issue a second request every time. Also not everyone will support GET so we'll need to get the creds for an async request w/o it. Which means there will be some scenarios where the last_op response will be the only way to get the creds - so for consistency it seems like it should be in there regardless of whether GET is supported or not.

vaikas commented 7 years ago

Seems like since there are no brokers that support async ops for bindings (this is for bindings only, right?), it seems that we have a bit of an opportunity to create a good flow that makes sense. So, one could say that in order to support async bindings, you have to do couple of things:

  1. 202 that points to polling that tells the caller when to stop polling [either success or failure]
  2. once 202 returns success, call GET

So, broker writer must support 202 + last_operation + GET to get async bindings support.

duglin commented 7 years ago

That is certainly an option, but then we're inconsistent with async provisioning. I'm also not sure we can require GET since that mandates stateful brokers. I suspect that might be why the 202 is supposed to return the creds, but that's just a guess.

We should discuss this tomorrow... although, @mattmcneeney may not be on the call.

mattmcneeney commented 7 years ago

Returning no information in the last_operation call for bindings is actually consistent with async service instance provisioning, where the dashboard URL (the only data you can get from a provision) is returned alongside the 202 Accepted.

Although it would mean brokers having to support another endpoint, I would definitely support the workflow where the async binding last_operation call only returns a {"state":"succeeded"} and then the GET binding endpoint should be called to get binding specific information. I think this helps avoids the difficult questions such as how long should the last operation data be held onto, and what happens once it has been called (does the data disappear?).

Any brokers who can't do this because they are stateless etc can continue to use synchronous bindings.

On Tue, 12 Sep 2017 at 06:41, Doug Davis notifications@github.com wrote:

That is certainly an option, but then we're inconsistent with async provisioning. I'm also not sure we can require GET since that mandates stateful brokers. I suspect that might be why the 202 is supposed to return the creds, but that's just a guess.

We should discuss this tomorrow... although, @mattmcneeney https://github.com/mattmcneeney may not be on the call.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/openservicebrokerapi/servicebroker/issues/137#issuecomment-328742824, or mute the thread https://github.com/notifications/unsubscribe-auth/AG7UzMDENBQrDnsoB1TGG-OHuqMORA2mks5shhmfgaJpZM4MDStm .

duglin commented 7 years ago

I'm not following the "how long" question. If we're going to mandate GET then there's no real data to hold on to for last_op, at least in the successful case since last_op will know the operation was successful since the broker should have all of the info needed.

Yes, returning no other info on last_op is consistent with async provision, but I would like to suggest that we allow creds on the async provision last_op response to be consistent with our new async binding. I say this because I can imagine a case where a stateless broker can't support GET in general but is willing to hold on to the state long enough to return the last_op response- like we expect them to do today for async provision. And in that case they can probably hold on to the creds too for that short amount of time.

At the f2f we opted to not introduce the more correct set of URLs because we didn't want to be inconsistent or offer more than one way to do something. By having async bindings look so different from async provision it feels like we're back-tracking on that consistency decision and leaving the spec in kind of a weird state.

mattmcneeney commented 7 years ago

The how long question referred to how long should that last operation endpoint with binding data live for, what happens if it is called again after returning succeeded with data, etc. I'm not saying it's not a solution, just that there a few edge cases that we may be able to forget about by relying on a GET endpoint that should always return the binding data. (But then again, that raises the question of how many times binding credentials will be returned by that endpoint!) On Tue, 12 Sep 2017 at 06:56, Doug Davis notifications@github.com wrote:

I'm not following the "how long" question. If we're going to mandate GET then there's no real data to hold on to for last_op, at least in the successful case since last_op will know the operation was successful since the broker should have all of the info needed.

Yes, returning no other info on last_op is consistent with async provision, but I would like to suggest that we allow creds on the async provision last_op response to be consistent with our new async binding. I say this because I can imagine a case where a stateless broker can't support GET in general but is willing to hold on to the state long enough to return the last_op response- like we expect them to do today for async provision. And in that case they can probably hold on to the creds too for that short amount of time.

At the f2f we opted to not introduce the more correct set of URLs because we didn't want to be inconsistent or offer more than one way to do something. By having async bindings look so different from async provision it feels like we're back-tracking on that consistency decision and leaving the spec in kind of a weird state.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/openservicebrokerapi/servicebroker/issues/137#issuecomment-328745307, or mute the thread https://github.com/notifications/unsubscribe-auth/AG7UzC4VSenLkV-wIlZi1c3cq37eCQ4Rks5shhzxgaJpZM4MDStm .

vaikas commented 7 years ago

I would think GET endpoint should return the binding data for as long as the resource (binding) is around.

kibbles-n-bytes commented 7 years ago

I'm not too concerned with making the async binding flow exactly match the async provision flow. If we're talking ideal design, I could even see the argument that the async provision response should NOT return the dashboard URL, as that is also something that might take a while to get set up correctly, and its presence is more an artifact of not having GETs in the spec at that time.

Ultimately, in my opinion the GET is the most consistent and clear way to get the credentials back. I view credentials as out of scope of what an operation resource is meant to do, which is a generic resource that just reports on the status of an ongoing/completed process. And supporting credentials being passed back with the 202 but not being accessible is just a headache for the platform and I suspect not a common use case. If you're going to support binding asynchronously then I think it's perfectly fine to say you have to be stateful at that point.

bmelville commented 7 years ago

Doug, are you suggesting that last_op return credentials only once? That seems scary from the perspective of idempotency and could easily lead to lost data.

I will also +1 Kibbe's suggestion that in a true async provisioning world, even dashboard URL may not be available until the instance has been provisioned. Any async operation must allow for the results of that operation to be made available only after it completes.

duglin commented 7 years ago

@bmelville no, I'm suggesting that async bindings should have a similar UX as async provisioning to provide consistency between the two. Whether last_op can be called again, even after its said the op is done, is not clear in the spec and I would be fine with it returning the same data over and over until the broker decides to "not remember" that operation any more.

Let me try to be a bit more clear since I probably wasn't in the past....

That's at least my current thinking on it.

vaikas commented 7 years ago

My issue is with the first two points. Why is it important? I don't understand from the UX perspective why this has any bearing. The platform should be able to provide the UX that basically goes like this for bindings:

and for service instances:

I think we're getting distracted by the dashboard URL because apparently it can be precomputed ahead of time, but has no bearing on the actual resource (Service Instance) being created and mixing that with the result of the operation is making things more complicated.

I'd argue again that baking returning information from the last_operation is a bad idea because then you:

So, your second to last point is what I'd like to focus on. We're designing a new experience for async bindings. If you are saying that the broker can return the credentials (multiple times, mind you since we can't assume that things don't fall on the floor) in the last_operation, it clearly has to hang onto them somehow (or be able to get a mapping from last operation to them and if that's the case, then they could more than likely return or compute the mapping from the serviceinstance/binding as well in order to compute the value for last_operation), and I have a hard time seeing how you could return them in the last_operation but not in the get response. I'm sure such a system could be built, but I'm not sure how realistic it is. I feel like there's a lot of assumptions baked in there about what can't be done that's leading us down a path of complicated and unclean API :)

mattmcneeney commented 7 years ago

I missed last week's call in which you may have discussed this, but I agree with many of the points above. Summarising my thoughts:

I'm going to make a change to the spec regarding my last point here, and it would be great to discuss this again on next week's call?

mattmcneeney commented 7 years ago

Branch updated: https://github.com/mattmcneeney/servicebroker/blob/async-bindings/spec.md Shout if anyone else wants write access.

bmelville commented 7 years ago

I agree with your points, except for dashboard_url being a red herring. The URL may be specific to a dynamic IP or port, which may not be known until provisioned in the async process. I think this can be captured as a separate issue.

Edit: https://github.com/openservicebrokerapi/servicebroker/issues/170 already exists.

vaikas commented 7 years ago

I think we're all saying the same thing. In the current model the dashboard_url is assumed to be available before the provisioning finishes. This might not be a great assumption as we've all mentioned :)

On Fri, Sep 15, 2017 at 8:07 AM, Brendan Melville notifications@github.com wrote:

I agree with your points, except for dashboard_url being a red herring. The URL may be specific to a dynamic IP or port, which may not be known until provisioned in the async process. I think this can be captured as a separate issue.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/openservicebrokerapi/servicebroker/issues/137#issuecomment-329810036, or mute the thread https://github.com/notifications/unsubscribe-auth/AKwedJvtQcdufCO0DzMZO7Et6qT36twjks5sipLKgaJpZM4MDStm .

kibbles-n-bytes commented 7 years ago

A couple of nits on the status codes for binding (here):

mattmcneeney commented 7 years ago

Good points @kibbles-n-bytes - branch updated!

How do the interested folks feel about this branch now?

Spec: https://github.com/mattmcneeney/servicebroker/blob/async-bindings/spec.md

Diff against get-endpoints: https://github.com/mattmcneeney/servicebroker/compare/get-endpoints...mattmcneeney:async-bindings

kibbles-n-bytes commented 7 years ago

Thanks @mattmcneeney!

We should also document 422 Unprocessable Entity in the unbind response status codes (here)

mattmcneeney commented 7 years ago

Good point. That made me re-check the 422 description for Bindings. I only had one error described regarding the required app_guid field, so I've updated that too. Thanks @kibbles-n-bytes !

duglin commented 6 years ago

Can we close this in favor of #334 ?

mattmcneeney commented 6 years ago

@duglin fine by me as long as folks are happy to continue discussions on the PR

jmrodri commented 6 years ago

👍