Repository: elastic/go-sysinfo
Pull request #71 (2019-11-01 06:34:48)

Recognize systemd based cgroups
Systemd based cgroups like how containerd works creates entries with <namespace>.slice. In the case of kubernetes pods it would be `kubepods.slice`. This PR looks for `.slice` in addition to Docker and LXC.

andrewkroh: LGTM. Could you please add a test case for .slice in https://github.com/elastic/go-sysinfo/blob/64e7342b68af91c08e51a1570d690b5e23156ff3/providers/linux/container_test.go#L83.
vjsamuel: @andrewkroh done

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 624371c..d295b33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added
 
+- Added detection of systemd cgroups to the `IsContainerized` check. [#71](https://github.com/elastic/go-sysinfo/pull/71)
+
 ### Changed
 
 ### Deprecated
diff --git a/providers/linux/container.go b/providers/linux/container.go
index 6081e0c..3cf0628 100644
--- a/providers/linux/container.go
+++ b/providers/linux/container.go
@@ -49,7 +49,7 @@ func isContainerizedCgroup(data []byte) (bool, error) {
 
 		// Following a suggestion on Stack Overflow on how to detect
 		// being inside a container: https://stackoverflow.com/a/20012536/235203
-		if bytes.Contains(line, []byte("docker")) || bytes.Contains(line, []byte("lxc")) {
+		if bytes.Contains(line, []byte("docker")) || bytes.Contains(line, []byte(".slice")) || bytes.Contains(line, []byte("lxc")) {
 			return true, nil
 		}
 	}
diff --git a/providers/linux/machineid.go b/providers/linux/machineid.go
index a84d085..7a6b8a7 100644
--- a/providers/linux/machineid.go
+++ b/providers/linux/machineid.go
@@ -27,11 +27,9 @@ import (
 	"github.com/elastic/go-sysinfo/types"
 )
 
-var (
-	// Possible (current and historic) locations of the machine-id file.
-	// These will be searched in order.
-	machineIDFiles = []string{"/etc/machine-id", "/var/lib/dbus/machine-id", "/var/db/dbus/machine-id"}
-)
+// Possible (current and historic) locations of the machine-id file.
+// These will be searched in order.
+var machineIDFiles = []string{"/etc/machine-id", "/var/lib/dbus/machine-id", "/var/db/dbus/machine-id"}
 
 func MachineID() (string, error) {
 	var contents []byte


Test patch:
diff --git a/providers/linux/container_test.go b/providers/linux/container_test.go
index 4f05293..86382ed 100644
--- a/providers/linux/container_test.go
+++ b/providers/linux/container_test.go
@@ -78,36 +78,57 @@ const lxcCgroup = `9:hugetlb:/lxc/81438f4655cd771c425607dcf7654f4dc03c073c0123ed
 2:cpu:/lxc/81438f4655cd771c425607dcf7654f4dc03c073c0123edc45fcfad28132e8c60
 1:cpuset:/lxc/81438f4655cd771c425607dcf7654f4dc03c073c0123edc45fcfad28132e8c60`
 
+const systemdCgroup = `12:hugetlb:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+11:perf_event:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+10:pids:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+9:cpu,cpuacct:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+8:cpuset:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+7:memory:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+6:freezer:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+5:rdma:/
+4:net_cls,net_prio:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+3:devices:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+2:blkio:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1
+1:name=systemd:/kubepods.slice/kubepods-podc1281d63_01ab_11ea_ba0a_3cfdfe55a1c0.slice/e2b68f8a6e227921b236c686a243e8ff50f561f493d401da7ac3f8cae28f08b1`
+
 const emptyCgroup = ``
 
 func TestIsContainerized(t *testing.T) {
-	containerized, err := isContainerizedCgroup([]byte(nonContainerizedCgroup))
-	if err != nil {
-		t.Fatal(err)
-	}
-	assert.False(t, containerized)
-
-	containerized, err = isContainerizedCgroup([]byte(containerCgroup))
-	if err != nil {
-		t.Fatal(err)
-	}
-	assert.True(t, containerized)
-
-	containerized, err = isContainerizedCgroup([]byte(containerHostPIDNamespaceCgroup))
-	if err != nil {
-		t.Fatal(err)
-	}
-	assert.False(t, containerized)
-
-	containerized, err = isContainerizedCgroup([]byte(lxcCgroup))
-	if err != nil {
-		t.Fatal(err)
+	tests := []struct {
+		cgroupStr     string
+		containerized bool
+	}{
+		{
+			cgroupStr:     nonContainerizedCgroup,
+			containerized: false,
+		},
+		{
+			cgroupStr:     containerCgroup,
+			containerized: true,
+		},
+		{
+			cgroupStr:     containerHostPIDNamespaceCgroup,
+			containerized: false,
+		},
+		{
+			cgroupStr:     lxcCgroup,
+			containerized: true,
+		},
+		{
+			cgroupStr:     systemdCgroup,
+			containerized: true,
+		},
+		{
+			cgroupStr:     emptyCgroup,
+			containerized: false,
+		},
 	}
-	assert.True(t, containerized)
 
-	containerized, err = isContainerizedCgroup([]byte(emptyCgroup))
-	if err != nil {
-		t.Fatal(err)
+	for _, test := range tests {
+		containerized, err := isContainerizedCgroup([]byte(test.cgroupStr))
+		if err != nil {
+			t.Fatal(err)
+		}
+		assert.Equal(t, test.containerized, containerized)
 	}
-	assert.False(t, containerized)
 }