package com.sequenceiq.cloudbreak.core.bootstrap.service;
import static org.mockito.AdditionalAnswers.returnsFirstArg;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anySet;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doNothing;
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.HashSet;
import java.util.Set;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import com.sequenceiq.cloudbreak.TestUtil;
import com.sequenceiq.cloudbreak.common.type.ResourceType;
import com.sequenceiq.cloudbreak.domain.InstanceGroup;
import com.sequenceiq.cloudbreak.domain.InstanceMetaData;
import com.sequenceiq.cloudbreak.domain.Resource;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.orchestrator.container.ContainerOrchestrator;
import com.sequenceiq.cloudbreak.orchestrator.exception.CloudbreakOrchestratorFailedException;
import com.sequenceiq.cloudbreak.orchestrator.model.GatewayConfig;
import com.sequenceiq.cloudbreak.orchestrator.model.Node;
import com.sequenceiq.cloudbreak.repository.HostMetadataRepository;
import com.sequenceiq.cloudbreak.repository.InstanceGroupRepository;
import com.sequenceiq.cloudbreak.repository.InstanceMetaDataRepository;
import com.sequenceiq.cloudbreak.repository.ResourceRepository;
import com.sequenceiq.cloudbreak.service.events.CloudbreakEventService;
import com.sequenceiq.cloudbreak.service.messages.CloudbreakMessagesService;
import com.sequenceiq.cloudbreak.service.stack.connector.adapter.ServiceProviderConnectorAdapter;
import com.sequenceiq.cloudbreak.service.stack.connector.adapter.ServiceProviderMetadataAdapter;
@RunWith(MockitoJUnitRunner.class)
public class ClusterBootstrapperErrorHandlerTest {
@Mock
private ResourceRepository resourceRepository;
@Mock
private InstanceMetaDataRepository instanceMetaDataRepository;
@Mock
private InstanceGroupRepository instanceGroupRepository;
@Mock
private HostMetadataRepository hostMetadataRepository;
//private CloudPlatformResolver platformResolver;
@Mock
private CloudbreakEventService eventService;
@Mock
private ContainerOrchestrator orchestrator;
//@Mock
//private ServiceProviderMetadataAdapter metadataSetup;
@Mock
private CloudbreakMessagesService cloudbreakMessagesService;
@Mock
private ServiceProviderConnectorAdapter connector;
@Mock
private ServiceProviderMetadataAdapter metadata;
@InjectMocks
private ClusterBootstrapperErrorHandler underTest;
@Test(expected = CloudbreakOrchestratorFailedException.class)
public void clusterBootstrapErrorHandlerWhenNodeCountLessThanOneAfterTheRollbackThenClusterProvisionFailed() throws CloudbreakOrchestratorFailedException {
final Stack stack = TestUtil.stack();
doNothing().when(eventService).fireCloudbreakEvent(anyLong(), anyString(), anyString());
when(orchestrator.getAvailableNodes(any(GatewayConfig.class), anySet())).thenReturn(new ArrayList<>());
when(instanceGroupRepository.save(any(InstanceGroup.class))).then(returnsFirstArg());
when(instanceMetaDataRepository.save(any(InstanceMetaData.class))).then(returnsFirstArg());
when(instanceMetaDataRepository.findNotTerminatedByPrivateAddress(anyLong(), anyString())).thenAnswer(new Answer<InstanceMetaData>() {
@Override
public InstanceMetaData answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
String ip = (String) args[1];
for (InstanceMetaData instanceMetaData : stack.getRunningInstanceMetaData()) {
if (instanceMetaData.getPrivateIp().equals(ip)) {
return instanceMetaData;
}
}
return null;
}
});
when(instanceGroupRepository.findOneByGroupNameInStack(anyLong(), anyString())).thenAnswer(new Answer<InstanceGroup>() {
@Override
public InstanceGroup answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
String name = (String) args[1];
for (InstanceMetaData instanceMetaData : stack.getRunningInstanceMetaData()) {
if (instanceMetaData.getInstanceGroup().getGroupName().equals(name)) {
return instanceMetaData.getInstanceGroup();
}
}
return null;
}
});
underTest.terminateFailedNodes(null, orchestrator, TestUtil.stack(),
new GatewayConfig("10.0.0.1", "198.0.0.1", "10.0.0.1", 8443, "/cert/1", false), prepareNodes(stack));
}
@Test
public void clusterBootstrapErrorHandlerWhenNodeCountHigherThanZeroAfterTheRollbackThenClusterProvisionFailed()
throws CloudbreakOrchestratorFailedException {
final Stack stack = TestUtil.stack();
doNothing().when(eventService).fireCloudbreakEvent(anyLong(), anyString(), anyString());
when(orchestrator.getAvailableNodes(any(GatewayConfig.class), anySet())).thenReturn(new ArrayList<>());
when(instanceGroupRepository.save(any(InstanceGroup.class))).then(returnsFirstArg());
when(instanceMetaDataRepository.save(any(InstanceMetaData.class))).then(returnsFirstArg());
doNothing().when(resourceRepository).delete(anyLong());
when(resourceRepository.findByStackIdAndNameAndType(anyLong(), anyString(), any(ResourceType.class))).thenReturn(new Resource());
when(connector.removeInstances(any(Stack.class), anySet(), anyString())).thenReturn(new HashSet<>());
when(instanceMetaDataRepository.findNotTerminatedByPrivateAddress(anyLong(), anyString())).thenAnswer(new Answer<InstanceMetaData>() {
@Override
public InstanceMetaData answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
String ip = (String) args[1];
for (InstanceMetaData instanceMetaData : stack.getRunningInstanceMetaData()) {
if (instanceMetaData.getPrivateIp().equals(ip)) {
return instanceMetaData;
}
}
return null;
}
});
when(instanceGroupRepository.findOneByGroupNameInStack(anyLong(), anyString())).thenAnswer(new Answer<InstanceGroup>() {
@Override
public InstanceGroup answer(InvocationOnMock invocation) {
Object[] args = invocation.getArguments();
String name = (String) args[1];
for (InstanceMetaData instanceMetaData : stack.getRunningInstanceMetaData()) {
if (instanceMetaData.getInstanceGroup().getGroupName().equals(name)) {
InstanceGroup instanceGroup = instanceMetaData.getInstanceGroup();
instanceGroup.setNodeCount(2);
return instanceGroup;
}
}
return null;
}
});
underTest.terminateFailedNodes(null, orchestrator, TestUtil.stack(),
new GatewayConfig("10.0.0.1", "198.0.0.1", "10.0.0.1", 8443, "/cert/1", false), prepareNodes(stack));
verify(eventService, times(4)).fireCloudbreakEvent(anyLong(), anyString(), anyString());
verify(instanceGroupRepository, times(3)).save(any(InstanceGroup.class));
verify(instanceMetaDataRepository, times(3)).save(any(InstanceMetaData.class));
verify(connector, times(3)).removeInstances(any(Stack.class), anySet(), anyString());
verify(resourceRepository, times(3)).findByStackIdAndNameAndType(anyLong(), anyString(), any(ResourceType.class));
verify(resourceRepository, times(3)).delete(anyLong());
verify(instanceGroupRepository, times(3)).findOneByGroupNameInStack(anyLong(), anyString());
}
private Set<Node> prepareNodes(Stack stack) {
Set<Node> nodes = new HashSet<>();
for (InstanceMetaData instanceMetaData : stack.getRunningInstanceMetaData()) {
nodes.add(new Node(instanceMetaData.getPrivateIp(), instanceMetaData.getPublicIpWrapper()));
}
return nodes;
}
}