From e602dc2a0c208f70a364fac95d6c9e3e5486ffc1 Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Mon, 14 Nov 2022 15:04:22 -0800 Subject: [PATCH 1/4] refactor out v1 extractor and stub v2 --- .../CGroupsV1ContainerIdExtractor.java | 95 ++++++++++++++ .../CGroupsV2ContainerIdExtractor.java | 24 ++++ .../resources/ContainerResource.java | 118 +++++++----------- .../CGroupsV1ContainerIdExtractorTest.java | 109 ++++++++++++++++ .../CGroupsV2ContainerIdExtractorTest.java | 9 ++ .../resources/ContainerResourceTest.java | 103 +++++---------- 6 files changed, 314 insertions(+), 144 deletions(-) create mode 100644 instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java create mode 100644 instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java create mode 100644 instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java create mode 100644 instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java new file mode 100644 index 000000000000..3524de4586b4 --- /dev/null +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java @@ -0,0 +1,95 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.resources; + +import io.opentelemetry.api.internal.OtelEncodingUtils; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Stream; + +/** Utility for extracting the container ID from runtimes inside cgroup v1 containers.*/ +final class CGroupsV1ContainerIdExtractor { + + private static final Logger logger = Logger.getLogger(CGroupsV1ContainerIdExtractor.class.getName()); + static final Path V1_CGROUP_FILE_PATH = Paths.get("/proc/self/cgroup"); + private final ContainerResource.Filesystem filesystem; + + CGroupsV1ContainerIdExtractor(){ + this(ContainerResource.FILESYSTEM_INSTANCE); + } + + //Exists for testing + CGroupsV1ContainerIdExtractor(ContainerResource.Filesystem filesystem) { + this.filesystem = filesystem; + } + + + /** + * Each line of cgroup file looks like "14:name=systemd:/docker/.../... A hex string is expected + * inside the last section separated by '/' Each segment of the '/' can contain metadata separated + * by either '.' (at beginning) or '-' (at end) + * + * @return containerId + */ + Optional extractContainerId() { + if (!filesystem.exists(V1_CGROUP_FILE_PATH) || !filesystem.isReadable(V1_CGROUP_FILE_PATH)) { + return Optional.empty(); + } + try (Stream lines = filesystem.lines(V1_CGROUP_FILE_PATH)) { + return lines + .filter(line -> !line.isEmpty()) + .map(CGroupsV1ContainerIdExtractor::getIdFromLine) + .filter(Optional::isPresent) + .findFirst() + .orElse(Optional.empty()); + } catch (Exception e) { + logger.log(Level.WARNING, "Unable to read file", e); + } + return Optional.empty(); + } + + private static Optional getIdFromLine(String line) { + // This cgroup output line should have the container id in it + int lastSlashIdx = line.lastIndexOf('/'); + if (lastSlashIdx < 0) { + return Optional.empty(); + } + + String containerId; + + String lastSection = line.substring(lastSlashIdx + 1); + int colonIdx = lastSection.lastIndexOf(':'); + + if (colonIdx != -1) { + // since containerd v1.5.0+, containerId is divided by the last colon when the cgroupDriver is + // systemd: + // https://github.com/containerd/containerd/blob/release/1.5/pkg/cri/server/helpers_linux.go#L64 + containerId = lastSection.substring(colonIdx + 1); + } else { + int startIdx = lastSection.lastIndexOf('-'); + int endIdx = lastSection.lastIndexOf('.'); + + startIdx = startIdx == -1 ? 0 : startIdx + 1; + if (endIdx == -1) { + endIdx = lastSection.length(); + } + if (startIdx > endIdx) { + return Optional.empty(); + } + + containerId = lastSection.substring(startIdx, endIdx); + } + + if (OtelEncodingUtils.isValidBase16String(containerId) && !containerId.isEmpty()) { + return Optional.of(containerId); + } else { + return Optional.empty(); + } + } +} diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java new file mode 100644 index 000000000000..8d453ca81721 --- /dev/null +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java @@ -0,0 +1,24 @@ +package io.opentelemetry.instrumentation.resources; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; + +/** Utility for extracting the container ID from runtimes inside cgroup v2 containers.*/ +class CGroupsV2ContainerIdExtractor { + + static final Path V2_CGROUP_FILE_PATH = Paths.get("/proc/self/mountinfo"); + + CGroupsV2ContainerIdExtractor(){ + this(ContainerResource.FILESYSTEM_INSTANCE); + } + private final ContainerResource.Filesystem filesystem; + + // Exists for testing + CGroupsV2ContainerIdExtractor( + ContainerResource.Filesystem filesystem) {this.filesystem = filesystem;} + + Optional extractContainerId() { + return Optional.empty(); + } +} diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java index f225084ae517..d05d78fb0b6b 100644 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java @@ -5,106 +5,78 @@ package io.opentelemetry.instrumentation.resources; +import com.google.errorprone.annotations.MustBeClosed; import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.internal.OtelEncodingUtils; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; +import java.io.IOException; import java.nio.file.Files; +import java.nio.file.LinkOption; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Optional; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Stream; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.CONTAINER_ID; + /** Factory for {@link Resource} retrieving Container ID information. */ public final class ContainerResource { - private static final Logger logger = Logger.getLogger(ContainerResource.class.getName()); - private static final String UNIQUE_HOST_NAME_FILE_NAME = "/proc/self/cgroup"; - private static final Resource INSTANCE = buildSingleton(UNIQUE_HOST_NAME_FILE_NAME); + private static final Resource INSTANCE = buildSingleton(); - private static Resource buildSingleton(String uniqueHostNameFileName) { + private static Resource buildSingleton() { // can't initialize this statically without running afoul of animalSniffer on paths - return buildResource(Paths.get(uniqueHostNameFileName)); + return new ContainerResource().buildResource(); + } + + private final CGroupsV1ContainerIdExtractor v1Extractor; + private final CGroupsV2ContainerIdExtractor v2Extractor; + + private ContainerResource() { + this(new CGroupsV1ContainerIdExtractor(), new CGroupsV2ContainerIdExtractor()); } - // package private for testing - static Resource buildResource(Path path) { - return extractContainerId(path) - .map( - containerId -> - Resource.create(Attributes.of(ResourceAttributes.CONTAINER_ID, containerId))) + // Visible for testing + ContainerResource( + CGroupsV1ContainerIdExtractor v1Extractor, CGroupsV2ContainerIdExtractor v2Extractor) { + this.v1Extractor = v1Extractor; + this.v2Extractor = v2Extractor; + } + + + // Visible for testing + Resource buildResource() { + return getContainerId() + .map(id -> Resource.create(Attributes.of(CONTAINER_ID, id))) .orElseGet(Resource::empty); } + private Optional getContainerId() { + Optional v1Result = v1Extractor.extractContainerId(); + if(v1Result.isPresent()){ + return v1Result; + } + return v2Extractor.extractContainerId(); + } + /** Returns resource with container information. */ public static Resource get() { return INSTANCE; } - /** - * Each line of cgroup file looks like "14:name=systemd:/docker/.../... A hex string is expected - * inside the last section separated by '/' Each segment of the '/' can contain metadata separated - * by either '.' (at beginning) or '-' (at end) - * - * @return containerId - */ - private static Optional extractContainerId(Path cgroupFilePath) { - if (!Files.exists(cgroupFilePath) || !Files.isReadable(cgroupFilePath)) { - return Optional.empty(); - } - try (Stream lines = Files.lines(cgroupFilePath)) { - return lines - .filter(line -> !line.isEmpty()) - .map(ContainerResource::getIdFromLine) - .filter(Optional::isPresent) - .findFirst() - .orElse(Optional.empty()); - } catch (Exception e) { - logger.log(Level.WARNING, "Unable to read file", e); + // Exists for testing + final static Filesystem FILESYSTEM_INSTANCE = new Filesystem(); + static class Filesystem { + boolean exists(Path path, LinkOption... options) { + return Files.exists(path, options); } - return Optional.empty(); - } - private static Optional getIdFromLine(String line) { - // This cgroup output line should have the container id in it - int lastSlashIdx = line.lastIndexOf('/'); - if (lastSlashIdx < 0) { - return Optional.empty(); + boolean isReadable(Path path) { + return Files.isReadable(path); } - String containerId; - - String lastSection = line.substring(lastSlashIdx + 1); - int colonIdx = lastSection.lastIndexOf(':'); - - if (colonIdx != -1) { - // since containerd v1.5.0+, containerId is divided by the last colon when the cgroupDriver is - // systemd: - // https://github.com/containerd/containerd/blob/release/1.5/pkg/cri/server/helpers_linux.go#L64 - containerId = lastSection.substring(colonIdx + 1); - } else { - int startIdx = lastSection.lastIndexOf('-'); - int endIdx = lastSection.lastIndexOf('.'); - - startIdx = startIdx == -1 ? 0 : startIdx + 1; - if (endIdx == -1) { - endIdx = lastSection.length(); - } - if (startIdx > endIdx) { - return Optional.empty(); - } - - containerId = lastSection.substring(startIdx, endIdx); + @MustBeClosed + Stream lines(Path path) throws IOException { + return Files.lines(path); } - if (OtelEncodingUtils.isValidBase16String(containerId) && !containerId.isEmpty()) { - return Optional.of(containerId); - } else { - return Optional.empty(); - } } - - private ContainerResource() {} } diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java new file mode 100644 index 000000000000..debcd1b305fd --- /dev/null +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java @@ -0,0 +1,109 @@ +package io.opentelemetry.instrumentation.resources; + +import static io.opentelemetry.instrumentation.resources.CGroupsV1ContainerIdExtractor.V1_CGROUP_FILE_PATH; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.util.Optional; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class CGroupsV1ContainerIdExtractorTest { + + @Mock + ContainerResource.Filesystem filesystem; + + @Test + void fileDoesntExist() throws IOException { + when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(false); + CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result).isEmpty(); + verify(filesystem, never()).lines(any()); + } + + @Test + void fileNotReadable() throws IOException{ + when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(true); + when(filesystem.isReadable(V1_CGROUP_FILE_PATH)).thenReturn(false); + CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result).isEmpty(); + verify(filesystem, never()).lines(any()); + } + + @ParameterizedTest + @ValueSource( + strings = { + // invalid containerId (non-hex) + "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23zzzz", + // unrecognized format (last "-" is after last ".") + "13:name=systemd:/podruntime/docker/kubepods/ac679f8.a8319c8cf7d38e1adf263bc08-d23zzzz" + }) + void invalidContainerIds(String line) throws IOException { + when(filesystem.isReadable(V1_CGROUP_FILE_PATH)).thenReturn(true); + when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(true); + when(filesystem.lines(V1_CGROUP_FILE_PATH)).thenReturn(Stream.of(line)); + + CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result).isEmpty(); + } + + @ParameterizedTest + @MethodSource("validLines") + void validCgroupLines(String line, String expectedContainerId) throws IOException { + when(filesystem.isReadable(V1_CGROUP_FILE_PATH)).thenReturn(true); + when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(true); + when(filesystem.lines(V1_CGROUP_FILE_PATH)).thenReturn(Stream.of(line)); + + CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result.get()).isEqualTo(expectedContainerId); + } + + static Stream validLines() { + return Stream.of( + // with suffix + arguments( + "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23.aaaa", + "ac679f8a8319c8cf7d38e1adf263bc08d23"), + // with prefix and suffix + arguments( + "13:name=systemd:/podruntime/docker/kubepods/crio-dc679f8a8319c8cf7d38e1adf263bc08d23.stuff", + "dc679f8a8319c8cf7d38e1adf263bc08d23"), + // just container id + arguments( + "13:name=systemd:/pod/d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356", + "d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356"), + // with prefix + arguments( + "//\n" + + "1:name=systemd:/podruntime/docker/kubepods/docker-dc579f8a8319c8cf7d38e1adf263bc08d23" + + "2:name=systemd:/podruntime/docker/kubepods/docker-dc579f8a8319c8cf7d38e1adf263bc08d23" + + "3:name=systemd:/podruntime/docker/kubepods/docker-dc579f8a8319c8cf7d38e1adf263bc08d23", + "dc579f8a8319c8cf7d38e1adf263bc08d23"), + // with two dashes in prefix + arguments( + "11:perf_event:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod4415fd05_2c0f_4533_909b_f2180dca8d7c.slice/cri-containerd-713a77a26fe2a38ebebd5709604a048c3d380db1eb16aa43aca0b2499e54733c.scope", + "713a77a26fe2a38ebebd5709604a048c3d380db1eb16aa43aca0b2499e54733c"), + // with colon, env: k8s v1.24.0, the cgroupDriver by systemd(default), and container is + // cri-containerd v1.6.8 + arguments( + "11:devices:/system.slice/containerd.service/kubepods-pod87a18a64_b74a_454a_b10b_a4a36059d0a3.slice:cri-containerd:05c48c82caff3be3d7f1e896981dd410e81487538936914f32b624d168de9db0", + "05c48c82caff3be3d7f1e896981dd410e81487538936914f32b624d168de9db0")); + } +} \ No newline at end of file diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java new file mode 100644 index 000000000000..e07e6a4d2b57 --- /dev/null +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java @@ -0,0 +1,9 @@ +package io.opentelemetry.instrumentation.resources; + +import static org.junit.jupiter.api.Assertions.*; + +class CGroupsV2ContainerIdExtractorTest { + + + +} \ No newline at end of file diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java index 82408b102dc4..29a0aec2ad60 100644 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java @@ -5,91 +5,52 @@ package io.opentelemetry.instrumentation.resources; -import static io.opentelemetry.instrumentation.resources.ContainerResource.buildResource; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.CONTAINER_ID; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.mockito.Mockito.when; import io.opentelemetry.sdk.resources.Resource; -import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.stream.Stream; +import java.util.Optional; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) class ContainerResourceTest { - @ParameterizedTest - @ValueSource( - strings = { - // invalid containerId (non-hex) - "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23zzzz", - // unrecognized format (last "-" is after last ".") - "13:name=systemd:/podruntime/docker/kubepods/ac679f8.a8319c8cf7d38e1adf263bc08-d23zzzz" - }) - void buildResource_returnsEmptyResource_whenContainerIdIsInvalid( - String line, @TempDir Path tempFolder) throws IOException { - Path cgroup = createCgroup(tempFolder.resolve("cgroup"), line); - assertThat(buildResource(cgroup)).isEqualTo(Resource.empty()); - } + public static final String TEST_CONTAINER_ID = "abcdef123123deadbeef"; + @Mock + CGroupsV1ContainerIdExtractor v1; + @Mock + CGroupsV2ContainerIdExtractor v2; @Test - void buildResource_returnsEmptyResource_whenFileDoesNotExist(@TempDir Path tempFolder) { - Path cgroup = tempFolder.resolve("DoesNotExist"); - assertThat(buildResource(cgroup)).isEqualTo(Resource.empty()); + void v1Success() { + when(v1.extractContainerId()).thenReturn(Optional.of(TEST_CONTAINER_ID)); + ContainerResource containerResource = new ContainerResource(v1, v2); + Resource resource = containerResource.buildResource(); + Assertions.assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); } - @ParameterizedTest - @MethodSource("validLines") - void buildResource_extractsContainerIdFromValidLines( - String line, String expectedContainerId, @TempDir Path tempFolder) throws IOException { - Path cgroup = createCgroup(tempFolder.resolve("cgroup"), line); - assertThat(getContainerId(buildResource(cgroup))).isEqualTo(expectedContainerId); - } + @Test + void v2Success() { + when(v1.extractContainerId()).thenReturn(Optional.empty()); + when(v2.extractContainerId()).thenReturn(Optional.of(TEST_CONTAINER_ID)); + ContainerResource containerResource = new ContainerResource(v1, v2); + Resource resource = containerResource.buildResource(); + Assertions.assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); - static Stream validLines() { - return Stream.of( - // with suffix - arguments( - "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23.aaaa", - "ac679f8a8319c8cf7d38e1adf263bc08d23"), - // with prefix and suffix - arguments( - "13:name=systemd:/podruntime/docker/kubepods/crio-dc679f8a8319c8cf7d38e1adf263bc08d23.stuff", - "dc679f8a8319c8cf7d38e1adf263bc08d23"), - // just container id - arguments( - "13:name=systemd:/pod/d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356", - "d86d75589bf6cc254f3e2cc29debdf85dde404998aa128997a819ff991827356"), - // with prefix - arguments( - "//\n" - + "1:name=systemd:/podruntime/docker/kubepods/docker-dc579f8a8319c8cf7d38e1adf263bc08d23" - + "2:name=systemd:/podruntime/docker/kubepods/docker-dc579f8a8319c8cf7d38e1adf263bc08d23" - + "3:name=systemd:/podruntime/docker/kubepods/docker-dc579f8a8319c8cf7d38e1adf263bc08d23", - "dc579f8a8319c8cf7d38e1adf263bc08d23"), - // with two dashes in prefix - arguments( - "11:perf_event:/kubepods.slice/kubepods-burstable.slice/kubepods-burstable-pod4415fd05_2c0f_4533_909b_f2180dca8d7c.slice/cri-containerd-713a77a26fe2a38ebebd5709604a048c3d380db1eb16aa43aca0b2499e54733c.scope", - "713a77a26fe2a38ebebd5709604a048c3d380db1eb16aa43aca0b2499e54733c"), - // with colon, env: k8s v1.24.0, the cgroupDriver by systemd(default), and container is - // cri-containerd v1.6.8 - arguments( - "11:devices:/system.slice/containerd.service/kubepods-pod87a18a64_b74a_454a_b10b_a4a36059d0a3.slice:cri-containerd:05c48c82caff3be3d7f1e896981dd410e81487538936914f32b624d168de9db0", - "05c48c82caff3be3d7f1e896981dd410e81487538936914f32b624d168de9db0")); } - private static String getContainerId(Resource resource) { - return resource.getAttribute(ResourceAttributes.CONTAINER_ID); + @Test + void bothVersionsFail() { + when(v1.extractContainerId()).thenReturn(Optional.empty()); + when(v2.extractContainerId()).thenReturn(Optional.empty()); + ContainerResource containerResource = new ContainerResource(v1, v2); + Resource resource = containerResource.buildResource(); + assertThat(resource).isSameAs(Resource.empty()); } - private static Path createCgroup(Path path, String line) throws IOException { - return Files.write(path, line.getBytes(StandardCharsets.UTF_8)); - } } From adab0cc8aa8db2126a9749e9346fa67a1eb55d4d Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Mon, 14 Nov 2022 15:06:59 -0800 Subject: [PATCH 2/4] readable includes exists check --- .../resources/CGroupsV1ContainerIdExtractor.java | 2 +- .../instrumentation/resources/ContainerResource.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java index 3524de4586b4..36b0e9e35258 100644 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java @@ -38,7 +38,7 @@ final class CGroupsV1ContainerIdExtractor { * @return containerId */ Optional extractContainerId() { - if (!filesystem.exists(V1_CGROUP_FILE_PATH) || !filesystem.isReadable(V1_CGROUP_FILE_PATH)) { + if (!filesystem.isReadable(V1_CGROUP_FILE_PATH)) { return Optional.empty(); } try (Stream lines = filesystem.lines(V1_CGROUP_FILE_PATH)) { diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java index d05d78fb0b6b..79d382305fb9 100644 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java @@ -65,9 +65,6 @@ public static Resource get() { // Exists for testing final static Filesystem FILESYSTEM_INSTANCE = new Filesystem(); static class Filesystem { - boolean exists(Path path, LinkOption... options) { - return Files.exists(path, options); - } boolean isReadable(Path path) { return Files.isReadable(path); From 8be96c0cc213ef229429cc06479814d62b2eea0b Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Mon, 14 Nov 2022 16:03:21 -0800 Subject: [PATCH 3/4] parse cgroup v2 file --- .../CGroupsV2ContainerIdExtractor.java | 24 ------- ...java => CgroupV1ContainerIdExtractor.java} | 22 +++--- .../CgroupV2ContainerIdExtractor.java | 56 +++++++++++++++ .../resources/ContainerResource.java | 24 +++---- .../CGroupsV2ContainerIdExtractorTest.java | 9 --- ... => CgroupV1ContainerIdExtractorTest.java} | 54 +++++++-------- .../CgroupV2ContainerIdExtractorTest.java | 68 +++++++++++++++++++ .../resources/ContainerResourceTest.java | 8 +-- 8 files changed, 172 insertions(+), 93 deletions(-) delete mode 100644 instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java rename instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/{CGroupsV1ContainerIdExtractor.java => CgroupV1ContainerIdExtractor.java} (81%) create mode 100644 instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java delete mode 100644 instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java rename instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/{CGroupsV1ContainerIdExtractorTest.java => CgroupV1ContainerIdExtractorTest.java} (64%) create mode 100644 instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java deleted file mode 100644 index 8d453ca81721..000000000000 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractor.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.opentelemetry.instrumentation.resources; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Optional; - -/** Utility for extracting the container ID from runtimes inside cgroup v2 containers.*/ -class CGroupsV2ContainerIdExtractor { - - static final Path V2_CGROUP_FILE_PATH = Paths.get("/proc/self/mountinfo"); - - CGroupsV2ContainerIdExtractor(){ - this(ContainerResource.FILESYSTEM_INSTANCE); - } - private final ContainerResource.Filesystem filesystem; - - // Exists for testing - CGroupsV2ContainerIdExtractor( - ContainerResource.Filesystem filesystem) {this.filesystem = filesystem;} - - Optional extractContainerId() { - return Optional.empty(); - } -} diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV1ContainerIdExtractor.java similarity index 81% rename from instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java rename to instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV1ContainerIdExtractor.java index 36b0e9e35258..7d23ccbc54d2 100644 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractor.java +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV1ContainerIdExtractor.java @@ -13,23 +13,23 @@ import java.util.logging.Logger; import java.util.stream.Stream; -/** Utility for extracting the container ID from runtimes inside cgroup v1 containers.*/ -final class CGroupsV1ContainerIdExtractor { +/** Utility for extracting the container ID from runtimes inside cgroup v1 containers. */ +final class CgroupV1ContainerIdExtractor { - private static final Logger logger = Logger.getLogger(CGroupsV1ContainerIdExtractor.class.getName()); - static final Path V1_CGROUP_FILE_PATH = Paths.get("/proc/self/cgroup"); + private static final Logger logger = + Logger.getLogger(CgroupV1ContainerIdExtractor.class.getName()); + static final Path V1_CGROUP_PATH = Paths.get("/proc/self/cgroup"); private final ContainerResource.Filesystem filesystem; - CGroupsV1ContainerIdExtractor(){ + CgroupV1ContainerIdExtractor() { this(ContainerResource.FILESYSTEM_INSTANCE); } - //Exists for testing - CGroupsV1ContainerIdExtractor(ContainerResource.Filesystem filesystem) { + // Exists for testing + CgroupV1ContainerIdExtractor(ContainerResource.Filesystem filesystem) { this.filesystem = filesystem; } - /** * Each line of cgroup file looks like "14:name=systemd:/docker/.../... A hex string is expected * inside the last section separated by '/' Each segment of the '/' can contain metadata separated @@ -38,13 +38,13 @@ final class CGroupsV1ContainerIdExtractor { * @return containerId */ Optional extractContainerId() { - if (!filesystem.isReadable(V1_CGROUP_FILE_PATH)) { + if (!filesystem.isReadable(V1_CGROUP_PATH)) { return Optional.empty(); } - try (Stream lines = filesystem.lines(V1_CGROUP_FILE_PATH)) { + try (Stream lines = filesystem.lines(V1_CGROUP_PATH)) { return lines .filter(line -> !line.isEmpty()) - .map(CGroupsV1ContainerIdExtractor::getIdFromLine) + .map(CgroupV1ContainerIdExtractor::getIdFromLine) .filter(Optional::isPresent) .findFirst() .orElse(Optional.empty()); diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java new file mode 100644 index 000000000000..5e9a1ab2ccb1 --- /dev/null +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractor.java @@ -0,0 +1,56 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.resources; + +import static java.util.Optional.empty; + +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** Utility for extracting the container ID from runtimes inside cgroup v2 containers. */ +class CgroupV2ContainerIdExtractor { + + private static final Logger logger = + Logger.getLogger(CgroupV2ContainerIdExtractor.class.getName()); + + static final Path V2_CGROUP_PATH = Paths.get("/proc/self/mountinfo"); + private static final Pattern CONTAINER_RE = + Pattern.compile(".*/docker/containers/([0-9a-f]{64})/.*"); + + private final ContainerResource.Filesystem filesystem; + + CgroupV2ContainerIdExtractor() { + this(ContainerResource.FILESYSTEM_INSTANCE); + } + + // Exists for testing + CgroupV2ContainerIdExtractor(ContainerResource.Filesystem filesystem) { + this.filesystem = filesystem; + } + + Optional extractContainerId() { + if (!filesystem.isReadable(V2_CGROUP_PATH)) { + return empty(); + } + try { + return filesystem + .lines(V2_CGROUP_PATH) + .map(CONTAINER_RE::matcher) + .filter(Matcher::matches) + .findFirst() + .map(matcher -> matcher.group(1)); + } catch (IOException e) { + logger.log(Level.WARNING, "Unable to read v2 cgroup path", e); + } + return empty(); + } +} diff --git a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java index 79d382305fb9..9e745475cd20 100644 --- a/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java +++ b/instrumentation/resources/library/src/main/java/io/opentelemetry/instrumentation/resources/ContainerResource.java @@ -5,21 +5,24 @@ package io.opentelemetry.instrumentation.resources; +import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.CONTAINER_ID; + import com.google.errorprone.annotations.MustBeClosed; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.sdk.resources.Resource; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.LinkOption; import java.nio.file.Path; import java.util.Optional; import java.util.stream.Stream; -import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.CONTAINER_ID; - -/** Factory for {@link Resource} retrieving Container ID information. */ +/** + * Factory for {@link Resource} retrieving Container ID information. It supports both cgroup v1 and + * v2 runtimes. + */ public final class ContainerResource { + static final Filesystem FILESYSTEM_INSTANCE = new Filesystem(); private static final Resource INSTANCE = buildSingleton(); private static Resource buildSingleton() { @@ -27,21 +30,20 @@ private static Resource buildSingleton() { return new ContainerResource().buildResource(); } - private final CGroupsV1ContainerIdExtractor v1Extractor; - private final CGroupsV2ContainerIdExtractor v2Extractor; + private final CgroupV1ContainerIdExtractor v1Extractor; + private final CgroupV2ContainerIdExtractor v2Extractor; private ContainerResource() { - this(new CGroupsV1ContainerIdExtractor(), new CGroupsV2ContainerIdExtractor()); + this(new CgroupV1ContainerIdExtractor(), new CgroupV2ContainerIdExtractor()); } // Visible for testing ContainerResource( - CGroupsV1ContainerIdExtractor v1Extractor, CGroupsV2ContainerIdExtractor v2Extractor) { + CgroupV1ContainerIdExtractor v1Extractor, CgroupV2ContainerIdExtractor v2Extractor) { this.v1Extractor = v1Extractor; this.v2Extractor = v2Extractor; } - // Visible for testing Resource buildResource() { return getContainerId() @@ -51,7 +53,7 @@ Resource buildResource() { private Optional getContainerId() { Optional v1Result = v1Extractor.extractContainerId(); - if(v1Result.isPresent()){ + if (v1Result.isPresent()) { return v1Result; } return v2Extractor.extractContainerId(); @@ -63,7 +65,6 @@ public static Resource get() { } // Exists for testing - final static Filesystem FILESYSTEM_INSTANCE = new Filesystem(); static class Filesystem { boolean isReadable(Path path) { @@ -74,6 +75,5 @@ boolean isReadable(Path path) { Stream lines(Path path) throws IOException { return Files.lines(path); } - } } diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java deleted file mode 100644 index e07e6a4d2b57..000000000000 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV2ContainerIdExtractorTest.java +++ /dev/null @@ -1,9 +0,0 @@ -package io.opentelemetry.instrumentation.resources; - -import static org.junit.jupiter.api.Assertions.*; - -class CGroupsV2ContainerIdExtractorTest { - - - -} \ No newline at end of file diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV1ContainerIdExtractorTest.java similarity index 64% rename from instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java rename to instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV1ContainerIdExtractorTest.java index debcd1b305fd..b529e25bf979 100644 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CGroupsV1ContainerIdExtractorTest.java +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV1ContainerIdExtractorTest.java @@ -1,6 +1,11 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + package io.opentelemetry.instrumentation.resources; -import static io.opentelemetry.instrumentation.resources.CGroupsV1ContainerIdExtractor.V1_CGROUP_FILE_PATH; +import static io.opentelemetry.instrumentation.resources.CgroupV1ContainerIdExtractor.V1_CGROUP_PATH; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.params.provider.Arguments.arguments; import static org.mockito.ArgumentMatchers.any; @@ -21,25 +26,14 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class CGroupsV1ContainerIdExtractorTest { - - @Mock - ContainerResource.Filesystem filesystem; +class CgroupV1ContainerIdExtractorTest { - @Test - void fileDoesntExist() throws IOException { - when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(false); - CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); - Optional result = extractor.extractContainerId(); - assertThat(result).isEmpty(); - verify(filesystem, never()).lines(any()); - } + @Mock ContainerResource.Filesystem filesystem; @Test - void fileNotReadable() throws IOException{ - when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(true); - when(filesystem.isReadable(V1_CGROUP_FILE_PATH)).thenReturn(false); - CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + void fileNotReadable() throws IOException { + when(filesystem.isReadable(V1_CGROUP_PATH)).thenReturn(false); + CgroupV1ContainerIdExtractor extractor = new CgroupV1ContainerIdExtractor(filesystem); Optional result = extractor.extractContainerId(); assertThat(result).isEmpty(); verify(filesystem, never()).lines(any()); @@ -48,17 +42,16 @@ void fileNotReadable() throws IOException{ @ParameterizedTest @ValueSource( strings = { - // invalid containerId (non-hex) - "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23zzzz", - // unrecognized format (last "-" is after last ".") - "13:name=systemd:/podruntime/docker/kubepods/ac679f8.a8319c8cf7d38e1adf263bc08-d23zzzz" + // invalid containerId (non-hex) + "13:name=systemd:/podruntime/docker/kubepods/ac679f8a8319c8cf7d38e1adf263bc08d23zzzz", + // unrecognized format (last "-" is after last ".") + "13:name=systemd:/podruntime/docker/kubepods/ac679f8.a8319c8cf7d38e1adf263bc08-d23zzzz" }) void invalidContainerIds(String line) throws IOException { - when(filesystem.isReadable(V1_CGROUP_FILE_PATH)).thenReturn(true); - when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(true); - when(filesystem.lines(V1_CGROUP_FILE_PATH)).thenReturn(Stream.of(line)); + when(filesystem.isReadable(V1_CGROUP_PATH)).thenReturn(true); + when(filesystem.lines(V1_CGROUP_PATH)).thenReturn(Stream.of(line)); - CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + CgroupV1ContainerIdExtractor extractor = new CgroupV1ContainerIdExtractor(filesystem); Optional result = extractor.extractContainerId(); assertThat(result).isEmpty(); } @@ -66,13 +59,12 @@ void invalidContainerIds(String line) throws IOException { @ParameterizedTest @MethodSource("validLines") void validCgroupLines(String line, String expectedContainerId) throws IOException { - when(filesystem.isReadable(V1_CGROUP_FILE_PATH)).thenReturn(true); - when(filesystem.exists(V1_CGROUP_FILE_PATH)).thenReturn(true); - when(filesystem.lines(V1_CGROUP_FILE_PATH)).thenReturn(Stream.of(line)); + when(filesystem.isReadable(V1_CGROUP_PATH)).thenReturn(true); + when(filesystem.lines(V1_CGROUP_PATH)).thenReturn(Stream.of(line)); - CGroupsV1ContainerIdExtractor extractor = new CGroupsV1ContainerIdExtractor(filesystem); + CgroupV1ContainerIdExtractor extractor = new CgroupV1ContainerIdExtractor(filesystem); Optional result = extractor.extractContainerId(); - assertThat(result.get()).isEqualTo(expectedContainerId); + assertThat(result.orElse("fail")).isEqualTo(expectedContainerId); } static Stream validLines() { @@ -106,4 +98,4 @@ static Stream validLines() { "11:devices:/system.slice/containerd.service/kubepods-pod87a18a64_b74a_454a_b10b_a4a36059d0a3.slice:cri-containerd:05c48c82caff3be3d7f1e896981dd410e81487538936914f32b624d168de9db0", "05c48c82caff3be3d7f1e896981dd410e81487538936914f32b624d168de9db0")); } -} \ No newline at end of file +} diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java new file mode 100644 index 000000000000..b9cfa49266ca --- /dev/null +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/CgroupV2ContainerIdExtractorTest.java @@ -0,0 +1,68 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.resources; + +import static io.opentelemetry.instrumentation.resources.CgroupV2ContainerIdExtractor.V2_CGROUP_PATH; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +import java.util.Optional; +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class CgroupV2ContainerIdExtractorTest { + + @Mock ContainerResource.Filesystem filesystem; + + @Test + void fileNotReadable() { + when(filesystem.isReadable(V2_CGROUP_PATH)).thenReturn(false); + CgroupV2ContainerIdExtractor extractor = new CgroupV2ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result).isSameAs(Optional.empty()); + } + + @Test + void extractSuccess() throws Exception { + when(filesystem.isReadable(V2_CGROUP_PATH)).thenReturn(true); + Stream fileContent = getTestFileContent(); + when(filesystem.lines(V2_CGROUP_PATH)).thenReturn(fileContent); + CgroupV2ContainerIdExtractor extractor = new CgroupV2ContainerIdExtractor(filesystem); + Optional result = extractor.extractContainerId(); + assertThat(result.orElse("fail")) + .isEqualTo("dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183"); + } + + private static Stream getTestFileContent() { + return Stream.of( + "456 375 0:143 / / rw,relatime master:175 - overlay overlay rw,lowerdir=/var/lib/docker/overlay2/l/37L57D2IM7MEWLVE2Q2ECNDT67:/var/lib/docker/overlay2/l/46FCA2JFPCSNFGAR5TSYLLNHLK,upperdir=/var/lib/docker/overlay2/4e82c300793d703c19bdf887bfdad8b0354edda884ea27a8a2df89ab292719a4/diff,workdir=/var/lib/docker/overlay2/4e82c300793d703c19bdf887bfdad8b0354edda884ea27a8a2df89ab292719a4/work", + "457 456 0:146 / /proc rw,nosuid,nodev,noexec,relatime - proc proc rw", + "466 456 0:147 / /dev rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", + "467 466 0:148 / /dev/pts rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666", + "468 456 0:149 / /sys ro,nosuid,nodev,noexec,relatime - sysfs sysfs ro", + "469 468 0:30 / /sys/fs/cgroup ro,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw", + "470 466 0:145 / /dev/mqueue rw,nosuid,nodev,noexec,relatime - mqueue mqueue rw", + "471 466 0:150 / /dev/shm rw,nosuid,nodev,noexec,relatime - tmpfs shm rw,size=65536k", + "472 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/resolv.conf /etc/resolv.conf rw,relatime - ext4 /dev/vda1 rw", + "473 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/hostname /etc/hostname rw,relatime - ext4 /dev/vda1 rw", + "474 456 254:1 /docker/containers/dc64b5743252dbaef6e30521c34d6bbd1620c8ce65bdb7bf9e7143b61bb5b183/hosts /etc/hosts rw,relatime - ext4 /dev/vda1 rw", + "376 466 0:148 /0 /dev/console rw,nosuid,noexec,relatime - devpts devpts rw,gid=5,mode=620,ptmxmode=666", + "377 457 0:146 /bus /proc/bus ro,nosuid,nodev,noexec,relatime - proc proc rw", + "378 457 0:146 /fs /proc/fs ro,nosuid,nodev,noexec,relatime - proc proc rw", + "379 457 0:146 /irq /proc/irq ro,nosuid,nodev,noexec,relatime - proc proc rw", + "380 457 0:146 /sys /proc/sys ro,nosuid,nodev,noexec,relatime - proc proc rw", + "381 457 0:146 /sysrq-trigger /proc/sysrq-trigger ro,nosuid,nodev,noexec,relatime - proc proc rw", + "382 457 0:151 / /proc/acpi ro,relatime - tmpfs tmpfs ro", + "383 457 0:147 /null /proc/kcore rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", + "384 457 0:147 /null /proc/keys rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", + "385 457 0:147 /null /proc/timer_list rw,nosuid - tmpfs tmpfs rw,size=65536k,mode=755", + "386 468 0:152 / /sys/firmware ro,relatime - tmpfs tmpfs "); + } +} diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java index 29a0aec2ad60..a0217b1f0a5a 100644 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java @@ -21,10 +21,8 @@ class ContainerResourceTest { public static final String TEST_CONTAINER_ID = "abcdef123123deadbeef"; - @Mock - CGroupsV1ContainerIdExtractor v1; - @Mock - CGroupsV2ContainerIdExtractor v2; + @Mock CgroupV1ContainerIdExtractor v1; + @Mock CgroupV2ContainerIdExtractor v2; @Test void v1Success() { @@ -41,7 +39,6 @@ void v2Success() { ContainerResource containerResource = new ContainerResource(v1, v2); Resource resource = containerResource.buildResource(); Assertions.assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); - } @Test @@ -52,5 +49,4 @@ void bothVersionsFail() { Resource resource = containerResource.buildResource(); assertThat(resource).isSameAs(Resource.empty()); } - } From b6165844461f399550ade49052570b36b3901753 Mon Sep 17 00:00:00 2001 From: Jason Plumb Date: Tue, 15 Nov 2022 08:59:10 -0800 Subject: [PATCH 4/4] code review comments --- .../instrumentation/resources/ContainerResourceTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java index a0217b1f0a5a..0cfc09576648 100644 --- a/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java +++ b/instrumentation/resources/library/src/test/java/io/opentelemetry/instrumentation/resources/ContainerResourceTest.java @@ -7,11 +7,11 @@ import static io.opentelemetry.semconv.resource.attributes.ResourceAttributes.CONTAINER_ID; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import io.opentelemetry.sdk.resources.Resource; import java.util.Optional; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -29,7 +29,8 @@ void v1Success() { when(v1.extractContainerId()).thenReturn(Optional.of(TEST_CONTAINER_ID)); ContainerResource containerResource = new ContainerResource(v1, v2); Resource resource = containerResource.buildResource(); - Assertions.assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); + assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); + verifyNoInteractions(v2); } @Test @@ -38,7 +39,7 @@ void v2Success() { when(v2.extractContainerId()).thenReturn(Optional.of(TEST_CONTAINER_ID)); ContainerResource containerResource = new ContainerResource(v1, v2); Resource resource = containerResource.buildResource(); - Assertions.assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); + assertThat(resource.getAttribute(CONTAINER_ID)).isEqualTo(TEST_CONTAINER_ID); } @Test