]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-20075 Remove null chars from provider command output
authorEric Giffon <eric.giffon@sonarsource.com>
Wed, 2 Aug 2023 15:18:30 +0000 (17:18 +0200)
committersonartech <sonartech@sonarsource.com>
Fri, 4 Aug 2023 20:04:15 +0000 (20:04 +0000)
server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/CloudUsageDataProvider.java
server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/CloudUsageDataProviderTest.java

index dd10f981ab5de4c4f4bc9cc964fbdbfe729a093f..49b390ba4e52fe601900c3333d2b5de0a40f4f58 100644 (file)
@@ -32,7 +32,9 @@ import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
 import java.util.Collection;
 import java.util.Scanner;
+import java.util.function.Supplier;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import javax.inject.Inject;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
@@ -65,27 +67,29 @@ public class CloudUsageDataProvider {
   static final String SONAR_HELM_CHART_VERSION = "SONAR_HELM_CHART_VERSION";
   static final String DOCKER_RUNNING = "DOCKER_RUNNING";
   private static final String[] KUBERNETES_PROVIDER_COMMAND = {"bash", "-c", "uname -r"};
+  private static final int KUBERNETES_PROVIDER_MAX_SIZE = 100;
   private final ContainerSupport containerSupport;
   private final System2 system2;
   private final Paths2 paths2;
+  private final Supplier<ProcessBuilder> processBuilderSupplier;
   private OkHttpClient httpClient;
   private TelemetryData.CloudUsage cloudUsageData;
 
   @Inject
   public CloudUsageDataProvider(ContainerSupport containerSupport, System2 system2, Paths2 paths2) {
-    this.containerSupport = containerSupport;
-    this.system2 = system2;
-    this.paths2 = paths2;
+    this(containerSupport, system2, paths2, ProcessBuilder::new, null);
     if (isOnKubernetes()) {
       initHttpClient();
     }
   }
 
   @VisibleForTesting
-  CloudUsageDataProvider(ContainerSupport containerSupport, System2 system2, Paths2 paths2, OkHttpClient httpClient) {
+  CloudUsageDataProvider(ContainerSupport containerSupport, System2 system2, Paths2 paths2, Supplier<ProcessBuilder> processBuilderSupplier,
+                         @Nullable OkHttpClient httpClient) {
     this.containerSupport = containerSupport;
     this.system2 = system2;
     this.paths2 = paths2;
+    this.processBuilderSupplier = processBuilderSupplier;
     this.httpClient = httpClient;
   }
 
@@ -208,12 +212,14 @@ public class CloudUsageDataProvider {
   }
 
   @CheckForNull
-  private static String getKubernetesProvider() {
+  private String getKubernetesProvider() {
     try {
-      Process process = new ProcessBuilder().command(KUBERNETES_PROVIDER_COMMAND).start();
+      Process process = processBuilderSupplier.get().command(KUBERNETES_PROVIDER_COMMAND).start();
       try (Scanner scanner = new Scanner(process.getInputStream(), UTF_8)) {
         scanner.useDelimiter("\n");
-        return scanner.next();
+        // Null characters can be present in the output on Windows
+        String output = scanner.next().replace("\u0000", "");
+        return StringUtils.abbreviate(output, KUBERNETES_PROVIDER_MAX_SIZE);
       } finally {
         process.destroy();
       }
index 823848ed9e7890eed2b42358830571e753c82071..f7a22cdab582470a5d8b3e8841a968aa32e9e115 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.telemetry;
 
+import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.nio.file.Paths;
@@ -55,7 +56,9 @@ public class CloudUsageDataProviderTest {
   private final Paths2 paths2 = Mockito.mock(Paths2.class);
   private final OkHttpClient httpClient = Mockito.mock(OkHttpClient.class);
   private final ContainerSupport containerSupport = mock(ContainerSupport.class);
-  private final CloudUsageDataProvider underTest = new CloudUsageDataProvider(containerSupport, system2, paths2, httpClient);
+  private final ProcessBuilder processBuilder = mock(ProcessBuilder.class);
+  private final CloudUsageDataProvider underTest = new CloudUsageDataProvider(containerSupport, system2, paths2, () -> processBuilder,
+    httpClient);
 
   @Before
   public void setUp() throws Exception {
@@ -147,8 +150,23 @@ public class CloudUsageDataProviderTest {
   }
 
   @Test
-  public void kubernetesProvider_shouldReturnValue() {
-    assertThat(underTest.getCloudUsage().kubernetesProvider()).isNotBlank();
+  public void kubernetesProvider_shouldReturnValue() throws IOException {
+    Process processMock = mock(Process.class);
+    when(processMock.getInputStream()).thenReturn(new ByteArrayInputStream("some-provider".getBytes()));
+    when(processBuilder.command(any(String[].class))).thenReturn(processBuilder);
+    when(processBuilder.start()).thenReturn(processMock);
+
+    assertThat(underTest.getCloudUsage().kubernetesProvider()).isEqualTo("some-provider");
+  }
+
+  @Test
+  public void kubernetesProvider_whenValueContainsNullChars_shouldReturnValueWithoutNullChars() throws IOException {
+    Process processMock = mock(Process.class);
+    when(processMock.getInputStream()).thenReturn(new ByteArrayInputStream("so\u0000me-prov\u0000ider".getBytes()));
+    when(processBuilder.command(any(String[].class))).thenReturn(processBuilder);
+    when(processBuilder.start()).thenReturn(processMock);
+
+    assertThat(underTest.getCloudUsage().kubernetesProvider()).isEqualTo("some-provider");
   }
 
   @Test