package com.sequenceiq.cloudbreak.reactor;
import com.sequenceiq.cloudbreak.core.CloudbreakSecuritySetupException;
import com.sequenceiq.cloudbreak.domain.InstanceMetaData;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.reactor.api.event.EventSelectorUtil;
import com.sequenceiq.cloudbreak.reactor.api.event.resource.UnhealthyInstancesDetectionRequest;
import com.sequenceiq.cloudbreak.reactor.api.event.resource.UnhealthyInstancesDetectionResult;
import com.sequenceiq.cloudbreak.service.stack.StackService;
import com.sequenceiq.cloudbreak.service.stack.repair.CandidateUnhealthyInstanceSelector;
import com.sequenceiq.cloudbreak.service.stack.repair.UnhealthyInstancesFinalizer;
import org.hamcrest.Description;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import reactor.bus.Event;
import reactor.bus.EventBus;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.argThat;
@RunWith(MockitoJUnitRunner.class)
public class UnhealthyInstancesDetectionHandlerTest {
@Mock
private StackService stackService;
@Mock
private CandidateUnhealthyInstanceSelector candidateUnhealthyInstanceSelector;
@Mock
private UnhealthyInstancesFinalizer unhealthyInstancesFinalizer;
@Mock
private EventBus eventBus;
@InjectMocks
private UnhealthyInstancesDetectionHandler unhealthyInstancesDetectionHandler;
@Test
public void shouldNotInvokeFinalizerIfNoCandidateUnhealthyInstancesWereSelected() throws CloudbreakSecuritySetupException {
long stackId = 1L;
UnhealthyInstancesDetectionRequest unhealthyInstancesDetectionRequest = new UnhealthyInstancesDetectionRequest(stackId);
Event event = mock(Event.class);
when(event.getData()).thenReturn(unhealthyInstancesDetectionRequest);
Stack stack = mock(Stack.class);
when(stackService.getById(stackId)).thenReturn(stack);
when(candidateUnhealthyInstanceSelector.selectCandidateUnhealthyInstances(stack)).thenReturn(Collections.EMPTY_SET);
unhealthyInstancesDetectionHandler.accept(event);
verifyZeroInteractions(unhealthyInstancesFinalizer);
verify(eventBus).notify(eq(EventSelectorUtil.selector(UnhealthyInstancesDetectionResult.class)),
argThat(new UnhealthyInstancesResultMatcher(Collections.EMPTY_SET)));
}
@Test
public void shouldCreateResponseWithExactInstances() throws CloudbreakSecuritySetupException {
long stackId = 1L;
UnhealthyInstancesDetectionRequest unhealthyInstancesDetectionRequest = new UnhealthyInstancesDetectionRequest(stackId);
Event event = mock(Event.class);
when(event.getData()).thenReturn(unhealthyInstancesDetectionRequest);
Stack stack = mock(Stack.class);
when(stackService.getById(stackId)).thenReturn(stack);
Set<InstanceMetaData> unhealthyInstances = new HashSet<>();
InstanceMetaData imd1 = mock(InstanceMetaData.class);
InstanceMetaData imd2 = mock(InstanceMetaData.class);
InstanceMetaData imd3 = mock(InstanceMetaData.class);
unhealthyInstances.add(imd1);
unhealthyInstances.add(imd2);
unhealthyInstances.add(imd3);
when(candidateUnhealthyInstanceSelector.selectCandidateUnhealthyInstances(stack)).thenReturn(unhealthyInstances);
Set<String> unhealthyInstanceIds = new HashSet<>();
unhealthyInstanceIds.add("i-0f1e0605506aaaaaa");
unhealthyInstanceIds.add("i-0f1e0605506cccccc");
when(unhealthyInstancesFinalizer.finalizeUnhealthyInstances(stack, unhealthyInstances)).thenReturn(unhealthyInstanceIds);
unhealthyInstancesDetectionHandler.accept(event);
verify(eventBus).notify(eq(EventSelectorUtil.selector(UnhealthyInstancesDetectionResult.class)),
argThat(new UnhealthyInstancesResultMatcher(unhealthyInstanceIds)));
}
private class UnhealthyInstancesResultMatcher extends ArgumentMatcher<Event<UnhealthyInstancesDetectionResult>> {
private Set<String> expectedUnhealthyIds;
private String errorMessage;
UnhealthyInstancesResultMatcher(Set<String> expectedUnhealthyIds) {
this.expectedUnhealthyIds = expectedUnhealthyIds;
}
@Override
public boolean matches(Object argument) {
Event event = (Event) argument;
UnhealthyInstancesDetectionResult payload = (UnhealthyInstancesDetectionResult) event.getData();
Set<String> unhealthyInstanceIds = payload.getUnhealthyInstanceIds();
if (unhealthyInstanceIds.size() != expectedUnhealthyIds.size()) {
errorMessage = String.format("Sizes don't match, expected=%d, actual=%d",
expectedUnhealthyIds.size(), unhealthyInstanceIds.size());
return false;
}
for (String i : expectedUnhealthyIds) {
if (!unhealthyInstanceIds.contains(i)) {
errorMessage = String.format("Expected unhealthy instance id %s not found in actual instances %s",
i, unhealthyInstanceIds);
return false;
}
}
return true;
}
@Override
public void describeTo(Description description) {
if (errorMessage == null) {
super.describeTo(description);
} else {
description.appendText(errorMessage);
}
}
}
}