3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.common.health;
22 import com.google.common.collect.ImmutableSet;
23 import java.util.Random;
25 import org.elasticsearch.cluster.health.ClusterHealthStatus;
26 import org.junit.Test;
27 import org.mockito.Mockito;
28 import org.sonar.process.cluster.health.NodeDetails;
29 import org.sonar.process.cluster.health.NodeHealth;
30 import org.sonar.server.common.health.EsStatusClusterCheck;
31 import org.sonar.server.es.EsClient;
32 import org.sonar.server.health.Health;
34 import static org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric;
35 import static org.assertj.core.api.Assertions.assertThat;
36 import static org.mockito.ArgumentMatchers.any;
37 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
38 import static org.mockito.Mockito.when;
39 import static org.sonar.process.cluster.health.NodeHealth.Status.GREEN;
41 public class EsStatusClusterCheckTest {
43 private EsClient esClient = Mockito.mock(EsClient.class, RETURNS_DEEP_STUBS);
44 private Random random = new Random();
45 private EsStatusClusterCheck underTest = new EsStatusClusterCheck(esClient);
48 public void check_ignores_NodeHealth_arg_and_returns_RED_with_cause_if_an_exception_occurs_checking_ES_cluster_status() {
49 Set<NodeHealth> nodeHealths = ImmutableSet.of(newNodeHealth(NodeHealth.Status.GREEN));
50 when(esClient.clusterHealth(any())).thenThrow(new RuntimeException("Faking an exception occurring while using the EsClient"));
52 Health health = new EsStatusClusterCheck(esClient).check(nodeHealths);
54 assertThat(health.getStatus()).isEqualTo(Health.Status.RED);
55 assertThat(health.getCauses()).containsOnly("Elasticsearch status is RED (unavailable)");
59 public void check_ignores_NodeHealth_arg_and_returns_GREEN_without_cause_if_ES_cluster_status_is_GREEN() {
60 Set<NodeHealth> nodeHealths = ImmutableSet.of(newNodeHealth(NodeHealth.Status.YELLOW));
61 when(esClient.clusterHealth(any()).getStatus()).thenReturn(ClusterHealthStatus.GREEN);
62 when(esClient.clusterHealth(any()).getNumberOfNodes()).thenReturn(3);
64 Health health = underTest.check(nodeHealths);
66 assertThat(health).isEqualTo(Health.GREEN);
70 public void check_returns_YELLOW_with_cause_if_ES_cluster_has_less_than_three_nodes_but_status_is_green() {
71 Set<NodeHealth> nodeHealths = ImmutableSet.of(newNodeHealth(GREEN));
72 when(esClient.clusterHealth(any()).getStatus()).thenReturn(ClusterHealthStatus.GREEN);
73 when(esClient.clusterHealth(any()).getNumberOfNodes()).thenReturn(2);
75 Health health = underTest.check(nodeHealths);
77 assertThat(health.getStatus()).isEqualTo(Health.Status.YELLOW);
78 assertThat(health.getCauses()).containsOnly("There should be at least three search nodes");
82 public void check_returns_RED_with_cause_if_ES_cluster_has_less_than_three_nodes_and_status_is_RED() {
83 Set<NodeHealth> nodeHealths = ImmutableSet.of(newNodeHealth(GREEN));
84 when(esClient.clusterHealth(any()).getStatus()).thenReturn(ClusterHealthStatus.RED);
85 when(esClient.clusterHealth(any()).getNumberOfNodes()).thenReturn(2);
87 Health health = underTest.check(nodeHealths);
89 assertThat(health.getStatus()).isEqualTo(Health.Status.RED);
90 assertThat(health.getCauses()).contains("Elasticsearch status is RED", "There should be at least three search nodes");
94 private NodeHealth newNodeHealth(NodeHealth.Status status) {
95 return NodeHealth.newNodeHealthBuilder()
97 .setDetails(NodeDetails.newNodeDetailsBuilder()
98 .setType(random.nextBoolean() ? NodeDetails.Type.APPLICATION : NodeDetails.Type.SEARCH)
99 .setName(randomAlphanumeric(23))
100 .setHost(randomAlphanumeric(23))
101 .setPort(1 + random.nextInt(96))
102 .setStartedAt(1 + random.nextInt(966))