From b0e5888c6a32be0873d355756b3e20e497c95a9c Mon Sep 17 00:00:00 2001 From: Eric Giffon Date: Tue, 25 Jul 2023 18:07:17 +0200 Subject: [PATCH] SONAR-19994 Scanner property for plugins download timeout --- .../sonar/scanner/bootstrap/PluginFiles.java | 10 ++++++++-- .../scanner/bootstrap/PluginFilesTest.java | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java index adc0c01247f..eb1551d8b3b 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/PluginFiles.java @@ -19,6 +19,7 @@ */ package org.sonar.scanner.bootstrap; +import com.google.common.annotations.VisibleForTesting; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; @@ -30,9 +31,9 @@ import java.util.Optional; import java.util.stream.Stream; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; -import org.sonar.api.config.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.sonar.api.config.Configuration; import org.sonar.scanner.bootstrap.ScannerPluginInstaller.InstalledPlugin; import org.sonarqube.ws.client.GetRequest; import org.sonarqube.ws.client.HttpException; @@ -44,13 +45,18 @@ public class PluginFiles { private static final Logger LOGGER = LoggerFactory.getLogger(PluginFiles.class); private static final String MD5_HEADER = "Sonar-MD5"; + @VisibleForTesting + static final String PLUGINS_DOWNLOAD_TIMEOUT_PROPERTY = "sonar.plugins.download.timeout"; + private static final int PLUGINS_DOWNLOAD_TIMEOUT_DEFAULT = 300; private final DefaultScannerWsClient wsClient; + private final Configuration configuration; private final File cacheDir; private final File tempDir; public PluginFiles(DefaultScannerWsClient wsClient, Configuration configuration) { this.wsClient = wsClient; + this.configuration = configuration; File home = locateHomeDir(configuration); this.cacheDir = mkdir(new File(home, "cache"), "user cache"); this.tempDir = mkdir(new File(home, "_tmp"), "temp dir"); @@ -85,7 +91,7 @@ public class PluginFiles { private Optional download(InstalledPlugin plugin) { GetRequest request = new GetRequest("api/plugins/download") .setParam("plugin", plugin.key) - .setTimeOutInMs(5 * 60_000); + .setTimeOutInMs(configuration.getInt(PLUGINS_DOWNLOAD_TIMEOUT_PROPERTY).orElse(PLUGINS_DOWNLOAD_TIMEOUT_DEFAULT) * 1000); File downloadedFile = newTempFile(); LOGGER.debug("Download plugin '{}' to '{}'", plugin.key, downloadedFile); diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java index e072875e19d..6ac3838aafa 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/bootstrap/PluginFilesTest.java @@ -22,8 +22,10 @@ package org.sonar.scanner.bootstrap; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.SocketTimeoutException; import java.util.Collections; import java.util.Optional; +import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; import okhttp3.HttpUrl; import okhttp3.mockwebserver.MockResponse; @@ -47,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.ThrowableAssert.ThrowingCallable; import static org.mockito.Mockito.mock; +import static org.sonar.scanner.bootstrap.PluginFiles.PLUGINS_DOWNLOAD_TIMEOUT_PROPERTY; public class PluginFilesTest { @@ -70,6 +73,7 @@ public class PluginFilesTest { userHome = temp.newFolder(); MapSettings settings = new MapSettings(); settings.setProperty("sonar.userHome", userHome.getAbsolutePath()); + settings.setProperty(PLUGINS_DOWNLOAD_TIMEOUT_PROPERTY, 1); underTest = new PluginFiles(wsClient, settings.asConfig()); } @@ -141,6 +145,19 @@ public class PluginFilesTest { expectISE("foo", "returned code 500", () -> underTest.get(plugin)); } + @Test + public void getPlugin_whenTimeOutReached_thenDownloadFails() { + MockResponse response = new MockResponse().setBody("test").setBodyDelay(2, TimeUnit.SECONDS); + response.setHeader("Sonar-MD5", "md5"); + server.enqueue(response); + InstalledPlugin plugin = newInstalledPlugin("foo", "abc"); + + assertThatThrownBy(() -> underTest.get(plugin)) + .isInstanceOf(IllegalStateException.class) + .hasMessageStartingWith("Fail to download plugin [" + plugin.key + "]") + .cause().isInstanceOf(SocketTimeoutException.class); + } + @Test public void download_a_new_version_of_plugin_during_blue_green_switch() throws IOException { FileAndMd5 tempJar = new FileAndMd5(); -- 2.39.5