]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16464 make ES health check OS language agnostic
authorAurelien Poscia <aurelien.poscia@sonarsource.com>
Tue, 7 Jun 2022 09:22:58 +0000 (11:22 +0200)
committersonartech <sonartech@sonarsource.com>
Wed, 8 Jun 2022 20:02:53 +0000 (20:02 +0000)
server/sonar-main/src/main/java/org/sonar/application/process/EsManagedProcess.java
server/sonar-main/src/test/java/org/sonar/application/process/EsManagedProcessTest.java

index a5864cf9e7531b5923687625babb5445aa431d54..44f437b323c01758916f7adc21c046c373d52e24 100644 (file)
  */
 package org.sonar.application.process;
 
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.net.ConnectException;
 import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
-import org.elasticsearch.rest.RestStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.application.es.EsConnector;
@@ -39,11 +36,9 @@ import static org.sonar.application.process.EsManagedProcess.Status.YELLOW;
 public class EsManagedProcess extends AbstractManagedProcess {
   private static final Logger LOG = LoggerFactory.getLogger(EsManagedProcess.class);
   private static final int WAIT_FOR_UP_DELAY_IN_MILLIS = 100;
-  private static final Set<String> SUPPRESSED_ERROR_MESSAGES = Set.of("Connection refused", "Timeout connecting");
 
   private volatile boolean nodeOperational = false;
   private final int waitForUpTimeout;
-  private final AtomicBoolean firstMasterNotDiscoveredLog = new AtomicBoolean(true);
   private final EsConnector esConnector;
 
   public EsManagedProcess(Process process, ProcessId processId, EsConnector esConnector) {
@@ -97,19 +92,11 @@ public class EsManagedProcess extends AbstractManagedProcess {
       return esConnector.getClusterHealthStatus()
         .map(EsManagedProcess::convert)
         .orElse(CONNECTION_REFUSED);
-    } catch (ElasticsearchStatusException e) {
-      if (e.status() == RestStatus.SERVICE_UNAVAILABLE && e.getMessage().contains("type=master_not_discovered_exception")) {
-        if (firstMasterNotDiscoveredLog.getAndSet(false)) {
-          LOG.info("Elasticsearch is waiting for a master to be elected. Did you start all the search nodes ?");
-        }
-      }
-      return KO;
     } catch (ElasticsearchException e) {
-      if (e.status() == RestStatus.INTERNAL_SERVER_ERROR && (SUPPRESSED_ERROR_MESSAGES.stream().anyMatch(s -> e.getMessage().contains(s)))) {
+      if (e.getRootCause() instanceof ConnectException) {
         return CONNECTION_REFUSED;
-      } else {
-        LOG.error("Failed to check status", e);
       }
+      LOG.error("Failed to check status", e);
       return KO;
     } catch (Exception e) {
       LOG.error("Failed to check status", e);
index 9d8169f3b625c4d2fbdf681efd640a14b9d53dd6..b3baaef99e68809bbff8d9097d68988ff7c7aa4c 100644 (file)
  */
 package org.sonar.application.process;
 
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.AppenderBase;
 import java.net.ConnectException;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
 import org.elasticsearch.ElasticsearchException;
-import org.elasticsearch.ElasticsearchStatusException;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
-import org.elasticsearch.rest.RestStatus;
 import org.junit.Test;
-import org.slf4j.LoggerFactory;
 import org.sonar.application.es.EsConnector;
 import org.sonar.process.ProcessId;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.tuple;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -128,49 +118,29 @@ public class EsManagedProcessTest {
   }
 
   @Test
-  public void isOperational_should_return_false_if_ElasticsearchException_thrown() {
+  public void isOperational_should_not_be_os_language_sensitive() {
     EsConnector esConnector = mock(EsConnector.class);
     when(esConnector.getClusterHealthStatus())
-      .thenThrow(new ElasticsearchException("test"));
-    EsManagedProcess underTest = new EsManagedProcess(mock(Process.class), ProcessId.ELASTICSEARCH, esConnector, WAIT_FOR_UP_TIMEOUT);
+      .thenThrow(new ElasticsearchException(new ExecutionException(new ConnectException("Connexion refusée"))));
+    EsManagedProcess underTest = new EsManagedProcess(mock(Process.class), ProcessId.ELASTICSEARCH, esConnector, WAIT_FOR_UP_TIMEOUT_LONG);
     assertThat(underTest.isOperational()).isFalse();
   }
 
   @Test
-  public void isOperational_must_log_once_when_master_is_not_elected() {
-    MemoryAppender<ILoggingEvent> memoryAppender = new MemoryAppender<>();
-    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-    lc.reset();
-    memoryAppender.setContext(lc);
-    memoryAppender.start();
-    lc.getLogger(EsManagedProcess.class).addAppender(memoryAppender);
-
+  public void isOperational_if_exception_root_cause_returned_by_ES_is_not_ConnectException_should_return_false() {
     EsConnector esConnector = mock(EsConnector.class);
     when(esConnector.getClusterHealthStatus())
-      .thenThrow(new ElasticsearchStatusException("foobar[type=master_not_discovered_exception,acme]...", RestStatus.SERVICE_UNAVAILABLE));
-
-    EsManagedProcess underTest = new EsManagedProcess(mock(Process.class), ProcessId.ELASTICSEARCH, esConnector, WAIT_FOR_UP_TIMEOUT);
-    assertThat(underTest.isOperational()).isFalse();
-    assertThat(memoryAppender.events).isNotEmpty();
-    assertThat(memoryAppender.events)
-      .extracting(ILoggingEvent::getLevel, ILoggingEvent::getMessage)
-      .containsOnlyOnce(
-        tuple(Level.INFO, "Elasticsearch is waiting for a master to be elected. Did you start all the search nodes ?"));
-
-    // Second call must not log another message
+      .thenThrow(new ElasticsearchException(new ExecutionException(new Exception("Connexion refusée"))));
+    EsManagedProcess underTest = new EsManagedProcess(mock(Process.class), ProcessId.ELASTICSEARCH, esConnector, WAIT_FOR_UP_TIMEOUT_LONG);
     assertThat(underTest.isOperational()).isFalse();
-    assertThat(memoryAppender.events)
-      .extracting(ILoggingEvent::getLevel, ILoggingEvent::getMessage)
-      .containsOnlyOnce(
-        tuple(Level.INFO, "Elasticsearch is waiting for a master to be elected. Did you start all the search nodes ?"));
   }
 
-  private static class MemoryAppender<E> extends AppenderBase<E> {
-    private final List<E> events = new ArrayList<>();
-
-    @Override
-    protected void append(E eventObject) {
-      events.add(eventObject);
-    }
+  @Test
+  public void isOperational_should_return_false_if_ElasticsearchException_thrown() {
+    EsConnector esConnector = mock(EsConnector.class);
+    when(esConnector.getClusterHealthStatus())
+      .thenThrow(new ElasticsearchException("test"));
+    EsManagedProcess underTest = new EsManagedProcess(mock(Process.class), ProcessId.ELASTICSEARCH, esConnector, WAIT_FOR_UP_TIMEOUT);
+    assertThat(underTest.isOperational()).isFalse();
   }
 }