Do not fail delete operation if backing apps or services are missing

If backing apps or services are missing, then the error is logged and the
app name or service instance name is returned as if the service was deleted
as expected.

Resolves #208
This commit is contained in:
Roy Clarkson
2019-03-25 23:09:08 -04:00
committed by Roy Clarkson
parent 9ca8d894ae
commit 5ffcd6a2af
4 changed files with 175 additions and 6 deletions

View File

@@ -83,6 +83,9 @@ public class DeployerClient {
.doOnSuccess(response -> log.debug("Finished undeploying application {}", backingApplication))
.doOnError(exception -> log.error("Error undeploying application {} with error '{}'",
backingApplication, exception.getMessage()))
.onErrorReturn(UndeployApplicationResponse.builder()
.name(backingApplication.getName())
.build())
.map(UndeployApplicationResponse::getName);
}
@@ -129,11 +132,13 @@ public class DeployerClient {
.serviceInstanceName(backingService.getServiceInstanceName())
.properties(backingService.getProperties())
.build())
.doOnRequest(l -> log.debug("Deleting backing service {}", backingService.getName()))
.doOnSuccess(response -> log.debug("Finished deleting backing service {}", backingService.getName()))
.doOnError(exception -> log.error("Error deleting backing service {} with error '{}'",
backingService.getName(), exception.getMessage()))
.onErrorReturn(DeleteServiceInstanceResponse.builder()
.name(backingService.getServiceInstanceName())
.build())
.map(DeleteServiceInstanceResponse::getName);
}
}

View File

@@ -40,9 +40,13 @@ import static org.mockito.Mockito.when;
class DeployerClientTest {
private static final String APP_NAME = "helloworld";
private static final String APP_ARCHIVE = "app.jar";
private static final String APP_PATH = "classpath:/jars/" + APP_ARCHIVE;
private static final String SERVICE_INSTANCE_NAME = "helloservice";
private DeployerClient deployerClient;
@Mock
@@ -174,9 +178,10 @@ class DeployerClientTest {
}
@Test
void shouldNotUndeployAppThatDoesNotExist() {
void shouldNotReturnErrorWhenUndeployingAppThatDoesNotExist() {
// given
when(appDeployer.undeploy(any())).thenReturn(Mono.error(new IllegalStateException("app does not exist")));
when(appDeployer.undeploy(any()))
.thenReturn(Mono.error(new IllegalStateException("app does not exist")));
BackingApplication application = BackingApplication.builder()
.name(APP_NAME)
@@ -186,12 +191,118 @@ class DeployerClientTest {
// when
StepVerifier.create(deployerClient.undeploy(application))
// then
.expectErrorMessage("app does not exist")
.verify();
.expectNext(APP_NAME)
.verifyComplete();
verify(appDeployer).undeploy(argThat(request -> APP_NAME.equals(request.getName())));
}
@Test
void shouldCreateServiceInstance() {
// given
when(appDeployer.createServiceInstance(any()))
.thenReturn(Mono.just(CreateServiceInstanceResponse.builder()
.name(SERVICE_INSTANCE_NAME)
.build()));
BackingService service = BackingService.builder()
.serviceInstanceName(SERVICE_INSTANCE_NAME)
.build();
// when
StepVerifier.create(deployerClient.createServiceInstance(service))
// then
.expectNext(SERVICE_INSTANCE_NAME)
.verifyComplete();
verify(appDeployer).createServiceInstance(argThat(request ->
SERVICE_INSTANCE_NAME.equals(request.getServiceInstanceName())));
}
@Test
void shouldUpdateServiceInstance() {
// given
when(appDeployer.updateServiceInstance(any()))
.thenReturn(Mono.just(UpdateServiceInstanceResponse.builder()
.name(SERVICE_INSTANCE_NAME)
.build()));
BackingService service = BackingService.builder()
.serviceInstanceName(SERVICE_INSTANCE_NAME)
.build();
// when
StepVerifier.create(deployerClient.updateServiceInstance(service))
// then
.expectNext(SERVICE_INSTANCE_NAME)
.verifyComplete();
verify(appDeployer).updateServiceInstance(argThat(request ->
SERVICE_INSTANCE_NAME.equals(request.getServiceInstanceName())));
}
@Test
void shouldReturnErrorWhenUpdatingServiceInstanceThatDoesNotExist() {
// given
when(appDeployer.updateServiceInstance(any()))
.thenReturn(Mono.error(new IllegalStateException("service instance does not exist")));
BackingService service = BackingService.builder()
.serviceInstanceName(SERVICE_INSTANCE_NAME)
.build();
// when
StepVerifier.create(deployerClient.updateServiceInstance(service))
// then
.expectErrorMessage("service instance does not exist")
.verify();
verify(appDeployer).updateServiceInstance(argThat(request ->
SERVICE_INSTANCE_NAME.equals(request.getServiceInstanceName())));
}
@Test
void shouldDeleteServiceInstance() {
// given
when(appDeployer.deleteServiceInstance(any()))
.thenReturn(Mono.just(DeleteServiceInstanceResponse.builder()
.name(SERVICE_INSTANCE_NAME)
.build()));
BackingService service = BackingService.builder()
.serviceInstanceName(SERVICE_INSTANCE_NAME)
.build();
// when
StepVerifier.create(deployerClient.deleteServiceInstance(service))
// then
.expectNext(SERVICE_INSTANCE_NAME)
.verifyComplete();
verify(appDeployer).deleteServiceInstance(argThat(request ->
SERVICE_INSTANCE_NAME.equals(request.getServiceInstanceName())));
}
@Test
void shouldNotReturnErrorWhenDeletingServiceInstanceThatDoesNotExist() {
// given
when(appDeployer.deleteServiceInstance(any()))
.thenReturn(Mono.error(new IllegalStateException("service instance does not exist")));
BackingService service = BackingService.builder()
.serviceInstanceName(SERVICE_INSTANCE_NAME)
.build();
// when
StepVerifier.create(deployerClient.deleteServiceInstance(service))
// then
.expectNext(SERVICE_INSTANCE_NAME)
.verifyComplete();
verify(appDeployer).deleteServiceInstance(argThat(request ->
SERVICE_INSTANCE_NAME.equals(request.getServiceInstanceName())));
}
private ArgumentMatcher<DeployApplicationRequest> matchesRequest(String appName, String appArchive,
Map<String, String> properties,
Map<String, String> environment,

View File

@@ -102,6 +102,6 @@ class DeleteInstanceComponentTest extends WiremockComponentTest {
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
String state = brokerFixture.waitForAsyncOperationComplete("instance-id");
assertThat(state).isEqualTo(OperationState.FAILED.toString());
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
}
}

View File

@@ -47,6 +47,7 @@ class DeleteInstanceWithServicesComponentTest extends WiremockComponentTest {
static final String APP_NAME = "app-delete-with-services";
static final String BACKING_SI_NAME = "my-db-service";
static final String BACKING_SERVICE_NAME = "db-service";
@Autowired
@@ -86,4 +87,56 @@ class DeleteInstanceWithServicesComponentTest extends WiremockComponentTest {
String state = brokerFixture.waitForAsyncOperationComplete("instance-id");
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
}
@Test
void deleteAppsWhenTheyExistAndServicesWhenTheyDoNotExist() {
cloudControllerFixture.stubAppExists(APP_NAME);
cloudControllerFixture.stubServiceBindingDoesNotExist(APP_NAME);
cloudControllerFixture.stubDeleteApp(APP_NAME);
cloudControllerFixture.stubServiceInstanceDoesNotExist(BACKING_SI_NAME);
// when the service instance is deleted
given(brokerFixture.serviceInstanceRequest())
.when()
.delete(brokerFixture.deleteServiceInstanceUrl(), "instance-id")
.then()
.statusCode(HttpStatus.ACCEPTED.value());
// when the "last_operation" API is polled
given(brokerFixture.serviceInstanceRequest())
.when()
.get(brokerFixture.getLastInstanceOperationUrl(), "instance-id")
.then()
.statusCode(HttpStatus.OK.value())
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
String state = brokerFixture.waitForAsyncOperationComplete("instance-id");
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
}
@Test
void deleteAppsAndServicesWhenTheyDoNotExist() {
cloudControllerFixture.stubAppDoesNotExist(APP_NAME);
cloudControllerFixture.stubServiceInstanceDoesNotExist(BACKING_SI_NAME);
// when the service instance is deleted
given(brokerFixture.serviceInstanceRequest())
.when()
.delete(brokerFixture.deleteServiceInstanceUrl(), "instance-id")
.then()
.statusCode(HttpStatus.ACCEPTED.value());
// when the "last_operation" API is polled
given(brokerFixture.serviceInstanceRequest())
.when()
.get(brokerFixture.getLastInstanceOperationUrl(), "instance-id")
.then()
.statusCode(HttpStatus.OK.value())
.body("state", is(equalTo(OperationState.IN_PROGRESS.toString())));
String state = brokerFixture.waitForAsyncOperationComplete("instance-id");
assertThat(state).isEqualTo(OperationState.SUCCEEDED.toString());
}
}