From f027da4d6415d8c440c8d9680e5db5ae95b747a1 Mon Sep 17 00:00:00 2001 From: Wassim DHIF Date: Wed, 17 Jan 2024 17:27:45 +0100 Subject: [PATCH] Add controller priority unittest Signed-off-by: Wassim DHIF --- datadog/dogstatsd/container.py | 5 ++-- tests/unit/dogstatsd/test_container.py | 41 ++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/datadog/dogstatsd/container.py b/datadog/dogstatsd/container.py index 94b5be2b6..93bb819b5 100644 --- a/datadog/dogstatsd/container.py +++ b/datadog/dogstatsd/container.py @@ -33,7 +33,7 @@ class Cgroup(object): CGROUP_NS_PATH = "/proc/self/ns/cgroup" # path to the cgroup namespace file. CGROUPV1_BASE_CONTROLLER = "memory" # controller used to identify the container-id in cgroup v1 (memory). CGROUPV2_BASE_CONTROLLER = "" # controller used to identify the container-id in cgroup v2. - HOST_CGROUP_NAMESPACE_INODE = "0xEFFFFFFBL" # inode of the host cgroup namespace. + HOST_CGROUP_NAMESPACE_INODE = 0xEFFFFFFB # inode of the host cgroup namespace. UUID_SOURCE = r"[0-9a-f]{8}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{4}[-_][0-9a-f]{12}" CONTAINER_SOURCE = r"[0-9a-f]{64}" @@ -105,6 +105,7 @@ def _get_cgroup_from_inode(self): ) inode = os.stat(inode_path).st_ino # 0 is not a valid inode. 1 is a bad block inode and 2 is the root of a filesystem. - return "in-{0}".format(inode) if int(inode) > 2 else None + if inode > 2: + return "in-{0}".format(inode) return None diff --git a/tests/unit/dogstatsd/test_container.py b/tests/unit/dogstatsd/test_container.py index 3cf3da753..2d0ceeea1 100644 --- a/tests/unit/dogstatsd/test_container.py +++ b/tests/unit/dogstatsd/test_container.py @@ -130,7 +130,7 @@ def test_container_id_from_cgroup(file_contents, expected_container_id): if file_contents is None: mock_open.side_effect = IOError - with mock.patch("os.stat", mock.MagicMock(return_value=mock.Mock(st_ino="0xEFFFFFFBL"))): + with mock.patch("os.stat", mock.MagicMock(return_value=mock.Mock(st_ino=0xEFFFFFFB))): reader = Cgroup() assert expected_container_id == reader.container_id @@ -140,7 +140,44 @@ def test_container_id_from_cgroup(file_contents, expected_container_id): def test_container_id_inode(): """Test that the inode is returned when the container ID cannot be found.""" with mock.patch("datadog.dogstatsd.container.open", mock.mock_open(read_data="0::/")) as mock_open: - with mock.patch("os.stat", mock.MagicMock(return_value=mock.Mock(st_ino="1234"))): + with mock.patch("os.stat", mock.MagicMock(return_value=mock.Mock(st_ino=1234))): + reader = Cgroup() + assert reader.container_id == "in-1234" + mock_open.assert_called_once_with("/proc/self/cgroup", mode="r") + + cgroupv1_priority = """ +12:cpu,cpuacct:/ +11:hugetlb:/ +10:devices:/ +9:rdma:/ +8:net_cls,net_prio:/ +7:memory:/ +6:cpuset:/ +5:pids:/ +4:freezer:/ +3:perf_event:/ +2:blkio:/ +1:name=systemd:/ +0::/ +""" + + memory_priority_valid = False + + def inode_stat_mock(path): + nonlocal memory_priority_valid + if not memory_priority_valid: + # Priority is given to the cgroupv1 controller. + assert path == "/sys/fs/cgroup/memory/" + memory_priority_valid = True + + # The cgroupv1 controller is mounted on inode 0. This will cause a fallback to the cgroupv2 controller. + if path == "/sys/fs/cgroup/memory/": + return mock.Mock(st_ino=0) + elif path == "/sys/fs/cgroup/": + return mock.Mock(st_ino=1234) + + with mock.patch("datadog.dogstatsd.container.open", mock.mock_open(read_data=cgroupv1_priority)) as mock_open: + with mock.patch("os.stat", mock.MagicMock(side_effect=inode_stat_mock)): reader = Cgroup() assert reader.container_id == "in-1234" mock_open.assert_called_once_with("/proc/self/cgroup", mode="r")