private final String defaultQualityGate;
private final Long installationDate;
private final String installationVersion;
- private final boolean inDocker;
+ private final boolean inContainer;
private final ManagedInstanceInformation managedInstanceInformation;
private final CloudUsage cloudUsage;
private final List<UserTelemetryDto> users;
defaultQualityGate = builder.defaultQualityGate;
installationDate = builder.installationDate;
installationVersion = builder.installationVersion;
- inDocker = builder.inDocker;
+ inContainer = builder.inContainer;
users = builder.users;
projects = builder.projects;
projectStatistics = builder.projectStatistics;
return installationVersion;
}
- public boolean isInDocker() {
- return inDocker;
+ public boolean isInContainer() {
+ return inContainer;
}
public ManagedInstanceInformation getManagedInstanceInformation() {
private String defaultQualityGate;
private Long installationDate;
private String installationVersion;
- private boolean inDocker = false;
+ private boolean inContainer = false;
private ManagedInstanceInformation managedInstanceInformation;
private CloudUsage cloudUsage;
private Boolean hasUnanalyzedC;
return this;
}
- Builder setInDocker(boolean inDocker) {
- this.inDocker = inDocker;
+ Builder setInContainer(boolean inContainer) {
+ this.inContainer = inContainer;
return this;
}
if (telemetryData.getInstallationVersion() != null) {
json.prop("installationVersion", telemetryData.getInstallationVersion());
}
- json.prop("docker", telemetryData.isInDocker());
+ json.prop("container", telemetryData.isInContainer());
writeUserData(json, telemetryData);
writeProjectData(json, telemetryData);
@Test
@UseDataProvider("getFeatureFlagEnabledStates")
- public void write_docker_flag(boolean isInDocker) {
+ public void write_container_flag(boolean isIncontainer) {
TelemetryData data = telemetryBuilder()
- .setInDocker(isInDocker)
+ .setInContainer(isIncontainer)
.build();
String json = writeTelemetryData(data);
assertJson(json).isSimilarTo("""
{
- "docker": %s
+ "container": %s
}
- """.formatted(isInDocker));
+ """.formatted(isIncontainer));
}
@DataProvider
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.platform;
+
+public interface ContainerSupport {
+ /**
+ * @return {@code true} if we can detect that SQ is running inside a docker container
+ */
+ boolean isRunningInContainer();
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.server.platform;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.stream.Stream;
+import org.sonar.server.util.Paths2;
+
+public class ContainerSupportImpl implements ContainerSupport {
+ private final Paths2 paths2;
+
+ public ContainerSupportImpl(Paths2 paths2) {
+ this.paths2 = paths2;
+ }
+
+ @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;
+ }
+ }
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.server.platform;
-
-public interface DockerSupport {
- /**
- * @return {@code true} if we can detect that SQ is running inside a docker container
- */
- boolean isRunningInDocker();
-
-}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.server.platform;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.stream.Stream;
-import org.sonar.server.util.Paths2;
-
-public class DockerSupportImpl implements DockerSupport {
- private final Paths2 paths2;
-
- public DockerSupportImpl(Paths2 paths2) {
- this.paths2 = paths2;
- }
-
- @Override
- public boolean isRunningInDocker() {
- 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;
- }
- }
-}
import org.sonar.process.systeminfo.BaseSectionMBean;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
import org.sonar.server.log.ServerLogging;
-import org.sonar.server.platform.DockerSupport;
+import org.sonar.server.platform.ContainerSupport;
import org.sonar.server.platform.OfficialDistribution;
import org.sonar.server.platform.StatisticsSupport;
private final Server server;
private final ServerLogging serverLogging;
private final OfficialDistribution officialDistribution;
- private final DockerSupport dockerSupport;
+ private final ContainerSupport containerSupport;
private final StatisticsSupport statisticsSupport;
private final SonarRuntime sonarRuntime;
private final CommonSystemInformation commonSystemInformation;
public StandaloneSystemSection(Configuration config, Server server, ServerLogging serverLogging,
- OfficialDistribution officialDistribution, DockerSupport dockerSupport, StatisticsSupport statisticsSupport,
+ OfficialDistribution officialDistribution, ContainerSupport containerSupport, StatisticsSupport statisticsSupport,
SonarRuntime sonarRuntime, CommonSystemInformation commonSystemInformation) {
this.config = config;
this.server = server;
this.serverLogging = serverLogging;
this.officialDistribution = officialDistribution;
- this.dockerSupport = dockerSupport;
+ this.containerSupport = containerSupport;
this.statisticsSupport = statisticsSupport;
this.sonarRuntime = sonarRuntime;
this.commonSystemInformation = commonSystemInformation;
setAttribute(protobuf, "Version", getVersion());
setAttribute(protobuf, "Edition", sonarRuntime.getEdition().getLabel());
setAttribute(protobuf, NCLOC.getName(), statisticsSupport.getLinesOfCode());
- setAttribute(protobuf, "Docker", dockerSupport.isRunningInDocker());
+ setAttribute(protobuf, "Container", containerSupport.isRunningInContainer());
setAttribute(protobuf, "External Users and Groups Provisioning", commonSystemInformation.getManagedInstanceProviderName());
setAttribute(protobuf, "External User Authentication", commonSystemInformation.getExternalUserAuthentication());
addIfNotEmpty(protobuf, "Accepted external identity providers",
import org.sonar.process.systeminfo.Global;
import org.sonar.process.systeminfo.SystemInfoSection;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
-import org.sonar.server.platform.DockerSupport;
+import org.sonar.server.platform.ContainerSupport;
import org.sonar.server.platform.StatisticsSupport;
import org.sonar.server.platform.monitoring.CommonSystemInformation;
public class GlobalSystemSection implements SystemInfoSection, Global {
private final Server server;
- private final DockerSupport dockerSupport;
+ private final ContainerSupport containerSupport;
private final StatisticsSupport statisticsSupport;
private final SonarRuntime sonarRuntime;
private final CommonSystemInformation commonSystemInformation;
- public GlobalSystemSection(Server server, DockerSupport dockerSupport, StatisticsSupport statisticsSupport, SonarRuntime sonarRuntime,
+ public GlobalSystemSection(Server server, ContainerSupport containerSupport, StatisticsSupport statisticsSupport, SonarRuntime sonarRuntime,
CommonSystemInformation commonSystemInformation) {
this.server = server;
- this.dockerSupport = dockerSupport;
+ this.containerSupport = containerSupport;
this.statisticsSupport = statisticsSupport;
this.sonarRuntime = sonarRuntime;
this.commonSystemInformation = commonSystemInformation;
setAttribute(protobuf, "Server ID", server.getId());
setAttribute(protobuf, "Edition", sonarRuntime.getEdition().getLabel());
setAttribute(protobuf, NCLOC.getName() ,statisticsSupport.getLinesOfCode());
- setAttribute(protobuf, "Docker", dockerSupport.isRunningInDocker());
+ setAttribute(protobuf, "Container", containerSupport.isRunningInContainer());
setAttribute(protobuf, "High Availability", true);
setAttribute(protobuf, "External Users and Groups Provisioning",
commonSystemInformation.getManagedInstanceProviderName());
import org.sonar.db.qualitygate.ProjectQgateAssociationDto;
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.management.ManagedInstanceService;
-import org.sonar.server.platform.DockerSupport;
+import org.sonar.server.platform.ContainerSupport;
import org.sonar.server.property.InternalProperties;
import org.sonar.server.qualitygate.QualityGateCaycChecker;
import org.sonar.server.qualitygate.QualityGateFinder;
private final PlatformEditionProvider editionProvider;
private final Configuration configuration;
private final InternalProperties internalProperties;
- private final DockerSupport dockerSupport;
+ private final ContainerSupport containerSupport;
private final QualityGateCaycChecker qualityGateCaycChecker;
private final QualityGateFinder qualityGateFinder;
private final ManagedInstanceService managedInstanceService;
@Inject
public TelemetryDataLoaderImpl(Server server, DbClient dbClient, PluginRepository pluginRepository,
PlatformEditionProvider editionProvider, InternalProperties internalProperties, Configuration configuration,
- DockerSupport dockerSupport, QualityGateCaycChecker qualityGateCaycChecker, QualityGateFinder qualityGateFinder,
+ ContainerSupport containerSupport, QualityGateCaycChecker qualityGateCaycChecker, QualityGateFinder qualityGateFinder,
ManagedInstanceService managedInstanceService, CloudUsageDataProvider cloudUsageDataProvider) {
this.server = server;
this.dbClient = dbClient;
this.editionProvider = editionProvider;
this.internalProperties = internalProperties;
this.configuration = configuration;
- this.dockerSupport = dockerSupport;
+ this.containerSupport = containerSupport;
this.qualityGateCaycChecker = qualityGateCaycChecker;
this.qualityGateFinder = qualityGateFinder;
this.managedInstanceService = managedInstanceService;
return data
.setInstallationVersion(installationVersionProperty.orElse(null))
- .setInDocker(dockerSupport.isRunningInDocker())
+ .setInContainer(containerSupport.isRunningInContainer())
.setManagedInstanceInformation(buildManagedInstanceInformation())
.setCloudUsage(buildCloudUsage())
.build();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2023 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.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 org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+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.when;
+
+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();
+ }
+
+ @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();
+ }
+
+ @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();
+ }
+
+ @Test
+ public void isInDocker_returns_true_if_podman_file_exists() throws IOException {
+ when(paths2.exists(PODMAN_FILE_PATH)).thenReturn(true);
+ assertThat(underTest.isRunningInContainer()).isTrue();
+ }
+
+ @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();
+ }
+
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2023 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program 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.
- *
- * This program 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.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 org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-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.when;
-
-public class DockerSupportImplTest {
- 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 DockerSupportImpl underTest = new DockerSupportImpl(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.isRunningInDocker()).isFalse();
- }
-
- @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.isRunningInDocker()).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.isRunningInDocker()).isFalse();
- }
-
- @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.isRunningInDocker()).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.isRunningInDocker()).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.isRunningInDocker()).isTrue();
- }
-
- @Test
- public void isInDocker_returns_true_if_podman_file_exists() throws IOException {
- when(paths2.exists(PODMAN_FILE_PATH)).thenReturn(true);
- assertThat(underTest.isRunningInDocker()).isTrue();
- }
-
- @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.isRunningInDocker()).isFalse();
- }
-
-}
import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
import org.sonar.server.log.ServerLogging;
-import org.sonar.server.platform.DockerSupport;
+import org.sonar.server.platform.ContainerSupport;
import org.sonar.server.platform.OfficialDistribution;
import org.sonar.server.platform.StatisticsSupport;
private final Server server = mock(Server.class);
private final ServerLogging serverLogging = mock(ServerLogging.class);
private final OfficialDistribution officialDistribution = mock(OfficialDistribution.class);
- private final DockerSupport dockerSupport = mock(DockerSupport.class);
+ private final ContainerSupport containerSupport = mock(ContainerSupport.class);
private final StatisticsSupport statisticsSupport = mock(StatisticsSupport.class);
private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
private final CommonSystemInformation commonSystemInformation = mock(CommonSystemInformation.class);
private final StandaloneSystemSection underTest = new StandaloneSystemSection(config, server, serverLogging,
- officialDistribution, dockerSupport, statisticsSupport, sonarRuntime, commonSystemInformation);
+ officialDistribution, containerSupport, statisticsSupport, sonarRuntime, commonSystemInformation);
@Before
public void setUp() {
@Test
@UseDataProvider("trueOrFalse")
- public void return_docker_flag_from_DockerSupport(boolean flag) {
- when(dockerSupport.isRunningInDocker()).thenReturn(flag);
+ public void toProtobuf_whenRunningOrNotRunningInContainer_shouldReturnCorrectFlag(boolean flag) {
+ when(containerSupport.isRunningInContainer()).thenReturn(flag);
ProtobufSystemInfo.Section protobuf = underTest.toProtobuf();
- assertThat(attribute(protobuf, "Docker").getBooleanValue()).isEqualTo(flag);
+ assertThat(attribute(protobuf, "Container").getBooleanValue()).isEqualTo(flag);
}
@Test
import org.sonar.api.SonarRuntime;
import org.sonar.api.platform.Server;
import org.sonar.process.systeminfo.protobuf.ProtobufSystemInfo;
-import org.sonar.server.platform.DockerSupport;
+import org.sonar.server.platform.ContainerSupport;
import org.sonar.server.platform.StatisticsSupport;
import org.sonar.server.platform.monitoring.CommonSystemInformation;
public class GlobalSystemSectionTest {
private final Server server = mock(Server.class);
- private final DockerSupport dockerSupport = mock(DockerSupport.class);
+ private final ContainerSupport containerSupport = mock(ContainerSupport.class);
private final StatisticsSupport statisticsSupport = mock(StatisticsSupport.class);
private final SonarRuntime sonarRuntime = mock(SonarRuntime.class);
private final CommonSystemInformation commonSystemInformation = mock(CommonSystemInformation.class);
- private final GlobalSystemSection underTest = new GlobalSystemSection(server, dockerSupport, statisticsSupport, sonarRuntime, commonSystemInformation);
+ private final GlobalSystemSection underTest = new GlobalSystemSection(server, containerSupport, statisticsSupport, sonarRuntime, commonSystemInformation);
@Before
public void setUp() {
@Test
@UseDataProvider("trueOrFalse")
- public void get_docker_flag(boolean flag) {
- when(dockerSupport.isRunningInDocker()).thenReturn(flag);
+ public void toProtobuf_whenRunningOrNotRunningInContainer_shouldReturnCorrectFlag(boolean flag) {
+ when(containerSupport.isRunningInContainer()).thenReturn(flag);
ProtobufSystemInfo.Section protobuf = underTest.toProtobuf();
- assertThatAttributeIs(protobuf, "Docker", flag);
+ assertThatAttributeIs(protobuf, "Container", flag);
}
@Test
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserTelemetryDto;
import org.sonar.server.management.ManagedInstanceService;
-import org.sonar.server.platform.DockerSupport;
+import org.sonar.server.platform.ContainerSupport;
import org.sonar.server.property.InternalProperties;
import org.sonar.server.property.MapInternalProperties;
import org.sonar.server.qualitygate.QualityGateCaycChecker;
private final PluginRepository pluginRepository = mock(PluginRepository.class);
private final Configuration configuration = mock(Configuration.class);
private final PlatformEditionProvider editionProvider = mock(PlatformEditionProvider.class);
- private final DockerSupport dockerSupport = mock(DockerSupport.class);
+ private final ContainerSupport containerSupport = mock(ContainerSupport.class);
private final QualityGateCaycChecker qualityGateCaycChecker = mock(QualityGateCaycChecker.class);
private final QualityGateFinder qualityGateFinder = new QualityGateFinder(db.getDbClient());
private final InternalProperties internalProperties = spy(new MapInternalProperties());
private final CloudUsageDataProvider cloudUsageDataProvider = mock(CloudUsageDataProvider.class);
private final TelemetryDataLoader communityUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider,
- internalProperties, configuration, dockerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider);
+ internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider);
private final TelemetryDataLoader commercialUnderTest = new TelemetryDataLoaderImpl(server, db.getDbClient(), pluginRepository, editionProvider,
- internalProperties, configuration, dockerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider);
+ internalProperties, configuration, containerSupport, qualityGateCaycChecker, qualityGateFinder, managedInstanceService, cloudUsageDataProvider);
private QualityGateDto builtInDefaultQualityGate;
private MetricDto bugsDto;
assertDatabaseMetadata(data.getDatabase());
assertThat(data.getPlugins()).containsOnly(
entry("java", "4.12.0.11033"), entry("scmgit", "1.2"), entry("other", "undefined"));
- assertThat(data.isInDocker()).isFalse();
+ assertThat(data.isInContainer()).isFalse();
assertThat(data.getUserTelemetries())
.extracting(UserTelemetryDto::getUuid, UserTelemetryDto::getLastConnectionDate, UserTelemetryDto::getLastSonarlintConnectionDate, UserTelemetryDto::isActive)
import org.sonar.server.issue.index.IssueIndexSyncProgressChecker;
import org.sonar.server.permission.index.WebAuthorizationTypeSupport;
import org.sonar.server.platform.DefaultNodeInformation;
-import org.sonar.server.platform.DockerSupportImpl;
+import org.sonar.server.platform.ContainerSupportImpl;
import org.sonar.server.platform.LogServerVersion;
import org.sonar.server.platform.Platform;
import org.sonar.server.platform.ServerFileSystemImpl;
new TempFolderProvider(),
System2.INSTANCE,
Paths2Impl.getInstance(),
- DockerSupportImpl.class,
+ ContainerSupportImpl.class,
Clock.systemDefaultZone(),
// user session