From: Julien HENRY Date: Thu, 1 Oct 2015 15:31:10 +0000 (+0200) Subject: SONAR-6888 Support "views" task X-Git-Tag: 5.2-RC1~131 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cf74684017240262742beb84b3fd94db560ae92c;p=sonarqube.git SONAR-6888 Support "views" task --- diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java index ebcc795c9e5..3516932cd50 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java @@ -19,13 +19,20 @@ */ package org.sonar.batch.bootstrap; +import com.github.kevinsawicki.http.HttpRequest; +import java.net.MalformedURLException; +import java.net.URL; import java.util.List; import java.util.Map; import javax.annotation.CheckForNull; +import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; import org.sonar.api.SonarPlugin; +import org.sonar.api.platform.Server; +import org.sonar.api.utils.MessageException; import org.sonar.api.utils.System2; import org.sonar.api.utils.UriReader; +import org.sonar.api.utils.log.Loggers; import org.sonar.batch.analysis.AnalysisProperties; import org.sonar.batch.analysis.DefaultAnalysisMode; import org.sonar.batch.cache.GlobalPersistentCacheProvider; @@ -49,8 +56,12 @@ import org.sonar.core.platform.PluginRepository; import org.sonar.core.util.DefaultHttpDownloader; import org.sonar.core.util.UuidFactoryImpl; +import static java.lang.String.format; + public class GlobalContainer extends ComponentContainer { + private static final org.sonar.api.utils.log.Logger LOG = Loggers.get(GlobalContainer.class); + private final Map bootstrapProperties; private boolean preferCache; @@ -128,7 +139,18 @@ public class GlobalContainer extends ComponentContainer { } public void executeAnalysis(Map analysisProperties, Object... components) { - AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); + GlobalProperties globalProperties = this.getComponentByType(GlobalProperties.class); + // SONAR-6888 + String task = analysisProperties.get(CoreProperties.TASK); + if ("views".equals(task)) { + triggerViews(this.getComponentByType(ServerClient.class), this.getComponentByType(Server.class)); + return; + } + if (StringUtils.isNotBlank(task) && !CoreProperties.SCAN_TASK.equals(task)) { + throw MessageException.of("Tasks are no more supported on batch side since SonarQube 5.2"); + } + + AnalysisProperties props = new AnalysisProperties(analysisProperties, globalProperties.property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); if (isIssuesMode(props)) { String projectKey = getProjectKeyWithBranch(props); new ProjectSyncContainer(this, projectKey, false).execute(); @@ -136,6 +158,35 @@ public class GlobalContainer extends ComponentContainer { new ProjectScanContainer(this, props, components).execute(); } + private static void triggerViews(ServerClient serverClient, Server server) { + LOG.info("Trigger Views update"); + URL url; + try { + url = new URL(serverClient.getURL() + "/api/views/run"); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Invalid URL", e); + } + HttpRequest request = HttpRequest.post(url); + request.trustAllCerts(); + request.trustAllHosts(); + request.header("User-Agent", format("SonarQube %s", server.getVersion())); + request.basic(serverClient.getLogin(), serverClient.getPassword()); + if (!request.ok()) { + int responseCode = request.code(); + if (responseCode == 401) { + throw new IllegalStateException(format(serverClient.getMessageWhenNotAuthorized(), CoreProperties.LOGIN, CoreProperties.PASSWORD)); + } + if (responseCode == 409) { + throw new IllegalStateException("A full refresh of Views is already queued or running"); + } + if (responseCode == 403) { + // SONAR-4397 Details are in response content + throw new IllegalStateException(request.body()); + } + throw new IllegalStateException(format("Fail to execute request [code=%s, url=%s]: %s", responseCode, url, request.body())); + } + } + @CheckForNull private static String getProjectKeyWithBranch(AnalysisProperties props) { String projectKey = props.property(CoreProperties.PROJECT_KEY_PROPERTY); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java index 757e3536717..a8c3750bc1b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/MockHttpServer.java @@ -19,18 +19,18 @@ */ package org.sonar.batch.bootstrap; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.AbstractHandler; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import java.io.IOException; - import static javax.servlet.http.HttpServletResponse.SC_OK; import static org.apache.commons.io.IOUtils.write; @@ -40,7 +40,7 @@ public class MockHttpServer { private String requestBody; private String mockResponseData; private int mockResponseStatus = SC_OK; - private int numRequests = 0; + private List targets = new ArrayList<>(); public void start() throws Exception { server = new Server(0); @@ -49,7 +49,7 @@ public class MockHttpServer { } public int getNumberRequests() { - return numRequests; + return targets.size(); } /** @@ -61,7 +61,7 @@ public class MockHttpServer { Handler handler = new AbstractHandler() { public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { - numRequests++; + targets.add(target); setResponseBody(getMockResponseData()); setRequestBody(IOUtils.toString(baseRequest.getInputStream())); response.setStatus(mockResponseStatus); diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/tasks/TasksMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/tasks/TasksMediumTest.java new file mode 100644 index 00000000000..a4acf3ab613 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/tasks/TasksMediumTest.java @@ -0,0 +1,97 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.batch.mediumtest.tasks; + +import com.google.common.collect.ImmutableMap; +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.MessageException; +import org.sonar.api.utils.log.LogTester; +import org.sonar.batch.bootstrap.MockHttpServer; +import org.sonar.batch.mediumtest.BatchMediumTester; + +import static org.assertj.core.api.Assertions.assertThat; + +public class TasksMediumTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public LogTester logTester = new LogTester(); + + public BatchMediumTester tester = BatchMediumTester.builder() + .build(); + + private MockHttpServer server = null; + + @After + public void stopServer() { + if (server != null) { + server.stop(); + } + } + + @After + public void stop() { + tester.stop(); + } + + @Test + public void triggerViews() throws Exception { + startServer(200, "OK"); + tester = BatchMediumTester.builder() + .bootstrapProperties(ImmutableMap.of("sonar.host.url", "http://localhost:" + server.getPort())) + .build(); + tester.start(); + tester.newTask() + .properties(ImmutableMap.builder() + .put("sonar.task", "views").build()) + .start(); + + assertThat(logTester.logs()).contains("Trigger views update"); + } + + @Test(expected = MessageException.class) + public void unsupportedTask() throws Exception { + tester = BatchMediumTester.builder() + .build(); + tester.start(); + tester.newTask() + .properties(ImmutableMap.builder() + .put("sonar.task", "foo").build()) + .start(); + } + + private void startServer(Integer responseStatus, String responseData) throws Exception { + server = new MockHttpServer(); + server.start(); + + if (responseStatus != null) { + server.setMockResponseStatus(responseStatus); + } + if (responseData != null) { + server.setMockResponseData(responseData); + } + } + +}