package org.cloudfoundry.community.servicebroker.datalifecycle.service; import static org.cloudfoundry.community.servicebroker.datalifecycle.config.LCCatalogConfig.COPY; import static org.cloudfoundry.community.servicebroker.datalifecycle.config.LCCatalogConfig.PRODUCTION; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.IntStream; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.cloudfoundry.community.servicebroker.datalifecycle.config.LCCatalogConfig; import org.cloudfoundry.community.servicebroker.datalifecycle.dto.InstancePair; import org.cloudfoundry.community.servicebroker.datalifecycle.provider.CopyProvider; import org.cloudfoundry.community.servicebroker.datalifecycle.provider.DataProvider; import org.cloudfoundry.community.servicebroker.datalifecycle.repo.BrokerActionRepository; import org.cloudfoundry.community.servicebroker.datalifecycle.service.DataProviderService; import org.cloudfoundry.community.servicebroker.datalifecycle.service.LCServiceInstanceManager; import org.cloudfoundry.community.servicebroker.datalifecycle.service.LCServiceInstanceService; import org.cloudfoundry.community.servicebroker.exception.ServiceBrokerAsyncRequiredException; import org.cloudfoundry.community.servicebroker.exception.ServiceBrokerException; import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceExistsException; import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceUpdateNotSupportedException; import org.cloudfoundry.community.servicebroker.model.CreateServiceInstanceRequest; import org.cloudfoundry.community.servicebroker.model.DeleteServiceInstanceRequest; import org.cloudfoundry.community.servicebroker.model.ServiceDefinition; import org.cloudfoundry.community.servicebroker.model.ServiceInstance; import org.cloudfoundry.community.servicebroker.model.UpdateServiceInstanceRequest; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.core.task.SyncTaskExecutor; public class LCServiceInstanceServiceCopyTest { private LCServiceInstanceService service; private ServiceInstance instance; @Mock private CopyProvider copyProvider; @Mock private DataProvider dataProvider; @Mock private BrokerActionRepository brokerRepo; private ServiceDefinition serviceDef = new LCCatalogConfig().catalog() .getServiceDefinitions().get(0); @Mock LCServiceInstanceManager instanceManager; @Mock private DataProviderService dataProviderService; @Before public void setUp() throws ServiceInstanceExistsException, ServiceBrokerException { MockitoAnnotations.initMocks(this); service = new LCServiceInstanceService(copyProvider, dataProvider, "source_instance_id", brokerRepo, instanceManager, new SyncTaskExecutor(), dataProviderService); } private void createServiceInstance() throws ServiceInstanceExistsException, ServiceBrokerException, ServiceBrokerAsyncRequiredException { when(copyProvider.createCopy("source_instance_id")).thenReturn( "copy_instance"); CreateServiceInstanceRequest createServiceInstanceRequest = newCreateServiceInstanceRequest(); instance = service.createServiceInstance(createServiceInstanceRequest); } private CreateServiceInstanceRequest newCreateServiceInstanceRequest() { return new CreateServiceInstanceRequest(serviceDef.getId(), COPY, "org_guid", "space_guid", true) .withServiceInstanceId("service_instance_id").and() .withServiceDefinition(serviceDef).withAsyncClient(true); } @Test public void itShouldStoreWhatItCreates() throws ServiceInstanceExistsException, ServiceBrokerException, ServiceBrokerAsyncRequiredException { createServiceInstance(); assertThat(instance.getServiceInstanceLastOperation().getState(), is(equalTo("succeeded"))); verify(instanceManager).saveInstance(instance, "copy_instance"); } @Test public void itShouldCreateACopyWhenProvisionedWithACopyPlan() throws Exception { createServiceInstance(); verify(copyProvider).createCopy("source_instance_id"); } @Test public void itShouldSanitizeACopy() throws Exception { createServiceInstance(); verify(dataProvider).sanitize(anyString(), any()); } @Test public void itDeletesWhatItShould() throws Exception { createServiceInstance(); String id = instance.getServiceInstanceId(); when(instanceManager.getInstance(id)).thenReturn(instance); when(instanceManager.removeInstance(id)).thenReturn(instance); when(instanceManager.getCopyIdForInstance(id)).thenReturn( "copy_instance"); assertThat( service.deleteServiceInstance(new DeleteServiceInstanceRequest( id, instance.getServiceDefinitionId(), instance .getPlanId(), true)), is(equalTo(instance))); verify(copyProvider).deleteCopy("copy_instance"); verify(instanceManager).removeInstance(instance.getServiceInstanceId()); } @Test public void itReturnsTheCopyInstanceIdForServiceInstanceId() throws Exception { createServiceInstance(); Collection<Pair<String, ServiceInstance>> instances = Collections .singletonList(new ImmutablePair<String, ServiceInstance>( "copy_instance", instance)); when(instanceManager.getInstances()).thenReturn(instances); assertThat(service.getInstanceIdForServiceInstance(instance .getServiceInstanceId()), is(equalTo("copy_instance"))); } @Test public void itReturnsTheCorrectListOfServices() throws ServiceBrokerException, ServiceInstanceExistsException { Collection<Pair<String, ServiceInstance>> instances = createInstances(); when(instanceManager.getInstances()).thenReturn(instances); List<InstancePair> provisionedInstances = service .getProvisionedInstances(); assertThat(provisionedInstances, hasSize(5)); assertTrue(provisionedInstances.contains(new InstancePair( "source_instance_id", "copy_instance2"))); assertTrue(provisionedInstances.contains(new InstancePair( "source_instance_id", "source_instance_id"))); } private Collection<Pair<String, ServiceInstance>> createInstances() throws ServiceInstanceExistsException, ServiceBrokerException { Collection<Pair<String, ServiceInstance>> instances = new ArrayList<Pair<String, ServiceInstance>>(); IntStream.range(0, 4).forEach( i -> instances.add(new ImmutablePair<String, ServiceInstance>( "copy_instance" + i, null))); instances.add(new ImmutablePair<String, ServiceInstance>( "source_instance_id", null)); return instances; } @Test(expected = ServiceInstanceExistsException.class) public void itShouldThrowIfInstanceAlreadyExists() throws Exception { when(instanceManager.getInstance(any())).thenReturn( new ServiceInstance(new CreateServiceInstanceRequest(null, null, null, null, true))); createServiceInstance(); } @Test(expected = ServiceInstanceUpdateNotSupportedException.class) public void itShouldThrowForUpdateService() throws Exception { createServiceInstance(); service.updateServiceInstance(new UpdateServiceInstanceRequest( PRODUCTION, true).withInstanceId(instance .getServiceInstanceId())); } @Test(expected = ServiceBrokerAsyncRequiredException.class) public void itShouldThrowForSyncServiceDeletion() throws Exception { service.deleteServiceInstance(new DeleteServiceInstanceRequest(null, null, null, false)); } @Test(expected = ServiceBrokerAsyncRequiredException.class) public void itShouldThrowForSyncServiceCreation() throws Exception { service.createServiceInstance(new CreateServiceInstanceRequest() .withAsyncClient(false)); } @Test public void itShouldSaveTheInstnaceAsFailedIfDeprovisionFails() throws Exception { ServiceInstance theInstance = new ServiceInstance( newCreateServiceInstanceRequest()); doThrow(new ServiceBrokerException("Problem!")).when(copyProvider) .deleteCopy(anyString()); when(instanceManager.getInstance(anyString())).thenReturn(theInstance); when(instanceManager.getCopyIdForInstance(anyString())).thenReturn( "copy_id"); ServiceInstance failedInstance = service .deleteServiceInstance(new DeleteServiceInstanceRequest( theInstance.getServiceInstanceId(), theInstance .getServiceDefinitionId(), COPY, true)); assertThat(failedInstance.getServiceInstanceLastOperation().getState(), is(equalTo("failed"))); // Once for in progress, once for failed. verify(instanceManager, times(2)).saveInstance(any(), anyString()); assertTrue(failedInstance.isAsync()); } }