@PatchMapping(value = { "/{platformInstanceId}/v2/service_instances/{instanceId}", "/v2/service_instances/{instanceId}" }) public ResponseEntity<UpdateServiceInstanceResponse> updateServiceInstance( @PathVariable Map<String, String> pathVariables, @PathVariable(ServiceBrokerRequest.INSTANCE_ID_PATH_VARIABLE) String serviceInstanceId, @RequestParam(value = AsyncServiceBrokerRequest.ASYNC_REQUEST_PARAMETER, required = false) boolean acceptsIncomplete, @RequestHeader(value = ServiceBrokerRequest.API_INFO_LOCATION_HEADER, required = false) String apiInfoLocation, @RequestHeader(value = ServiceBrokerRequest.ORIGINATING_IDENTITY_HEADER, required = false) String originatingIdentityString, @Valid @RequestBody UpdateServiceInstanceRequest request) { ServiceDefinition serviceDefinition = getRequiredServiceDefinition(request.getServiceDefinitionId()); Plan plan = getServiceDefinitionPlan(serviceDefinition, request.getPlanId()); request.setServiceInstanceId(serviceInstanceId); request.setServiceDefinition(serviceDefinition); request.setPlan(plan); setCommonRequestFields(request, pathVariables.get(ServiceBrokerRequest.PLATFORM_INSTANCE_ID_VARIABLE), apiInfoLocation, originatingIdentityString, acceptsIncomplete); logger.debug("Updating a service instance: request={}", request); UpdateServiceInstanceResponse response = service.updateServiceInstance(request); logger.debug("Updating a service instance succeeded: serviceInstanceId={}, response={}", serviceInstanceId, response); return new ResponseEntity<>(response, getAsyncResponseCode(response)); }
/** * Construct a {@link UpdateServiceInstanceRequest} from the provided values. * * @return the newly constructed {@literal UpdateServiceInstanceRequest} */ public UpdateServiceInstanceRequest build() { return new UpdateServiceInstanceRequest(serviceDefinitionId, serviceInstanceId, planId, serviceDefinition, plan, previousValues, parameters, context, asyncAccepted, platformInstanceId, apiInfoLocation, originatingIdentity); } }
@Override public final boolean equals(Object o) { if (this == o) return true; if (!(o instanceof UpdateServiceInstanceRequest)) return false; if (!super.equals(o)) return false; UpdateServiceInstanceRequest that = (UpdateServiceInstanceRequest) o; return that.canEqual(this) && Objects.equals(serviceDefinitionId, that.serviceDefinitionId) && Objects.equals(planId, that.planId) && Objects.equals(previousValues, that.previousValues) && Objects.equals(serviceInstanceId, that.serviceInstanceId) && Objects.equals(serviceDefinition, that.serviceDefinition) && Objects.equals(plan, that.plan); }
@Test public void requestIsDeserializedFromJson() { UpdateServiceInstanceRequest request = JsonUtils.readTestDataFile("updateRequest.json", UpdateServiceInstanceRequest.class); assertThat(request.getServiceDefinitionId()).isEqualTo("test-service-id"); assertThat(request.getPlanId()).isEqualTo("test-plan-id"); assertThat(request.getPreviousValues().getPlanId()).isEqualTo("previous-plan-id"); }
@Test public void requestWithDefaultsIsBuilt() { UpdateServiceInstanceRequest request = UpdateServiceInstanceRequest.builder() .build(); assertThat(request.getServiceDefinitionId()).isNull(); assertThat(request.getServiceInstanceId()).isNull(); assertThat(request.getPlanId()).isNull(); assertThat(request.getServiceDefinition()).isNull(); assertThat(request.getContext()).isNull(); assertThat(request.getParameters()).hasSize(0); assertThat(request.isAsyncAccepted()).isEqualTo(false); assertThat(request.getPreviousValues()).isNull(); assertThat(request.getApiInfoLocation()).isNull(); assertThat(request.getPlatformInstanceId()).isNull(); assertThat(request.getOriginatingIdentity()).isNull(); }
@Override public Mono<UpdateServiceInstanceResponse> updateServiceInstance(UpdateServiceInstanceRequest request) { String serviceInstanceId = request.getServiceInstanceId(); String planId = request.getPlanId(); String previousPlan = request.getPreviousValues().getPlanId(); Map<String, Object> parameters = request.getParameters(); // // perform the steps necessary to initiate the asynchronous // updating of all necessary resources // UpdateServiceInstanceResponse response = UpdateServiceInstanceResponse.builder() .async(true) .build(); return Mono.just(response); }
@Test public void updateServiceInstanceFiltersPlansSucceeds() throws Exception { setupCatalogService(); setupServiceInstanceService(UpdateServiceInstanceResponse .builder() .build()); MvcResult mvcResult = mockMvc .perform(patch(buildCreateUpdateUrl()) .content(updateRequestBodyWithPlan) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(request().asyncStarted()) .andReturn(); mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) .andExpect(content().string("{}")); UpdateServiceInstanceRequest actualRequest = verifyUpdateServiceInstance(); assertThat(actualRequest.isAsyncAccepted()).isEqualTo(false); assertThat(actualRequest.getPlan().getId()).isEqualTo(actualRequest.getPlanId()); assertHeaderValuesNotSet(actualRequest); }
@Test public void updateServiceInstanceWithoutSyncAndHeadersSucceeds() throws Exception { setupCatalogService(); setupServiceInstanceService(UpdateServiceInstanceResponse.builder() .build()); MvcResult mvcResult = mockMvc.perform(patch(buildCreateUpdateUrl()) .content(updateRequestBody) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(request().asyncStarted()) .andReturn(); mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isOk()) .andExpect(content().string("{}")); UpdateServiceInstanceRequest actualRequest = verifyUpdateServiceInstance(); assertThat(actualRequest.isAsyncAccepted()).isEqualTo(false); assertThat(actualRequest.getServiceDefinition().getPlans().size()).isEqualTo(3); assertThat(actualRequest.getPlan()).isNull(); assertHeaderValuesNotSet(actualRequest); }
@Theory public void updateServiceInstanceWithResponseGivesExpectedStatus(UpdateResponseAndExpectedStatus data) { Mono<UpdateServiceInstanceResponse> responseMono; if (data.response == null) { responseMono = Mono.empty(); } else { responseMono = Mono.just(data.response); } when(serviceInstanceService.updateServiceInstance(any(UpdateServiceInstanceRequest.class))) .thenReturn(responseMono); UpdateServiceInstanceRequest updateRequest = UpdateServiceInstanceRequest.builder() .serviceDefinitionId("service-definition-id") .build(); ResponseEntity<UpdateServiceInstanceResponse> responseEntity = controller .updateServiceInstance(pathVariables, null, false, null, null, updateRequest) .block(); assertThat(responseEntity.getStatusCode()).isEqualTo(data.expectedStatus); assertThat(responseEntity.getBody()).isEqualTo(data.response); }
@Test public void updateServiceInstanceFiltersPlansSucceeds() { setupCatalogService(); setupServiceInstanceService(UpdateServiceInstanceResponse.builder() .build()); client.patch().uri(buildCreateUpdateUrl()) .contentType(MediaType.APPLICATION_JSON) .syncBody(updateRequestBodyWithPlan) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody() .json("{}"); UpdateServiceInstanceRequest actualRequest = verifyUpdateServiceInstance(); assertThat(actualRequest.isAsyncAccepted()).isEqualTo(false); assertThat(actualRequest.getPlan().getId()).isEqualTo("plan-three-id"); assertHeaderValuesNotSet(actualRequest); }
@Override public Mono<UpdateServiceInstanceResponse> updateServiceInstance( UpdateServiceInstanceRequest request) { if (request.getServiceDefinitionId() == null) { return Mono.error(new ServiceBrokerInvalidParametersException("arrrr")); } return Mono.just(UpdateServiceInstanceResponse.builder().build()); }
@Override public Mono<Void> complete( UpdateServiceInstanceRequest request, UpdateServiceInstanceResponse response) { return results.setAfterUpdate("after " + request.getServiceInstanceId()); } }))
@Test public void updateServiceInstanceWithAsyncAndHeadersSucceeds() throws Exception { setupCatalogService(); setupServiceInstanceService(UpdateServiceInstanceResponse.builder() .async(true) .operation("working") .dashboardUrl("https://dashboard.example.com") .build()); MvcResult mvcResult = mockMvc.perform(patch(buildCreateUpdateUrl(PLATFORM_INSTANCE_ID, true)) .content(updateRequestBody) .header(API_INFO_LOCATION_HEADER, API_INFO_LOCATION) .header(ORIGINATING_IDENTITY_HEADER, buildOriginatingIdentityHeader()) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)) .andExpect(request().asyncStarted()) .andReturn(); mockMvc.perform(asyncDispatch(mvcResult)) .andExpect(status().isAccepted()) .andExpect(jsonPath("$.operation", equalTo("working"))) .andExpect(jsonPath("$.dashboard_url", equalTo("https://dashboard.example.com"))); UpdateServiceInstanceRequest actualRequest = verifyUpdateServiceInstance(); assertThat(actualRequest.isAsyncAccepted()).isEqualTo(true); assertHeaderValuesSet(actualRequest); }
.build(); UpdateServiceInstanceRequest request = UpdateServiceInstanceRequest.builder() .serviceInstanceId("service-instance-id") .serviceDefinitionId("service-definition-id") .build(); assertThat(request.getServiceInstanceId()).isEqualTo("service-instance-id"); assertThat(request.getServiceDefinitionId()).isEqualTo("service-definition-id"); assertThat(request.getPlanId()).isEqualTo("plan-id"); assertThat(request.getPreviousValues().getPlanId()).isEqualTo("previous-plan-id"); assertThat(request.getParameters()).hasSize(5); assertThat(request.getParameters().get("field1")).isEqualTo("value1"); assertThat(request.getParameters().get("field2")).isEqualTo(2); assertThat(request.getParameters().get("field3")).isEqualTo(true); assertThat(request.getParameters().get("field4")).isEqualTo("value4"); assertThat(request.getParameters().get("field5")).isEqualTo("value5"); assertThat(request.getContext()).isEqualTo(context); assertThat(request.isAsyncAccepted()).isEqualTo(true); assertThat(request.getPlatformInstanceId()).isEqualTo("platform-instance-id"); assertThat(request.getApiInfoLocation()).isEqualTo("https://api.example.com"); assertThat(request.getOriginatingIdentity()).isEqualTo(originatingIdentity);
@Test(expected = ServiceDefinitionDoesNotExistException.class) public void updateServiceInstanceWithInvalidServiceDefinitionIdThrowsException() { UpdateServiceInstanceRequest updateRequest = UpdateServiceInstanceRequest.builder() .serviceDefinitionId("unknown-service-definition-id") .build(); ServiceInstanceController controller = createControllerUnderTest(); controller.updateServiceInstance(pathVariables, null, false, null, null, updateRequest) .block(); }
@Test public void updateServiceInstanceWithoutAsyncAndHeadersSucceeds() { setupCatalogService(); setupServiceInstanceService(UpdateServiceInstanceResponse.builder() .build()); client.patch().uri(buildCreateUpdateUrl()) .contentType(MediaType.APPLICATION_JSON) .syncBody(updateRequestBody) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isOk() .expectBody() .json("{}"); UpdateServiceInstanceRequest actualRequest = verifyUpdateServiceInstance(); assertThat(actualRequest.isAsyncAccepted()).isEqualTo(false); assertThat(actualRequest.getPlan()).isNull(); assertHeaderValuesNotSet(actualRequest); }
private void prepareUpdateEventFlows() { this.eventFlowRegistries.getUpdateInstanceRegistry() .addInitializationFlow(new UpdateServiceInstanceInitializationFlow() { @Override public Mono<Void> initialize(UpdateServiceInstanceRequest request) { return results.setBeforeUpdate("before " + request.getServiceInstanceId()); } }) .then(this.eventFlowRegistries.getUpdateInstanceRegistry() .addCompletionFlow(new UpdateServiceInstanceCompletionFlow() { @Override public Mono<Void> complete( UpdateServiceInstanceRequest request, UpdateServiceInstanceResponse response) { return results.setAfterUpdate("after " + request.getServiceInstanceId()); } })) .then(eventFlowRegistries.getUpdateInstanceRegistry() .addErrorFlow(new UpdateServiceInstanceErrorFlow() { @Override public Mono<Void> error(UpdateServiceInstanceRequest request, Throwable t) { return results.setErrorUpdate("error " + request.getServiceInstanceId()); } })) .subscribe(); }
@Test public void updateServiceInstanceWithAsyncAndHeadersSucceeds() throws Exception { setupCatalogService(); setupServiceInstanceService(UpdateServiceInstanceResponse.builder() .async(true) .operation("working") .dashboardUrl("https://dashboard.example.com") .build()); client.patch().uri(buildCreateUpdateUrl(PLATFORM_INSTANCE_ID, true)) .contentType(MediaType.APPLICATION_JSON) .syncBody(updateRequestBody) .header(API_INFO_LOCATION_HEADER, API_INFO_LOCATION) .header(ORIGINATING_IDENTITY_HEADER, buildOriginatingIdentityHeader()) .accept(MediaType.APPLICATION_JSON) .exchange() .expectStatus().isAccepted() .expectBody() .jsonPath("$.operation").isEqualTo("working") .jsonPath("$.dashboard_url").isEqualTo("https://dashboard.example.com"); UpdateServiceInstanceRequest actualRequest = verifyUpdateServiceInstance(); assertThat(actualRequest.isAsyncAccepted()).isEqualTo(true); assertHeaderValuesSet(actualRequest); }
@RequestHeader(value = ServiceBrokerRequest.ORIGINATING_IDENTITY_HEADER, required = false) String originatingIdentityString, @Valid @RequestBody UpdateServiceInstanceRequest request) { return getRequiredServiceDefinition(request.getServiceDefinitionId()) .flatMap(serviceDefinition -> getServiceDefinitionPlan(serviceDefinition, request.getPlanId()) .map(plan -> { request.setPlan(plan); return request; }) .switchIfEmpty(Mono.just(request)) .map(req -> { req.setServiceInstanceId(serviceInstanceId); req.setServiceDefinition(serviceDefinition); return req; }))
@Test public void updateServiceInstanceFails() { prepareUpdateEventFlows(); StepVerifier .create(serviceInstanceEventService.updateServiceInstance( UpdateServiceInstanceRequest.builder() .serviceInstanceId("foo") .build())) .expectError() .verify(); assertThat(this.results.getBeforeUpdate()).isEqualTo("before foo"); assertThat(this.results.getAfterUpdate()).isNullOrEmpty(); assertThat(this.results.getErrorUpdate()).isEqualTo("error foo"); }