]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-9802 fail restarting attempts on cluster nodes
authorDaniel Schwarz <daniel.schwarz@sonarsource.com>
Mon, 18 Sep 2017 08:48:23 +0000 (10:48 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 26 Sep 2017 21:49:37 +0000 (23:49 +0200)
server/sonar-server/src/main/java/org/sonar/server/platform/ws/RestartAction.java
server/sonar-server/src/test/java/org/sonar/server/platform/ws/RestartActionTest.java
server/sonar-server/src/test/java/org/sonar/server/platform/ws/SystemWsTest.java
tests/src/test/java/org/sonarqube/tests/cluster/ClusterTest.java

index 3a5160d573ac66ccb2782997ccbe567596e386e2..00d5aaebdc0482060e33e454af375d301f9aeb62 100644 (file)
@@ -28,6 +28,7 @@ import org.sonar.api.utils.log.Loggers;
 import org.sonar.server.app.ProcessCommandWrapper;
 import org.sonar.server.app.RestartFlagHolder;
 import org.sonar.server.platform.Platform;
+import org.sonar.server.platform.WebServer;
 import org.sonar.server.user.UserSession;
 
 /**
@@ -42,13 +43,16 @@ public class RestartAction implements SystemWsAction {
   private final Platform platform;
   private final ProcessCommandWrapper processCommandWrapper;
   private final RestartFlagHolder restartFlagHolder;
+  private final WebServer webServer;
 
-  public RestartAction(UserSession userSession, Configuration config, Platform platform, ProcessCommandWrapper processCommandWrapper, RestartFlagHolder restartFlagHolder) {
+  public RestartAction(UserSession userSession, Configuration config, Platform platform, ProcessCommandWrapper processCommandWrapper, RestartFlagHolder restartFlagHolder,
+      WebServer webServer) {
     this.userSession = userSession;
     this.config = config;
     this.platform = platform;
     this.processCommandWrapper = processCommandWrapper;
     this.restartFlagHolder = restartFlagHolder;
+    this.webServer = webServer;
   }
 
   @Override
@@ -62,6 +66,9 @@ public class RestartAction implements SystemWsAction {
 
   @Override
   public void handle(Request request, Response response) {
+    if (!webServer.isStandalone()) {
+      throw new IllegalArgumentException("Restart not allowed for cluster nodes");
+    }
     if (config.getBoolean("sonar.web.dev").orElse(false)) {
       LOGGER.info("Fast restarting WebServer...");
       restartFlagHolder.set();
index 87195c8d5c6e0778cb571c2aad75a71e77e5d23e..059e2e0e0646567f66a9d5ef6f3a14e6ad762036 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.server.app.ProcessCommandWrapper;
 import org.sonar.server.app.RestartFlagHolder;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.platform.Platform;
+import org.sonar.server.platform.WebServer;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.WsActionTester;
 import org.sonar.server.ws.WsTester;
@@ -38,6 +39,7 @@ import org.sonar.server.ws.WsTester;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class RestartActionTest {
   @Rule
@@ -51,13 +53,15 @@ public class RestartActionTest {
   private Platform platform = mock(Platform.class);
   private ProcessCommandWrapper processCommandWrapper = mock(ProcessCommandWrapper.class);
   private RestartFlagHolder restartFlagHolder = mock(RestartFlagHolder.class);
-  private RestartAction sut = new RestartAction(userSessionRule, settings.asConfig(), platform, processCommandWrapper, restartFlagHolder);
+  private WebServer webServer = mock(WebServer.class);
+  private RestartAction sut = new RestartAction(userSessionRule, settings.asConfig(), platform, processCommandWrapper, restartFlagHolder, webServer);
   private InOrder inOrder = Mockito.inOrder(platform, restartFlagHolder, processCommandWrapper);
 
   private WsActionTester actionTester = new WsActionTester(sut);
 
   @Test
   public void restart_if_dev_mode() throws Exception {
+    when(webServer.isStandalone()).thenReturn(true);
     settings.setProperty("sonar.web.dev", true);
 
     SystemWs ws = new SystemWs(sut);
@@ -72,6 +76,7 @@ public class RestartActionTest {
 
   @Test
   public void restart_flag_is_unset_in_dev_mode_even_if_restart_fails() throws Exception {
+    when(webServer.isStandalone()).thenReturn(true);
     settings.setProperty("sonar.web.dev", true);
     RuntimeException toBeThrown = new RuntimeException("simulating platform.restart() failed");
     doThrow(toBeThrown).when(platform).restart();
@@ -92,6 +97,7 @@ public class RestartActionTest {
 
   @Test
   public void request_fails_in_production_mode_with_ForbiddenException_when_user_is_not_logged_in() {
+    when(webServer.isStandalone()).thenReturn(true);
     expectedException.expect(ForbiddenException.class);
 
     actionTester.newRequest().execute();
@@ -99,6 +105,7 @@ public class RestartActionTest {
 
   @Test
   public void request_fails_in_production_mode_with_ForbiddenException_when_user_is_not_system_administrator() {
+    when(webServer.isStandalone()).thenReturn(true);
     userSessionRule.logIn().setNonSystemAdministrator();
 
     expectedException.expect(ForbiddenException.class);
@@ -106,8 +113,19 @@ public class RestartActionTest {
     actionTester.newRequest().execute();
   }
 
+  @Test
+  public void request_fails_in_cluster_mode_with_IllegalArgumentException() {
+    when(webServer.isStandalone()).thenReturn(false);
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Restart not allowed for cluster nodes");
+
+    actionTester.newRequest().execute();
+  }
+
   @Test
   public void calls_ProcessCommandWrapper_requestForSQRestart_in_production_mode() throws Exception {
+    when(webServer.isStandalone()).thenReturn(true);
     userSessionRule.logIn().setSystemAdministrator();
 
     actionTester.newRequest().execute();
@@ -118,6 +136,7 @@ public class RestartActionTest {
 
   @Test
   public void logs_login_of_authenticated_user_requesting_the_restart_in_production_mode() throws Exception {
+    when(webServer.isStandalone()).thenReturn(true);
     String login = "BigBother";
     userSessionRule.logIn(login).setSystemAdministrator();
 
index 334902594670dbed70b6722d8325d9d3cfaa5d38..593619663da896f07a5c0c45208342bb90832180 100644 (file)
@@ -27,6 +27,7 @@ import org.sonar.ce.http.CeHttpClientImpl;
 import org.sonar.server.app.ProcessCommandWrapper;
 import org.sonar.server.app.RestartFlagHolder;
 import org.sonar.server.platform.Platform;
+import org.sonar.server.platform.WebServer;
 import org.sonar.server.telemetry.TelemetryDataLoader;
 import org.sonar.server.tester.AnonymousMockUserSession;
 import org.sonar.server.user.UserSession;
@@ -41,7 +42,7 @@ public class SystemWsTest {
   @Test
   public void define() {
     RestartAction action1 = new RestartAction(mock(UserSession.class), mock(Configuration.class), mock(Platform.class), mock(ProcessCommandWrapper.class),
-      mock(RestartFlagHolder.class));
+      mock(RestartFlagHolder.class), mock(WebServer.class));
     InfoAction action2 = new InfoAction(new AnonymousMockUserSession(), ceHttpClient, mock(TelemetryDataLoader.class));
     SystemWs ws = new SystemWs(action1, action2);
     WebService.Context context = new WebService.Context();
index 5bf9ac21c7bc48845e3ce5c26881369bf85ebe9d..615c077fd957284cd1d78c07a29a42cd9b4d10a9 100644 (file)
@@ -39,6 +39,7 @@ import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 import org.sonarqube.ws.WsSystem;
 import org.sonarqube.ws.client.GetRequest;
+import org.sonarqube.ws.client.HttpException;
 
 import static com.google.common.base.Preconditions.checkState;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -263,6 +264,25 @@ public class ClusterTest {
     }
   }
 
+  @Test
+  public void restart_action_is_not_allowed_for_cluster_nodes() throws Exception {
+    try (Cluster cluster = newCluster(2, 1)) {
+      cluster.getNodes().forEach(Node::start);
+      cluster.getAppNodes().forEach(Node::waitForStatusUp);
+
+      cluster.getAppNodes().forEach(node -> {
+        try {
+          node.wsClient().system().restart();
+          fail("The restart webservice must not succeed on cluster nodes");
+        } catch (HttpException e) {
+          // all good, we expected this!
+          assertThat(e.code()).isEqualTo(400);
+          assertThat(e.content()).contains("Restart not allowed for cluster nodes");
+        }
+      });
+    }
+  }
+
   @Test
   public void health_becomes_RED_when_all_search_nodes_go_down() throws Exception {
     try (Cluster cluster = newCluster(2, 1)) {