]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-19425 Update logic for SQ container context
authorAlain Kermis <alain.kermis@sonarsource.com>
Thu, 8 Jun 2023 14:37:41 +0000 (16:37 +0200)
committersonartech <sonartech@sonarsource.com>
Tue, 13 Jun 2023 20:03:39 +0000 (20:03 +0000)
server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryData.java
server/sonar-server-common/src/main/java/org/sonar/server/telemetry/TelemetryDataJsonWriter.java
server/sonar-server-common/src/test/java/org/sonar/server/telemetry/TelemetryDataJsonWriterTest.java
server/sonar-webserver-core/src/main/java/org/sonar/server/platform/ContainerSupport.java
server/sonar-webserver-core/src/main/java/org/sonar/server/platform/ContainerSupportImpl.java
server/sonar-webserver-core/src/main/java/org/sonar/server/telemetry/CloudUsageDataProvider.java
server/sonar-webserver-core/src/test/java/org/sonar/server/platform/ContainerSupportImplTest.java
server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/CloudUsageDataProviderTest.java
server/sonar-webserver-core/src/test/java/org/sonar/server/telemetry/TelemetryDataLoaderImplTest.java

index c4938050f15352a1f807f56fb4991467e8663c6a..9531cb16006e14573dc36546ca9586bd21dbd62f 100644 (file)
@@ -352,8 +352,8 @@ public class TelemetryData {
   record ManagedInstanceInformation(boolean isManaged, @Nullable String provider) {
   }
 
-  record CloudUsage(boolean kubernetes, @Nullable String kubernetesVersion, @Nullable String kubernetesPlatform,
-                    @Nullable String kubernetesProvider, @Nullable String officialHelmChart, boolean officialImage) {
+  record CloudUsage(boolean kubernetes, @Nullable String kubernetesVersion, @Nullable String kubernetesPlatform, @Nullable String kubernetesProvider,
+                    @Nullable String officialHelmChart, @Nullable String containerRuntime, boolean officialImage) {
   }
 
   public static class ProjectStatistics {
index f28b8cdbb2200bc6073f897451218cef30ccd5d6..d78d10f114bda87886be70c60609b5300fa7b4d2 100644 (file)
@@ -240,6 +240,7 @@ public class TelemetryDataJsonWriter {
     json.prop("kubernetesPlatform", cloudUsage.kubernetesPlatform());
     json.prop("kubernetesProvider", cloudUsage.kubernetesProvider());
     json.prop("officialHelmChart", cloudUsage.officialHelmChart());
+    json.prop("containerRuntime", cloudUsage.containerRuntime());
     json.prop("officialImage", cloudUsage.officialImage());
     json.endObject();
   }
index 27d803053d15ce45af3637d39207c5ae7455d674..665ce7896f4085d2f8dfc15300852c6bfb3d808e 100644 (file)
@@ -292,7 +292,8 @@ public class TelemetryDataJsonWriterTest {
           "kubernetesPlatform": "linux/amd64",
           "kubernetesProvider": "5.4.181-99.354.amzn2.x86_64",
           "officialHelmChart": "10.1.0",
-          "officialImage": false
+          "officialImage": false,
+          "containerRuntime": "docker"
         }
       }
       """);
@@ -604,7 +605,7 @@ public class TelemetryDataJsonWriterTest {
       .setMessageSequenceNumber(1L)
       .setPlugins(Collections.emptyMap())
       .setManagedInstanceInformation(new TelemetryData.ManagedInstanceInformation(false, null))
-      .setCloudUsage(new TelemetryData.CloudUsage(true, "1.27", "linux/amd64", "5.4.181-99.354.amzn2.x86_64", "10.1.0", false))
+      .setCloudUsage(new TelemetryData.CloudUsage(true, "1.27", "linux/amd64", "5.4.181-99.354.amzn2.x86_64", "10.1.0", "docker", false))
       .setDatabase(new TelemetryData.Database("H2", "11"))
       .setNcdId(NCD_ID);
   }
index 22a59f5207f3fd23c6ecbb70e92d1b20e1e26ec3..30c18a19b2b572e6eac2bc26a0d4ad5cc4759358 100644 (file)
  */
 package org.sonar.server.platform;
 
+import javax.annotation.CheckForNull;
+
 public interface ContainerSupport {
   /**
    * @return {@code true} if we can detect that SQ is running inside a docker container
    */
   boolean isRunningInContainer();
 
+  @CheckForNull
+  String getContainerContext();
+
 }
index 38997c558f5b09b634001402b935a2ce7ac6ace2..e6d81ac1a9bb0e9287d4369039d5b3874f9ee381 100644 (file)
  */
 package org.sonar.server.platform;
 
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.stream.Stream;
+import com.google.common.annotations.VisibleForTesting;
+import java.util.Objects;
+import java.util.Scanner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.System2;
 import org.sonar.server.util.Paths2;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 public class ContainerSupportImpl implements ContainerSupport {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ContainerSupportImpl.class);
+  private static final String CONTAINER_FILE_PATH = "/run/.containerenv";
+  private static final String DOCKER = "docker";
+  private static final String PODMAN = "podman";
+  private static final String BUILDAH = "buildah";
+  private static final String CONTAINER_D = "containerd";
+  private static final String GENERAL_CONTAINER = "general_container";
+
+  private static final String[] MOUNT_GREP_COMMAND = {"bash", "-c", "mount | grep 'overlay on /'"};
+  private static final String[] CAT_COMMAND = {"bash", "-c", "cat /run/.containerenv"};
+
+  private final System2 system2;
   private final Paths2 paths2;
+  private String containerContextCache;
 
-  public ContainerSupportImpl(Paths2 paths2) {
+  public ContainerSupportImpl(Paths2 paths2, System2 system2) {
     this.paths2 = paths2;
+    this.system2 = system2;
+
+    populateCache();
+  }
+
+  @VisibleForTesting
+  void populateCache() {
+    if (isDocker()) {
+      containerContextCache = DOCKER;
+    } else if (isPodman()) {
+      containerContextCache = PODMAN;
+    } else if (isBuildah()) {
+      containerContextCache = BUILDAH;
+    } else if (isContainerd()) {
+      containerContextCache = CONTAINER_D;
+    } else if (isGeneralContainer()) {
+      containerContextCache = GENERAL_CONTAINER;
+    } else {
+      containerContextCache = null;
+    }
   }
 
   @Override
   public boolean isRunningInContainer() {
-    if (paths2.exists("/run/.containerenv")) {
-      return true;
-    }
-    try (Stream<String> stream = Files.lines(paths2.get("/proc/1/cgroup"))) {
-      return stream.anyMatch(line -> line.contains("/docker") || line.contains("/kubepods") || line.contains("containerd.service") );
-    } catch (IOException e) {
-      return false;
+    return containerContextCache != null;
+  }
+
+  @Override
+  public String getContainerContext() {
+    return containerContextCache;
+  }
+
+  private boolean isDocker() {
+    return executeCommand(MOUNT_GREP_COMMAND).contains("/docker") && paths2.exists("/.dockerenv");
+  }
+
+  private boolean isPodman() {
+    return Objects.equals(system2.envVariable("container"), PODMAN) && paths2.exists(CONTAINER_FILE_PATH);
+  }
+
+  private boolean isBuildah() {
+    return paths2.exists(CONTAINER_FILE_PATH) && executeCommand(CAT_COMMAND).contains("engine=\"buildah-");
+  }
+
+  private boolean isContainerd() {
+    return executeCommand(MOUNT_GREP_COMMAND).contains("/containerd");
+  }
+
+  private boolean isGeneralContainer() {
+    return paths2.exists(CONTAINER_FILE_PATH);
+  }
+
+  @VisibleForTesting
+  String executeCommand(String[] command) {
+    try {
+      Process process = new ProcessBuilder().command(command).start();
+      try (Scanner scanner = new Scanner(process.getInputStream(), UTF_8)) {
+        scanner.useDelimiter("\n");
+        return scanner.next();
+      } finally {
+        process.destroy();
+      }
+    } catch (Exception e) {
+      LOG.debug("Failed to execute command", e);
+      return "";
     }
   }
 }
index f35f1f026f285841ad765b24c02eecf6a2bb9349..dd10f981ab5de4c4f4bc9cc964fbdbfe729a093f 100644 (file)
@@ -48,6 +48,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.System2;
+import org.sonar.server.platform.ContainerSupport;
 import org.sonar.server.util.Paths2;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
@@ -64,13 +65,15 @@ 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 final ContainerSupport containerSupport;
   private final System2 system2;
   private final Paths2 paths2;
   private OkHttpClient httpClient;
   private TelemetryData.CloudUsage cloudUsageData;
 
   @Inject
-  public CloudUsageDataProvider(System2 system2, Paths2 paths2) {
+  public CloudUsageDataProvider(ContainerSupport containerSupport, System2 system2, Paths2 paths2) {
+    this.containerSupport = containerSupport;
     this.system2 = system2;
     this.paths2 = paths2;
     if (isOnKubernetes()) {
@@ -79,7 +82,8 @@ public class CloudUsageDataProvider {
   }
 
   @VisibleForTesting
-  CloudUsageDataProvider(System2 system2, Paths2 paths2, OkHttpClient httpClient) {
+  CloudUsageDataProvider(ContainerSupport containerSupport, System2 system2, Paths2 paths2, OkHttpClient httpClient) {
+    this.containerSupport = containerSupport;
     this.system2 = system2;
     this.paths2 = paths2;
     this.httpClient = httpClient;
@@ -107,6 +111,7 @@ public class CloudUsageDataProvider {
       kubernetesPlatform,
       getKubernetesProvider(),
       getOfficialHelmChartVersion(),
+      containerSupport.getContainerContext(),
       isOfficialImageUsed());
 
     return cloudUsageData;
index 7b3188a21714b7ccf52c7effc82648d224201807..56b3406846bde14996cad17c38cea59584c77023 100644 (file)
  */
 package org.sonar.server.platform;
 
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.apache.commons.io.FileUtils;
-import org.junit.Rule;
+import java.util.Arrays;
+import java.util.Collection;
+import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.sonar.api.utils.System2;
 import org.sonar.server.util.Paths2;
 
-import static java.lang.System.lineSeparator;
-import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
+@RunWith(Parameterized.class)
 public class ContainerSupportImplTest {
-  private static final String CGROUP_DIR = "/proc/1/cgroup";
-  private static final String PODMAN_FILE_PATH = "/run/.containerenv";
-
-  @Rule
-  public TemporaryFolder temporaryFolder = new TemporaryFolder();
-
-  private Paths2 paths2 = mock(Paths2.class);
-  private ContainerSupportImpl underTest = new ContainerSupportImpl(paths2);
-
-  @Test
-  public void isInDocker_returns_false_if_cgroup_file_does_not_exist() throws IOException {
-    Path emptyFile = temporaryFolder.newFile().toPath();
-    Files.delete(emptyFile);
-    when(paths2.get(CGROUP_DIR)).thenReturn(emptyFile);
-
-    assertThat(underTest.isRunningInContainer()).isFalse();
+  private static final String CONTAINER_FILE_PATH = "/run/.containerenv";
+  private static final String[] MOUNT_GREP_COMMAND = {"bash", "-c", "mount | grep 'overlay on /'"};
+  private static final String[] CAT_COMMAND = {"bash", "-c", "cat /run/.containerenv"};
+  private static final String DOCKER = "docker";
+  private static final String PODMAN = "podman";
+  private static final String BUILDAH = "buildah";
+  private static final String CONTAINER_D = "containerd";
+  private static final String GENERAL_CONTAINER = "general_container";
+
+  private final Paths2 paths2 = mock(Paths2.class);
+  private final System2 system2 = mock(System2.class);
+  private ContainerSupportImpl underTest = new ContainerSupportImpl(paths2, system2);
+
+  private String containerContext;
+
+  public ContainerSupportImplTest(String containerContext) {
+    this.containerContext = containerContext;
   }
 
-  @Test
-  public void isInDocker_returns_false_if_cgroup_file_is_empty() throws IOException {
-    Path emptyFile = temporaryFolder.newFile().toPath();
-    when(paths2.get(CGROUP_DIR)).thenReturn(emptyFile);
-
-    assertThat(underTest.isRunningInContainer()).isFalse();
-  }
-
-  @Test
-  public void isInDocker_returns_false_if_cgroup_dir_contains_no_file_with_slash_docker_string() throws IOException {
-    Path cgroupFile = temporaryFolder.newFile().toPath();
-    String content = "11:name=systemd:/" + lineSeparator() +
-      "10:hugetlb:/" + lineSeparator() +
-      "9:perf_event:/" + lineSeparator() +
-      "8:blkio:/" + lineSeparator() +
-      "7:freezer:/" + lineSeparator() +
-      "6:devices:/" + lineSeparator() +
-      "5:memory:/" + lineSeparator() +
-      "4:cpuacct:/" + lineSeparator() +
-      "3:cpu:/" + lineSeparator() +
-      "2:cpuset:/";
-    FileUtils.write(cgroupFile.toFile(), content, StandardCharsets.UTF_8);
-    when(paths2.get(CGROUP_DIR)).thenReturn(cgroupFile);
-
-    assertThat(underTest.isRunningInContainer()).isFalse();
+  @Before
+  public void setUp() {
+    if (containerContext == null) {
+      return;
+    }
+
+    switch (containerContext) {
+      case DOCKER -> {
+        underTest = spy(underTest);
+        when(underTest.executeCommand(MOUNT_GREP_COMMAND)).thenReturn("/docker");
+        when(paths2.exists("/.dockerenv")).thenReturn(true);
+      }
+      case PODMAN -> {
+        when(system2.envVariable("container")).thenReturn("podman");
+        when(paths2.exists(CONTAINER_FILE_PATH)).thenReturn(true);
+      }
+      case BUILDAH -> {
+        underTest = spy(underTest);
+        when(paths2.exists(CONTAINER_FILE_PATH)).thenReturn(true);
+        when(underTest.executeCommand(CAT_COMMAND)).thenReturn("XXX engine=\"buildah- XXX");
+      }
+      case CONTAINER_D -> {
+        underTest = spy(underTest);
+        when(underTest.executeCommand(MOUNT_GREP_COMMAND)).thenReturn("/containerd");
+      }
+      case GENERAL_CONTAINER -> when(paths2.exists(CONTAINER_FILE_PATH)).thenReturn(true);
+      default -> {
+      }
+    }
+    underTest.populateCache();
   }
 
-  @Test
-  public void isInDocker_returns_true_if_cgroup_dir_contains_file_with_slash_docker_string() throws IOException {
-    Path cgroupFile = temporaryFolder.newFile().toPath();
-    String content = "11:name=systemd:/" + lineSeparator() +
-      "10:hugetlb:/" + lineSeparator() +
-      "9:perf_event:/" + lineSeparator() +
-      "8:blkio:/" + lineSeparator() +
-      "7:freezer:/" + lineSeparator() +
-      "6:devices:/docker/3601745b3bd54d9780436faa5f0e4f72bb46231663bb99a6bb892764917832c2" + lineSeparator() +
-      "5:memory:/" + lineSeparator() +
-      "4:cpuacct:/" + lineSeparator() +
-      "3:cpu:/docker/3601745b3bd54d9780436faa5f0e4f72bb46231663bb99a6bb892764917832c2" + lineSeparator() +
-      "2:cpuset:/";
-    FileUtils.write(cgroupFile.toFile(), content, StandardCharsets.UTF_8);
-    when(paths2.get(CGROUP_DIR)).thenReturn(cgroupFile);
-
-    assertThat(underTest.isRunningInContainer()).isTrue();
-  }
-
-  @Test
-  public void isInDocker_returns_true_if_cgroup_dir_contains_file_with_kubepods_string() throws IOException {
-    Path cgroupFile = temporaryFolder.newFile().toPath();
-    String content = "11:blkio:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "10:cpuset:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "9:net_cls,net_prio:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "8:pids:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "7:perf_event:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "6:freezer:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "5:hugetlb:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "4:memory:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "3:devices:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "2:cpu,cpuacct:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366" + lineSeparator() +
-      "1:name=systemd:/kubepods/burstable/pod8e9a7fc0-4e11-4497-a424-19b9713eff0e/8953402928cc7fc95c7dc7bdb75b194139fe29e8fa196d7f90924deb29164366";
-    FileUtils.write(cgroupFile.toFile(), content, StandardCharsets.UTF_8);
-    when(paths2.get(CGROUP_DIR)).thenReturn(cgroupFile);
-
-    assertThat(underTest.isRunningInContainer()).isTrue();
-  }
-
-  @Test
-  public void isInDocker_returns_true_if_cgroup_dir_contains_file_with_containerd_string() throws IOException {
-    Path cgroupFile = temporaryFolder.newFile().toPath();
-    String content = "12:blkio:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "11:perf_event:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "10:hugetlb:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "9:pids:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "8:rdma:/" + lineSeparator() +
-      "7:memory:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "6:cpuset:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "5:net_cls,net_prio:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "4:freezer:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "3:cpu,cpuacct:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "2:devices:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "1:name=systemd:/default/846fe494c3021f068c9156ca6eb8a91038389b7e2a2b1ae9b050b33c3a5c9298" + lineSeparator() +
-      "0::/system.slice/containerd.service";
-    FileUtils.write(cgroupFile.toFile(), content, StandardCharsets.UTF_8);
-    when(paths2.get(CGROUP_DIR)).thenReturn(cgroupFile);
-
-    assertThat(underTest.isRunningInContainer()).isTrue();
+  @Parameterized.Parameters
+  public static Collection<String> data() {
+    return Arrays.asList(DOCKER, PODMAN, BUILDAH, CONTAINER_D, GENERAL_CONTAINER, null);
   }
 
   @Test
-  public void isInDocker_returns_true_if_podman_file_exists() throws IOException {
-    when(paths2.exists(PODMAN_FILE_PATH)).thenReturn(true);
-    assertThat(underTest.isRunningInContainer()).isTrue();
+  public void testGetContainerContext() {
+    Assert.assertEquals(containerContext, underTest.getContainerContext());
   }
 
   @Test
-  public void isInDocker_returns_false_if_podman_file_exists() throws IOException {
-    when(paths2.exists(PODMAN_FILE_PATH)).thenReturn(false);
-    Path emptyFile = temporaryFolder.newFile().toPath();
-    when(paths2.get(CGROUP_DIR)).thenReturn(emptyFile);
-    assertThat(underTest.isRunningInContainer()).isFalse();
+  public void testIsRunningInContainer() {
+    boolean expected = containerContext != null;
+    when(paths2.exists(CONTAINER_FILE_PATH)).thenReturn(expected);
+    Assert.assertEquals(expected, underTest.isRunningInContainer());
   }
 
 }
index ccefc0cae3c18414ab61635526fa5fa22234c70e..823848ed9e7890eed2b42358830571e753c82071 100644 (file)
@@ -34,6 +34,7 @@ import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.sonar.api.utils.System2;
+import org.sonar.server.platform.ContainerSupport;
 import org.sonar.server.util.Paths2;
 import org.sonarqube.ws.MediaTypes;
 
@@ -53,7 +54,8 @@ public class CloudUsageDataProviderTest {
   private final System2 system2 = Mockito.mock(System2.class);
   private final Paths2 paths2 = Mockito.mock(Paths2.class);
   private final OkHttpClient httpClient = Mockito.mock(OkHttpClient.class);
-  private final CloudUsageDataProvider underTest = new CloudUsageDataProvider(system2, paths2, httpClient);
+  private final ContainerSupport containerSupport = mock(ContainerSupport.class);
+  private final CloudUsageDataProvider underTest = new CloudUsageDataProvider(containerSupport, system2, paths2, httpClient);
 
   @Before
   public void setUp() throws Exception {
@@ -87,6 +89,18 @@ public class CloudUsageDataProviderTest {
     when(httpClient.newCall(any())).thenReturn(callMock);
   }
 
+  @Test
+  public void containerRuntime_whenContainerSupportContextExists_shouldNotBeNull() {
+    when(containerSupport.getContainerContext()).thenReturn("docker");
+    assertThat(underTest.getCloudUsage().containerRuntime()).isEqualTo("docker");
+  }
+
+  @Test
+  public void containerRuntime_whenContainerSupportContextMissing_shouldBeNull() {
+    when(containerSupport.getContainerContext()).thenReturn(null);
+    assertThat(underTest.getCloudUsage().containerRuntime()).isNull();
+  }
+
   @Test
   public void kubernetes_whenEnvVarExists_shouldReturnTrue() {
     assertThat(underTest.getCloudUsage().kubernetes()).isTrue();
@@ -171,7 +185,7 @@ public class CloudUsageDataProviderTest {
   public void initHttpClient_whenValidCertificate_shouldCreateClient() throws URISyntaxException {
     when(paths2.get(anyString())).thenReturn(Paths.get(requireNonNull(getClass().getResource("dummy.crt")).toURI()));
 
-    CloudUsageDataProvider provider = new CloudUsageDataProvider(system2, paths2);
+    CloudUsageDataProvider provider = new CloudUsageDataProvider(containerSupport, system2, paths2);
     assertThat(provider.getHttpClient()).isNotNull();
   }
 
@@ -180,7 +194,7 @@ public class CloudUsageDataProviderTest {
     when(paths2.get(anyString())).thenReturn(Paths.get(requireNonNull(getClass().getResource("dummy.crt")).toURI()));
     when(system2.envVariable(KUBERNETES_SERVICE_HOST)).thenReturn(null);
 
-    CloudUsageDataProvider provider = new CloudUsageDataProvider(system2, paths2);
+    CloudUsageDataProvider provider = new CloudUsageDataProvider(containerSupport, system2, paths2);
     assertThat(provider.getHttpClient()).isNull();
   }
 
@@ -188,7 +202,7 @@ public class CloudUsageDataProviderTest {
   public void initHttpClient_whenCertificateNotFound_shouldFail() {
     when(paths2.get(any())).thenReturn(Paths.get("dummy.crt"));
 
-    CloudUsageDataProvider provider = new CloudUsageDataProvider(system2, paths2);
+    CloudUsageDataProvider provider = new CloudUsageDataProvider(containerSupport, system2, paths2);
     assertThat(provider.getHttpClient()).isNull();
   }
 }
index 53e1ab87e281bd4d6263118ecd48992eba0f14c9..fe33ad00647a07ae5f4ab9ff7a3356cb3766cf17 100644 (file)
@@ -24,7 +24,6 @@ import com.tngtech.java.junit.dataprovider.DataProviderRunner;
 import com.tngtech.java.junit.dataprovider.UseDataProvider;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
-import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.HashSet;
@@ -557,7 +556,7 @@ public class TelemetryDataLoaderImplTest {
 
   @Test
   public void load_shouldContainCloudUsage() {
-    CloudUsage cloudUsage = new CloudUsage(true, "1.27", "linux/amd64", "5.4.181-99.354.amzn2.x86_64", "10.1.0", false);
+    CloudUsage cloudUsage = new CloudUsage(true, "1.27", "linux/amd64", "5.4.181-99.354.amzn2.x86_64", "10.1.0", "docker", false);
     when(cloudUsageDataProvider.getCloudUsage()).thenReturn(cloudUsage);
 
     TelemetryData data = commercialUnderTest.load();