package org.cloudfoundry.community.servicebroker.brooklyn.service;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.Map;
import java.util.function.Predicate;
import javax.ws.rs.core.Response;
import org.apache.brooklyn.rest.api.ActivityApi;
import org.apache.brooklyn.rest.api.EffectorApi;
import org.apache.brooklyn.rest.api.EntityApi;
import org.apache.brooklyn.rest.api.SensorApi;
import org.apache.brooklyn.rest.client.BrooklynApi;
import org.apache.brooklyn.rest.domain.EntitySummary;
import org.apache.brooklyn.rest.domain.SensorSummary;
import org.apache.brooklyn.rest.domain.TaskSummary;
import org.apache.brooklyn.util.core.ResourceUtils;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.yaml.Yamls;
import org.apache.http.client.HttpClient;
import org.cloudfoundry.community.servicebroker.brooklyn.BrooklynConfiguration;
import org.cloudfoundry.community.servicebroker.brooklyn.config.BrooklynConfig;
import org.cloudfoundry.community.servicebroker.brooklyn.model.BrooklynServiceInstance;
import org.cloudfoundry.community.servicebroker.brooklyn.model.BrooklynServiceInstanceBinding;
import org.cloudfoundry.community.servicebroker.brooklyn.repository.BrooklynServiceInstanceBindingRepository;
import org.cloudfoundry.community.servicebroker.brooklyn.repository.BrooklynServiceInstanceRepository;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.cloud.servicebroker.exception.ServiceBrokerException;
import org.springframework.cloud.servicebroker.exception.ServiceInstanceBindingExistsException;
import org.springframework.cloud.servicebroker.model.CreateServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.CreateServiceInstanceBindingResponse;
import org.springframework.cloud.servicebroker.model.DeleteServiceInstanceBindingRequest;
import org.springframework.cloud.servicebroker.model.ServiceDefinition;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {BrooklynConfiguration.class})
public class BrooklynServiceInstanceBindingServiceTest {
private final static String SVC_INST_BIND_ID = "serviceInstanceBindingId";
private final static String SVC_DEFN_ID = "serviceDefinitionId";
private static final String WHITELIST_YAML = ResourceUtils.create().getResourceAsString("whitelist-catalog.yaml");
private static final String NO_PLANS_YAML = ResourceUtils.create().getResourceAsString("noplans-catalog.yaml");
private static final String PLANS_YAML = ResourceUtils.create().getResourceAsString("plans-catalog.yaml");
private static final Map<String, Object> EXPECTED_CREDENTIALS = Maps.newHashMap();
static {
Map<String, Object> expectedCredentialsChild = Maps.newHashMap();
expectedCredentialsChild.put("sensor.one.name", null);
EXPECTED_CREDENTIALS.putAll(expectedCredentialsChild);
}
private final String TASK_ID = "NrBavIWX";
private final String TASK_RESPONSE_INCOMPLETE = "{id:\"" + TASK_ID + "\",displayName:\"pre-install\",description:\"\",entityId:\"Mo6NM5Qt\",entityDisplayName:\"MongoDBServer:Mo6N\",tags:[{wrappingType:\"contextEntity\",entity:{type:\"org.apache.brooklyn.api.entity.Entity\",id:\"Mo6NM5Qt\"}},{entitlementContext:{user:\"admin\",sourceIp:\"0:0:0:0:0:0:0:1\",requestUri:\"/v1/applications\",requestUniqueIdentifier:\"XbbETK\"}},\"SUB-TASK\"],submitTimeUtc:1443530180701,startTimeUtc:1443530180701,endTimeUtc:1443530180724,currentStatus:\"Completed\",result:null,isError:false,isCancelled:false,children:[],submittedByTask:{link:\"/v1/activities/TBCqTO6X\",metadata:{id:\"TBCqTO6X\",taskName:\"start (processes)\",entityId:\"Mo6NM5Qt\",entityDisplayName:\"MongoDBServer:Mo6N\"}},detailedStatus:\"Completed after 23ms No return value (null)\",streams:{},links:{self:\"/v1/activities/UfyAm4ul\",children:\"/v1/activities/UfyAm4ul/children\",entity:\"/v1/applications/TijtVDIn/entities/Mo6NM5Qt\"}}";
private final String TASK_RESPONSE_COMPLETE = "[\"rv6ylqjg6u\"]";
private final TaskSummary TASK_SUMMARY_INCOMPLETE = new TaskSummary(TASK_ID, "displayName", "description", "entityId", "entityDisplayName",
ImmutableSet.of(), 0l, 0l, null, "currentStatus", "childEntityId", false, false,
ImmutableList.of(), null, null, "blockingDetails", "detailedStatus", ImmutableMap.of(), ImmutableMap.of());
private final TaskSummary TASK_SUMMARY_COMPLETE = new TaskSummary(TASK_ID, "displayName", "description", "entityId", "entityDisplayName",
ImmutableSet.of(), 0l, 0l, 1l, "currentStatus", "childEntityId", false, false,
ImmutableList.of(), null, null, "blockingDetails", "detailedStatus", ImmutableMap.of(), ImmutableMap.of());
private static final BrooklynServiceInstanceBinding TEST_SERVICE_INSTANCE_BINDING = new BrooklynServiceInstanceBinding("service_instance_binding_id", "service-one-id", ImmutableMap.of(), "app_guid", "childEntityId");
@Mock
private BrooklynRestAdmin admin;
@Mock
private BrooklynServiceInstance serviceInstance;
private BrooklynServiceInstanceBindingService bindingService;
@Mock
private BrooklynServiceInstanceBindingRepository bindingRepository;
@Mock
private BrooklynServiceInstanceRepository instanceRepository;
@Mock
private BrooklynCatalogService brooklynCatalogService;
@Mock
private ServiceDefinition serviceDefinition;
@Mock
private SensorApi sensorApi;
@Mock
private BrooklynApi brooklynApi;
@Mock
private EntityApi entityApi;
@Mock
private HttpClient httpClient;
@Mock
private BrooklynConfig config;
@Mock
private EffectorApi effectorApi;
@Mock
private Response bindEffectorResponse;
@Mock
private ActivityApi activityApi;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
bindingService = new BrooklynServiceInstanceBindingService(admin, bindingRepository, instanceRepository, brooklynCatalogService);
}
@Test
public void newServiceInstanceBindingCreatedSuccessfully()
throws ServiceBrokerException, ServiceInstanceBindingExistsException {
when(admin.getCredentialsFromSensors(anyString(), anyString(), any(Predicate.class), any(Predicate.class), any(Predicate.class), any(Predicate.class))).thenReturn(new AsyncResult<>(Collections.<String, Object>emptyMap()));
when(admin.hasEffector(anyString(), anyString(), anyString())).thenReturn(new AsyncResult<>(false));
when(instanceRepository.findOne(anyString(), anyBoolean())).thenReturn(serviceInstance);
when(serviceDefinition.getMetadata()).thenReturn(ImmutableMap.of());
when(brooklynCatalogService.getServiceDefinition(anyString())).thenReturn(serviceDefinition);
when(serviceInstance.getEntityId()).thenReturn("entityId");
CreateServiceInstanceBindingRequest request = new CreateServiceInstanceBindingRequest(serviceInstance.getServiceDefinitionId(), "planId", "appGuid", null);
CreateServiceInstanceBindingResponse binding = bindingService.createServiceInstanceBinding(request.withBindingId(SVC_INST_BIND_ID));
assertNotNull(binding);
// TODO assert binding was completed successfully
//assertEquals(SVC_INST_BIND_ID, binding.getServiceBindingId());
}
@Test
public void newServiceInstanceBindingCreatedSuccessfullyWithBindEffector()
throws ServiceBrokerException, ServiceInstanceBindingExistsException, PollingException {
when(admin.getRestApi()).thenReturn(brooklynApi);
when(admin.getCredentialsFromSensors(
anyString(),
anyString(),
any(Predicate.class),
any(Predicate.class),
any(Predicate.class),
any(Predicate.class)
)).thenReturn(new AsyncResult<>(Collections.<String, Object>emptyMap()));
when(admin.hasEffector(anyString(), anyString(), anyString())).thenReturn(new AsyncResult<>(true));
when(admin.invokeEffector(anyString(), anyString(), anyString(), anyString(), anyMap())).thenReturn(new AsyncResult<>(TASK_RESPONSE_COMPLETE));
when(brooklynApi.getActivityApi()).thenReturn(activityApi);
when(activityApi.get(anyString()))
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_COMPLETE);
doCallRealMethod().when(admin).blockUntilTaskCompletes(anyString());
doCallRealMethod().when(admin).blockUntilTaskCompletes(anyString(), any(Duration.class), any(Object[].class));
when(instanceRepository.findOne(anyString(), anyBoolean())).thenReturn(serviceInstance);
when(serviceDefinition.getMetadata()).thenReturn(ImmutableMap.of());
when(brooklynCatalogService.getServiceDefinition(anyString())).thenReturn(serviceDefinition);
CreateServiceInstanceBindingRequest request = new CreateServiceInstanceBindingRequest(serviceInstance.getServiceDefinitionId(), "planId", "appGuid", null);
CreateServiceInstanceBindingResponse binding = bindingService.createServiceInstanceBinding(request.withBindingId(SVC_INST_BIND_ID));
// TODO assert binding was completed successfully
//assertEquals(SVC_INST_BIND_ID, binding.getServiceBindingId());
}
@Test(expected = RuntimeException.class)
public void testServiceInstanceBindingFailureWithBindEffector()
throws ServiceBrokerException, ServiceInstanceBindingExistsException, PollingException {
when(admin.getRestApi()).thenReturn(brooklynApi);
when(admin.getCredentialsFromSensors(
anyString(),
anyString(),
any(Predicate.class),
any(Predicate.class),
any(Predicate.class),
any(Predicate.class)
)).thenReturn(new AsyncResult<>(Collections.<String, Object>emptyMap()));
when(admin.hasEffector(anyString(), anyString(), anyString())).thenReturn(new AsyncResult<>(true));
when(admin.invokeEffector(anyString(), anyString(), anyString(), anyString(), anyMap())).thenReturn(new AsyncResult<>(null));
when(brooklynApi.getActivityApi()).thenReturn(activityApi);
when(activityApi.get(anyString()))
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_INCOMPLETE)
.thenReturn(TASK_SUMMARY_COMPLETE);
doCallRealMethod().when(admin).blockUntilTaskCompletes(anyString());
doCallRealMethod().when(admin).blockUntilTaskCompletes(anyString(), any(Duration.class), any(Object[].class));
when(instanceRepository.findOne(anyString(), anyBoolean())).thenReturn(serviceInstance);
when(serviceDefinition.getMetadata()).thenReturn(ImmutableMap.of());
when(brooklynCatalogService.getServiceDefinition(anyString())).thenReturn(serviceDefinition);
CreateServiceInstanceBindingRequest request = new CreateServiceInstanceBindingRequest(serviceInstance.getServiceDefinitionId(), "planId", "appGuid", null);
bindingService.createServiceInstanceBinding(request.withBindingId(SVC_INST_BIND_ID));
}
@Test
public void testWhitelistCreatedSuccessfully() throws ServiceInstanceBindingExistsException, ServiceBrokerException {
bindingService = new BrooklynServiceInstanceBindingService(new BrooklynRestAdmin(brooklynApi, httpClient, config), bindingRepository, instanceRepository, brooklynCatalogService);
when(admin.getCredentialsFromSensors(anyString(), anyString(), any(Predicate.class), any(Predicate.class), any(Predicate.class), any(Predicate.class))).thenCallRealMethod();
when(brooklynApi.getSensorApi()).thenReturn(sensorApi);
when(sensorApi.list(anyString(), anyString())).thenReturn(ImmutableList.of(
new SensorSummary("my.sensor", "my sensor type", "my sensor description", ImmutableMap.of()),
new SensorSummary("sensor.one.name", "sensor one type", "sensor one description", ImmutableMap.of())
));
when(brooklynApi.getEntityApi()).thenReturn(entityApi);
when(entityApi.list(any())).thenReturn(ImmutableList.of(
new EntitySummary("entityId", "name", "entityType", "catalogItemId", ImmutableMap.of())
));
when(instanceRepository.findOne(anyString(), anyBoolean())).thenReturn(serviceInstance);
when(brooklynCatalogService.getServiceDefinition(Mockito.anyString())).thenReturn(serviceDefinition);
when(serviceInstance.getServiceDefinitionId()).thenReturn(SVC_DEFN_ID);
when(serviceDefinition.getMetadata()).thenReturn(ImmutableMap.of("planYaml", WHITELIST_YAML));
when(brooklynApi.getEffectorApi()).thenReturn(effectorApi);
when(effectorApi.invoke(anyString(), anyString(), anyString(), anyString(), anyMap())).thenReturn(bindEffectorResponse);
when(sensorApi.get(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), anyBoolean())).thenReturn("");
when(serviceInstance.getEntityId()).thenReturn("entityId");
CreateServiceInstanceBindingRequest request = new CreateServiceInstanceBindingRequest(serviceInstance.getServiceDefinitionId(), "planId", "appGuid", null);
CreateServiceInstanceBindingResponse binding = bindingService.createServiceInstanceBinding(request.withBindingId(SVC_INST_BIND_ID));
BrooklynServiceInstanceBinding expectedBinding = new BrooklynServiceInstanceBinding(SVC_INST_BIND_ID, serviceInstance.getServiceInstanceId(), EXPECTED_CREDENTIALS, "appGuid", "childEntityId");
// TODO: test binding properly
//assertEquals(expectedBinding.getAppGuid(), binding.getAppGuid());
//assertEquals(expectedBinding.getCredentials(), binding.getCredentials());
//assertEquals(expectedBinding.getServiceBindingId(), binding.getServiceBindingId());
//assertEquals(expectedBinding.getServiceInstanceId(), binding.getServiceInstanceId());
}
@Test(expected = ServiceInstanceBindingExistsException.class)
public void serviceInstanceCreationFailsWithExistingInstance()
throws ServiceBrokerException, ServiceInstanceBindingExistsException {
when(bindingRepository.findOne(anyString()))
.thenReturn(TEST_SERVICE_INSTANCE_BINDING);
when(admin.getApplicationSensors(anyString())).thenReturn(new AsyncResult<>(Collections.<String, Object>emptyMap()));
CreateServiceInstanceBindingRequest request = new CreateServiceInstanceBindingRequest(serviceInstance.getServiceDefinitionId(), "planId", "appGuid", null);
bindingService.createServiceInstanceBinding(request.withBindingId(SVC_INST_BIND_ID));
bindingService.createServiceInstanceBinding(request.withBindingId(SVC_INST_BIND_ID));
}
@Test
public void serviceInstanceBindingRetrievedSuccessfully()
throws ServiceBrokerException, ServiceInstanceBindingExistsException {
BrooklynServiceInstanceBinding binding = TEST_SERVICE_INSTANCE_BINDING;
when(bindingRepository.findOne(anyString())).thenReturn(binding);
assertEquals(binding.getServiceBindingId(), bindingService.getServiceInstanceBinding(binding.getServiceBindingId()).getServiceBindingId());
}
@Test
public void serviceInstanceBindingDeletedSuccessfully()
throws ServiceBrokerException, ServiceInstanceBindingExistsException {
BrooklynServiceInstanceBinding binding = TEST_SERVICE_INSTANCE_BINDING;
when(bindingRepository.findOne(anyString())).thenReturn(binding);
when(instanceRepository.findOne(anyString(), any(Boolean.class))).thenReturn(serviceInstance);
when(serviceInstance.getServiceDefinitionId()).thenReturn(SVC_DEFN_ID);
when(admin.invokeEffector(anyString(), anyString(), anyString(), anyString(), anyMap())).thenReturn(new AsyncResult<>("effector called"));
DeleteServiceInstanceBindingRequest request = new DeleteServiceInstanceBindingRequest(serviceInstance.getServiceInstanceId(), binding.getServiceBindingId(), "serviceId", "planId", null);
}
@Test
public void testGetSensorPredicate() {
Object rootElement = Iterables.getOnlyElement(Yamls.parseAll(WHITELIST_YAML));
Predicate<String> predicate = BrooklynServiceInstanceBindingService.getSensorWhitelistPredicate(rootElement);
assertNotNull(predicate);
assertTrue(predicate.test("foo.bar"));
assertFalse(predicate.test("bar.foo"));
}
@Test
public void testGetSensorPredicateNoPlans() {
Object rootElement = Iterables.getOnlyElement(Yamls.parseAll(NO_PLANS_YAML));
Predicate<String> predicate = BrooklynServiceInstanceBindingService.getSensorWhitelistPredicate(rootElement);
assertNotNull(predicate);
assertTrue(predicate.test("foo.bar"));
assertTrue(predicate.test("bar.foo"));
}
@Test
public void testGetSensorPredicateNoWhitelist() {
Object rootElement = Iterables.getOnlyElement(Yamls.parseAll(PLANS_YAML));
Predicate<String> predicate = BrooklynServiceInstanceBindingService.getSensorWhitelistPredicate(rootElement);
assertNotNull(predicate);
assertTrue(predicate.test("foo.bar"));
assertTrue(predicate.test("bar.foo"));
}
}