aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessAction.java58
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessActionSupport.java59
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessChecker.java24
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessCheckerImpl.java66
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessAction.java50
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImpl.java36
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafemodeSystemWsModule.java7
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SystemWsModule.java5
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessActionTest.java100
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessCheckerImplTest.java92
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessActionTest.java84
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImplTest.java50
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafemodeSystemWsModuleTest.java2
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SystemWsModuleTest.java2
14 files changed, 630 insertions, 5 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessAction.java
new file mode 100644
index 00000000000..2876e5c64f8
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessAction.java
@@ -0,0 +1,58 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.SystemPasscode;
+import org.sonar.server.user.UserSession;
+
+public class LivenessAction implements SystemWsAction {
+ private final LivenessActionSupport livenessActionSupport;
+ private final SystemPasscode systemPasscode;
+ private final UserSession userSession;
+
+ public LivenessAction(LivenessActionSupport livenessActionSupport, SystemPasscode systemPasscode, UserSession userSession) {
+ this.livenessActionSupport = livenessActionSupport;
+ this.systemPasscode = systemPasscode;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ livenessActionSupport.define(controller, this);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ if (!systemPasscode.isValid(request) && !isSystemAdmin()) {
+ throw new ForbiddenException("Insufficient privileges");
+ }
+
+ livenessActionSupport.checkliveness(response);
+ }
+
+ private boolean isSystemAdmin() {
+ return userSession.isSystemAdministrator();
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessActionSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessActionSupport.java
new file mode 100644
index 00000000000..9dc80850c71
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessActionSupport.java
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+
+public class LivenessActionSupport {
+
+ private final LivenessChecker livenessChecker;
+
+ public LivenessActionSupport(LivenessChecker livenessChecker) {
+ this.livenessChecker = livenessChecker;
+ }
+
+ void define(WebService.NewController controller, SystemWsAction handler) {
+ controller.createAction("liveness")
+ .setDescription("Provide liveness of SonarQube, meant to be used for a liveness probe on Kubernetes" +
+ "<p>Require 'Administer System' permission or authentication with passcode</p>" +
+ "<p>When SonarQube is fully started, liveness check for database connectivity, Compute Engine status," +
+ " and, except for DataCenter Edition, if ElasticSearch is Green or Yellow</p>"+
+ "<p>When SonarQube is on Safe Mode (for example when a database migration is running), liveness check only for database connectivity</p>"+
+ "<p> " +
+ " <ul>" +
+ " <li>HTTP 204: this SonarQube node is alive</li>" +
+ " <li>Any other HTTP code: this SonarQube node is not alive, and should be reschedule</li>" +
+ " </ul>" +
+ "</p>")
+ .setSince("9.1")
+ .setInternal(true)
+ .setHandler(handler);
+ }
+
+ void checkliveness(Response response) {
+ if (livenessChecker.liveness()) {
+ response.noContent();
+ } else {
+ throw new IllegalStateException("Liveness check failed");
+ }
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessChecker.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessChecker.java
new file mode 100644
index 00000000000..013d8fc5788
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessChecker.java
@@ -0,0 +1,24 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+public interface LivenessChecker {
+ boolean liveness();
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessCheckerImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessCheckerImpl.java
new file mode 100644
index 00000000000..0be2dd55e6a
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/LivenessCheckerImpl.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.server.health.CeStatusNodeCheck;
+import org.sonar.server.health.DbConnectionNodeCheck;
+import org.sonar.server.health.EsStatusNodeCheck;
+import org.sonar.server.health.Health;
+import org.sonar.server.health.WebServerStatusNodeCheck;
+import org.sonar.server.platform.WebServer;
+
+public class LivenessCheckerImpl implements LivenessChecker {
+
+ private final WebServer webServer;
+ private final DbConnectionNodeCheck dbConnectionNodeCheck;
+ private final CeStatusNodeCheck ceStatusNodeCheck;
+ private final EsStatusNodeCheck esStatusNodeCheck;
+ private final WebServerStatusNodeCheck webServerStatusNodeCheck;
+
+ public LivenessCheckerImpl(WebServer webServer, DbConnectionNodeCheck dbConnectionNodeCheck,
+ WebServerStatusNodeCheck webServerStatusNodeCheck, CeStatusNodeCheck ceStatusNodeCheck, EsStatusNodeCheck esStatusNodeCheck) {
+ this.webServer = webServer;
+ this.dbConnectionNodeCheck = dbConnectionNodeCheck;
+ this.ceStatusNodeCheck = ceStatusNodeCheck;
+ this.esStatusNodeCheck = esStatusNodeCheck;
+ this.webServerStatusNodeCheck = webServerStatusNodeCheck;
+ }
+
+ public boolean liveness() {
+
+ if (!Health.Status.GREEN.equals(dbConnectionNodeCheck.check().getStatus())) {
+ return false;
+ }
+
+ if (!Health.Status.GREEN.equals(webServerStatusNodeCheck.check().getStatus())) {
+ return false;
+ }
+
+ if (!Health.Status.GREEN.equals(ceStatusNodeCheck.check().getStatus())) {
+ return false;
+ }
+
+ if (webServer.isStandalone() && Health.Status.RED.equals(esStatusNodeCheck.check().getStatus())) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessAction.java
new file mode 100644
index 00000000000..38cb538b8ed
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessAction.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.SystemPasscode;
+
+public class SafeModeLivenessAction implements SystemWsAction {
+ private final LivenessActionSupport livenessActionSupport;
+ private final SystemPasscode systemPasscode;
+
+ public SafeModeLivenessAction(LivenessActionSupport livenessActionSupport, SystemPasscode systemPasscode) {
+ this.livenessActionSupport = livenessActionSupport;
+ this.systemPasscode = systemPasscode;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ livenessActionSupport.define(controller, this);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ if (!systemPasscode.isValid(request)) {
+ throw new ForbiddenException("Insufficient privileges");
+ }
+
+ livenessActionSupport.checkliveness(response);
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImpl.java
new file mode 100644
index 00000000000..519acf31fa2
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImpl.java
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.sonar.server.health.DbConnectionNodeCheck;
+import org.sonar.server.health.Health;
+
+public class SafeModeLivenessCheckerImpl implements LivenessChecker {
+
+ private final DbConnectionNodeCheck dbConnectionNodeCheck;
+
+ public SafeModeLivenessCheckerImpl(DbConnectionNodeCheck dbConnectionNodeCheck) {
+ this.dbConnectionNodeCheck = dbConnectionNodeCheck;
+ }
+
+ public boolean liveness() {
+ return Health.Status.GREEN.equals(dbConnectionNodeCheck.check().getStatus());
+ }
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafemodeSystemWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafemodeSystemWsModule.java
index f6b4c329da9..7a5df9d2f33 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafemodeSystemWsModule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SafemodeSystemWsModule.java
@@ -30,8 +30,9 @@ public class SafemodeSystemWsModule extends Module {
DbMigrationStatusAction.class,
HealthActionSupport.class,
SafeModeHealthAction.class,
- SystemWs.class
-
- );
+ SafeModeLivenessCheckerImpl.class,
+ LivenessActionSupport.class,
+ SafeModeLivenessAction.class,
+ SystemWs.class);
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SystemWsModule.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SystemWsModule.java
index c8e16bfc366..4b907ca10aa 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SystemWsModule.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/platform/ws/SystemWsModule.java
@@ -30,6 +30,11 @@ public class SystemWsModule extends Module {
DbMigrationStatusAction.class,
HealthActionSupport.class,
HealthAction.class,
+
+ LivenessCheckerImpl.class,
+ LivenessActionSupport.class,
+ LivenessAction.class,
+
InfoAction.class,
LogsAction.class,
MigrateDbAction.class,
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessActionTest.java
new file mode 100644
index 00000000000..fbbc1b98b91
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessActionTest.java
@@ -0,0 +1,100 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.user.SystemPasscode;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class LivenessActionTest {
+
+ @Rule
+ public UserSessionRule userSessionRule = UserSessionRule.standalone();
+
+ private final SystemPasscode systemPasscode = mock(SystemPasscode.class);
+ private final LivenessChecker livenessChecker = mock(LivenessChecker.class);
+ private final LivenessActionSupport livenessActionSupport = new LivenessActionSupport(livenessChecker);
+ private final WsActionTester underTest = new WsActionTester(new LivenessAction(livenessActionSupport, systemPasscode, userSessionRule));
+
+ @Test
+ public void verify_definition() {
+ WebService.Action definition = underTest.getDef();
+
+ assertThat(definition.key()).isEqualTo("liveness");
+ assertThat(definition.isPost()).isFalse();
+ assertThat(definition.description()).isNotEmpty();
+ assertThat(definition.since()).isEqualTo("9.1");
+ assertThat(definition.isInternal()).isTrue();
+ assertThat(definition.responseExample()).isNull();
+ assertThat(definition.params()).isEmpty();
+ }
+
+ @Test
+ public void fail_when_system_passcode_is_invalid() {
+ when(systemPasscode.isValid(any())).thenReturn(false);
+
+ TestRequest request = underTest.newRequest();
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(ForbiddenException.class)
+ .hasMessage("Insufficient privileges");
+ }
+
+ @Test
+ public void fail_when_user_is_not_system_admin() {
+ when(systemPasscode.isValid(any())).thenReturn(false);
+ userSessionRule.logIn();
+
+ TestRequest request = underTest.newRequest();
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(ForbiddenException.class)
+ .hasMessage("Insufficient privileges");
+ }
+
+ @Test
+ public void liveness_check_failed_expect_500() {
+ when(systemPasscode.isValid(any())).thenReturn(true);
+ when(livenessChecker.liveness()).thenReturn(false);
+
+ TestRequest request = underTest.newRequest();
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage("Liveness check failed");
+ }
+
+ @Test
+ public void liveness_check_success_expect_204() {
+ when(systemPasscode.isValid(any())).thenReturn(true);
+ when(livenessChecker.liveness()).thenReturn(true);
+
+ assertThat(underTest.newRequest().execute().getStatus()).isEqualTo(204);
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessCheckerImplTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessCheckerImplTest.java
new file mode 100644
index 00000000000..75e73cb9638
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/LivenessCheckerImplTest.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.sonar.server.health.CeStatusNodeCheck;
+import org.sonar.server.health.DbConnectionNodeCheck;
+import org.sonar.server.health.EsStatusNodeCheck;
+import org.sonar.server.health.Health;
+import org.sonar.server.health.WebServerStatusNodeCheck;
+import org.sonar.server.platform.WebServer;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class LivenessCheckerImplTest {
+
+ public static final Health RED = Health.newHealthCheckBuilder().setStatus(Health.Status.RED).build();
+
+ private final WebServer webServer = mock(WebServer.class);
+ private final DbConnectionNodeCheck dbConnectionNodeCheck = mock(DbConnectionNodeCheck.class);
+ private final WebServerStatusNodeCheck webServerStatusNodeCheck = mock(WebServerStatusNodeCheck.class);
+ private final CeStatusNodeCheck ceStatusNodeCheck = mock(CeStatusNodeCheck.class);
+ private final EsStatusNodeCheck esStatusNodeCheck = mock(EsStatusNodeCheck.class);
+
+ LivenessCheckerImpl underTest = new LivenessCheckerImpl(webServer, dbConnectionNodeCheck, webServerStatusNodeCheck, ceStatusNodeCheck, esStatusNodeCheck);
+
+ @Test
+ public void fail_when_db_connexion_check_fail() {
+ when(dbConnectionNodeCheck.check()).thenReturn(RED);
+
+ Assertions.assertThat(underTest.liveness()).isFalse();
+ }
+
+ @Test
+ public void fail_when_web_check_fail() {
+ when(dbConnectionNodeCheck.check()).thenReturn(Health.GREEN);
+ when(webServerStatusNodeCheck.check()).thenReturn(RED);
+
+ Assertions.assertThat(underTest.liveness()).isFalse();
+ }
+
+ @Test
+ public void fail_when_ce_check_fail() {
+ when(dbConnectionNodeCheck.check()).thenReturn(Health.GREEN);
+ when(webServerStatusNodeCheck.check()).thenReturn(Health.GREEN);
+ when(ceStatusNodeCheck.check()).thenReturn(RED);
+
+ Assertions.assertThat(underTest.liveness()).isFalse();
+ }
+
+ @Test
+ public void dont_fail_when_not_standalone_but_es_check_fail() {
+ when(dbConnectionNodeCheck.check()).thenReturn(Health.GREEN);
+ when(webServerStatusNodeCheck.check()).thenReturn(Health.GREEN);
+ when(ceStatusNodeCheck.check()).thenReturn(Health.GREEN);
+ when(webServer.isStandalone()).thenReturn(false);
+ when(esStatusNodeCheck.check()).thenReturn(RED);
+
+ Assertions.assertThat(underTest.liveness()).isTrue();
+ }
+
+ @Test
+ public void fail_when_not_dce_and_es_check_fail() {
+ when(dbConnectionNodeCheck.check()).thenReturn(Health.GREEN);
+ when(webServerStatusNodeCheck.check()).thenReturn(Health.GREEN);
+ when(ceStatusNodeCheck.check()).thenReturn(Health.GREEN);
+ when(webServer.isStandalone()).thenReturn(true);
+ when(esStatusNodeCheck.check()).thenReturn(RED);
+
+ Assertions.assertThat(underTest.liveness()).isFalse();
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessActionTest.java
new file mode 100644
index 00000000000..c634451de25
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessActionTest.java
@@ -0,0 +1,84 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.user.SystemPasscode;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SafeModeLivenessActionTest {
+
+ private final SystemPasscode systemPasscode = mock(SystemPasscode.class);
+ private final LivenessChecker livenessChecker = mock(LivenessChecker.class);
+ private final LivenessActionSupport livenessActionSupport = new LivenessActionSupport(livenessChecker);
+ private final WsActionTester underTest = new WsActionTester(new SafeModeLivenessAction(livenessActionSupport, systemPasscode));
+
+ @Test
+ public void verify_definition() {
+ WebService.Action definition = underTest.getDef();
+
+ assertThat(definition.key()).isEqualTo("liveness");
+ assertThat(definition.isPost()).isFalse();
+ assertThat(definition.description()).isNotEmpty();
+ assertThat(definition.since()).isEqualTo("9.1");
+ assertThat(definition.isInternal()).isTrue();
+ assertThat(definition.responseExample()).isNull();
+ assertThat(definition.params()).isEmpty();
+ }
+
+ @Test
+ public void fail_when_system_passcode_is_invalid() {
+ when(systemPasscode.isValid(any())).thenReturn(false);
+
+ TestRequest request = underTest.newRequest();
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(ForbiddenException.class)
+ .hasMessage("Insufficient privileges");
+ }
+
+ @Test
+ public void liveness_check_failed_expect_500() {
+ when(systemPasscode.isValid(any())).thenReturn(true);
+ when(livenessChecker.liveness()).thenReturn(false);
+
+ TestRequest request = underTest.newRequest();
+ assertThatThrownBy(request::execute)
+ .isInstanceOf(IllegalStateException.class)
+ .hasMessage("Liveness check failed");
+ }
+
+ @Test
+ public void liveness_check_success_expect_204() {
+ when(systemPasscode.isValid(any())).thenReturn(true);
+ when(livenessChecker.liveness()).thenReturn(true);
+
+ assertThat(underTest.newRequest().execute().getStatus()).isEqualTo(204);
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImplTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImplTest.java
new file mode 100644
index 00000000000..06cc8c7171e
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafeModeLivenessCheckerImplTest.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform.ws;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.sonar.server.health.DbConnectionNodeCheck;
+import org.sonar.server.health.Health;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SafeModeLivenessCheckerImplTest {
+
+ public static final Health RED = Health.newHealthCheckBuilder().setStatus(Health.Status.RED).build();
+ private final DbConnectionNodeCheck dbConnectionNodeCheck = mock(DbConnectionNodeCheck.class);
+ private final SafeModeLivenessCheckerImpl underTest = new SafeModeLivenessCheckerImpl(dbConnectionNodeCheck);
+
+ @Test
+ public void fail_when_db_connexion_check_fail() {
+ when(dbConnectionNodeCheck.check()).thenReturn(RED);
+
+ Assertions.assertThat(underTest.liveness()).isFalse();
+ }
+
+ @Test
+ public void succeed_when_db_connexion_check_success() {
+ when(dbConnectionNodeCheck.check()).thenReturn(Health.GREEN);
+
+ Assertions.assertThat(underTest.liveness()).isTrue();
+ }
+
+}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafemodeSystemWsModuleTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafemodeSystemWsModuleTest.java
index fbecd406af4..c0f5884f7d4 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafemodeSystemWsModuleTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SafemodeSystemWsModuleTest.java
@@ -30,7 +30,7 @@ public class SafemodeSystemWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new SafemodeSystemWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 6);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 9);
}
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SystemWsModuleTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SystemWsModuleTest.java
index 6452b7cb752..4914f0c1782 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SystemWsModuleTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/platform/ws/SystemWsModuleTest.java
@@ -30,7 +30,7 @@ public class SystemWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new SystemWsModule().configure(container);
- assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 12);
+ assertThat(container.size()).isEqualTo(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER + 15);
}