@@ -362,6 +362,82 @@ private Mono<DeleteServiceInstanceResponse> handleDeleteException(Exception orig
362362 throw new ServiceInstanceDoesNotExistException (request .getServiceInstanceId ());
363363 }
364364
365+ /**
366+ * Handle exceptions by checking current backing service instance in order to return the appropriate response
367+ * as expected in the OSB specifications.
368+ * @param originalException The exception occuring during processing. Note that Subclasses of
369+ * ServiceBrokerException are considered already qualified, and returned as-is
370+ */
371+ private Mono <UpdateServiceInstanceResponse > handleUpdateException (Exception originalException ,
372+ String backingServiceInstanceName ,
373+ CloudFoundryOperations spacedTargetedOperations ,
374+ UpdateServiceInstanceRequest request ) {
375+ LOG .info ("Inspecting exception caught {} for possible concurrent dupl while handling request {} " , originalException , request );
376+
377+ if (originalException instanceof ServiceBrokerException && ! originalException .getClass ().equals (ServiceBrokerException .class )) {
378+ LOG .info ("Exception was thrown by ourselves, and already qualified, rethrowing it unmodified" );
379+ throw (ServiceBrokerException ) originalException ;
380+ }
381+
382+ ServiceInstance updatedSi = getCfServiceInstance (spacedTargetedOperations , backingServiceInstanceName );
383+ String spaceId = getSpacedIdFromTargettedOperationsInternals (spacedTargetedOperations );
384+
385+ if (updatedSi != null ) {
386+ if (!"update" .equals (updatedSi .getLastOperation ())) {
387+ LOG .info ("No instance in the inventory with id={} in space with id={}, and recently updated: " +
388+ "last_operation={}, flowing up original exception" ,
389+ request .getServiceInstanceId (), spaceId , updatedSi .getLastOperation () );
390+ //500 error
391+ throw new ServiceBrokerInvalidParametersException (originalException .getMessage ());
392+ }
393+ switch (updatedSi .getStatus ()) {
394+ case OsbApiConstants .LAST_OPERATION_STATE_INPROGRESS :
395+ LOG .info ("Concurrent update request is still in progress. " +
396+ "Returning accepted: 202" );
397+ String operation = toJson (new CmdbOperationState (updatedSi .getId (),
398+ OsbOperation .UPDATE ));
399+ //202 Accepted
400+ return Mono .just (UpdateServiceInstanceResponse .builder ()
401+ .operation (operation )
402+ .async (true )
403+ .build ());
404+
405+ case OsbApiConstants .LAST_OPERATION_STATE_SUCCEEDED :
406+ if (updatedSi .getService ().equals (request .getServiceDefinition ().getName ()) &&
407+ updatedSi .getPlan ().equals (request .getPlan ().getName ())) {
408+ LOG .info ("Concurrent update request has completed. " +
409+ "Returning 200 OK" );
410+ //200 OK
411+ return Mono .just (UpdateServiceInstanceResponse .builder ()
412+ .async (false )
413+ .build ());
414+ }
415+ else {
416+ LOG .info ("Plan update did not succeed while SI update completed, assuming invalid input. " +
417+ "Existing si service name={} and service plan={}" , updatedSi .getService (), updatedSi .getPlan ());
418+ throw new ServiceBrokerInvalidParametersException (originalException .getMessage ());
419+ }
420+
421+ case OsbApiConstants .LAST_OPERATION_STATE_FAILED :
422+ LOG .info ("Backing service failed to update with {}, flowing up the original error to the osb " +
423+ "client: " ,
424+ updatedSi .getMessage (), originalException .getMessage ());
425+ //500 error
426+ //In the future, return the usable field once CF supports it
427+ throw new ServiceBrokerException (originalException .getMessage ());
428+
429+ default :
430+ LOG .error ("Unexpected last operation state:" + updatedSi .getStatus ());
431+ throw new ServiceBrokerException ("Internal CF protocol error" );
432+ }
433+ }
434+ LOG .info ("No existing instance in the inventory with id={} in space with id={}, assuming invalid requestrace " +
435+ "condition " +
436+ "among concurrent update request. Returning 410" , request .getServiceInstanceId (), spaceId );
437+ //410 Gone
438+ throw new ServiceInstanceDoesNotExistException (request .getServiceInstanceId ());
439+ }
440+
365441 private String getRequestIncompatibilityWithExistingInstance (ServiceInstance existingServiceInstance ,
366442 ServiceDefinition serviceDefinition , Plan plan ) {
367443 if (! existingServiceInstance .getService ().equals (serviceDefinition .getName ())) {
@@ -615,11 +691,12 @@ public Mono<UpdateServiceInstanceResponse> updateServiceInstance(UpdateServiceIn
615691
616692 String backingServiceName = request .getServiceDefinition ().getName ();
617693 String backingServicePlanName = request .getPlan ().getName ();
694+ String backingServiceInstanceName = ServiceInstanceNameHelper .truncateNameToCfMaxSize (request .getServiceInstanceId ());
618695
619696 //ignore race condition during space creation for K8S dupl requests
620697 CloudFoundryOperations spacedTargetedOperations = getSpaceScopedOperations (backingServiceName );
621698 ServiceInstance existingBackingServiceInstance = getCfServiceInstance (spacedTargetedOperations ,
622- ServiceInstanceNameHelper . truncateNameToCfMaxSize ( request . getServiceInstanceId ()) );
699+ backingServiceInstanceName );
623700 //Lookup guids necessary for low level api usage, and that CloudFoundryOperations hides in its response
624701 String spaceId = getSpacedIdFromTargettedOperationsInternals (spacedTargetedOperations );
625702 String backingServicePlanId = fetchBackingServicePlanId (backingServiceName , backingServicePlanName , spaceId );
@@ -667,10 +744,8 @@ public Mono<UpdateServiceInstanceResponse> updateServiceInstance(UpdateServiceIn
667744 }
668745 responseBuilder .async (asyncProvisioning );
669746 }
670- catch (ClientV2Exception e ) {
671- LOG .info ("Unable to update service, caught:" + e , e );
672- //wrap to avoid log polution from sc-osb catching unexpectidely unknown (cf-java-client's) exceptions
673- throw new ServiceBrokerException (e .toString ());
747+ catch (Exception e ) {
748+ return handleUpdateException (e , backingServiceInstanceName , spacedTargetedOperations , request );
674749 }
675750 finally {
676751 //systematically try to update metadata (e.g. service instance rename) even if update failed
0 commit comments