-
Notifications
You must be signed in to change notification settings - Fork 84
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug 1536659 - bind PUT returns http code 202 when operation runs async #669
Conversation
Changes Unknown when pulling 27f7b30 on mhrivnak:async-bind-202 into ** on openshift:master**. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd model it more like Provision
@@ -79,7 +79,7 @@ type Broker interface { | |||
Provision(uuid.UUID, *ProvisionRequest, bool) (*ProvisionResponse, error) | |||
Update(uuid.UUID, *UpdateRequest, bool) (*UpdateResponse, error) | |||
Deprovision(apb.ServiceInstance, string, bool, bool) (*DeprovisionResponse, error) | |||
Bind(apb.ServiceInstance, uuid.UUID, *BindRequest, bool) (*BindResponse, error) | |||
Bind(apb.ServiceInstance, uuid.UUID, *BindRequest, bool) (*BindResponse, bool, error) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we returning a bool?
@@ -817,12 +817,14 @@ func (a AnsibleBroker) GetBind(instance apb.ServiceInstance, bindingUUID uuid.UU | |||
} | |||
|
|||
log.Debug("broker.GetBind: we got the bind credentials") | |||
return a.buildBindResponse(provExtCreds, bindExtCreds, false, "") | |||
return NewBindResponse(provExtCreds, bindExtCreds) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this better.
@@ -560,7 +560,7 @@ func (h handler) bind(w http.ResponseWriter, r *http.Request, params map[string] | |||
} | |||
|
|||
// process binding request | |||
resp, err := h.broker.Bind(serviceInstance, bindingUUID, req, async) | |||
resp, ranAsync, err := h.broker.Bind(serviceInstance, bindingUUID, req, async) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to return this boolean. We know if we are async based on the async. Provision
returns similar values without returning a ranAsync
. I'd prefer to model it similar to Provision
.
if err != nil {
switch err {
case broker.ErrorDuplicate:
writeResponse(w, http.StatusConflict, broker.ProvisionResponse{})
case broker.ErrorProvisionInProgress:
writeResponse(w, http.StatusAccepted, resp)
case broker.ErrorAlreadyProvisioned:
writeResponse(w, http.StatusOK, resp)
case broker.ErrorNotFound:
writeResponse(w, http.StatusBadRequest, broker.ErrorResponse{Description: err.Error()})
default:
writeResponse(w, http.StatusBadRequest, broker.ErrorResponse{Description: err.Error()})
}
} else if async {
writeDefaultResponse(w, http.StatusAccepted, resp, err)
} else {
writeDefaultResponse(w, http.StatusCreated, resp, err)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When async == true
for the argument being passed into the broker's Bind function, there are at least two cases where there will not be asynchronous execution.
- if the binding already exists
- if the broker is configured for
launch_apb_on_bind = false
In theory there could be other reasons for doing it synchronously even if async == true
.
Put another way, when async == true
, all that really means is that the client specified accepts_incomplete=true
. That is not a guarantee that asynchronous execution will happen. The handler must allow the broker to decide whether async execution is appropriate, and must then compose an http response based on what the broker decided. And the only way for the handler to know what the broker decided is if the broker tells it, hence the bool
.
A different but perfectly valid (I think?) way to handle this would be to add an attribute to the response object and communicate through that. But since the response object gets directly serialized into an HTTP response body, that might be overloading its definition.
We could add a private field "async" to the response, and then a method that returns whether the attribute was async or not, and I assume that would allow the field to be omitted from serialization to JSON? Something like:
type BindResponse struct {
Credentials map[string]interface{} `json:"credentials,omitempty"`
SyslogDrainURL string `json:"syslog_drain_url,omitempty"`
RouteServiceURL string `json:"route_service_url,omitempty"`
VolumeMounts []interface{} `json:"volume_mounts,omitempty"`
Operation string `json:"operation,omitempty"`
ranAsync bool
}
// returns true if the operation executed asynchronously, otherwise false
func (b BindResponse) RanAsync() (bool)
return b.ranAsync
Even if that's doable, it's probably simpler, and definitely just as effective, to return a separate value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mhrivnak very good explanation to why you did it differently than provision. Okay that makes sense now. Sorry I missed that.
@@ -93,9 +93,9 @@ func (m MockBroker) Deprovision(apb.ServiceInstance, string, bool, bool) (*broke | |||
m.called("deprovision", true) | |||
return nil, m.Err | |||
} | |||
func (m MockBroker) Bind(apb.ServiceInstance, uuid.UUID, *broker.BindRequest, bool) (*broker.BindResponse, error) { | |||
func (m MockBroker) Bind(apb.ServiceInstance, uuid.UUID, *broker.BindRequest, bool) (*broker.BindResponse, bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-1 to returning bool
.
@mhrivnak lint check failed. Please run |
27f7b30
to
880408f
Compare
@jmrodri thanks for pointing that out. I fixed one of the two lint errors, but the other appears to be failing on master and is unrelated to this PR:
|
|
||
log.Debugf("provision bind creds: %v", pCreds.Credentials) | ||
return &BindResponse{Credentials: pCreds.Credentials}, nil | ||
resp, err := NewBindResponse(provExtCreds, bindExtCreds) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, no dependency on the state of the broker, no reason to have it as a method.
@mhrivnak needs rebase |
Previously the http response incorrectly had code 201. Once async logic was removed from buildBindRequest, it looked an awful lot like a simple constructor. That's why I moved it next to the type definition and renamed it NewBindRequest to match golang convention. fixes openshift#667
880408f
to
abeb66c
Compare
Previously the http response incorrectly had code 201.
Once async logic was removed from buildBindRequest, it looked an awful lot like
a simple constructor. That's why I moved it next to the type definition and
renamed it NewBindRequest to match golang convention.
fixes #667