package clistat import ( "bufio" "bytes" "os" "github.com/spf13/afero" "golang.org/x/xerrors" ) const ( procMounts = "/proc/mounts" procOneCgroup = "/proc/1/cgroup" kubernetesDefaultServiceAccountToken = "/var/run/secrets/kubernetes.io/serviceaccount/token" //nolint:gosec ) // IsContainerized returns whether the host is containerized. // This is adapted from https://github.com/elastic/go-sysinfo/tree/main/providers/linux/container.go#L31 // with modifications to support Sysbox containers. // On non-Linux platforms, it always returns false. func IsContainerized(fs afero.Fs) (ok bool, err error) { cgData, err := afero.ReadFile(fs, procOneCgroup) if err != nil { if os.IsNotExist(err) { return false, nil } return false, xerrors.Errorf("read file %s: %w", procOneCgroup, err) } scn := bufio.NewScanner(bytes.NewReader(cgData)) for scn.Scan() { line := scn.Bytes() if bytes.Contains(line, []byte("docker")) || bytes.Contains(line, []byte(".slice")) || bytes.Contains(line, []byte("lxc")) || bytes.Contains(line, []byte("kubepods")) { return true, nil } } // Sometimes the above method of sniffing /proc/1/cgroup isn't reliable. // If a Kubernetes service account token is present, that's // also a good indication that we are in a container. _, err = afero.ReadFile(fs, kubernetesDefaultServiceAccountToken) if err == nil { return true, nil } // Last-ditch effort to detect Sysbox containers. // Check if we have anything mounted as type sysboxfs in /proc/mounts mountsData, err := afero.ReadFile(fs, procMounts) if err != nil { if os.IsNotExist(err) { return false, nil } return false, xerrors.Errorf("read file %s: %w", procMounts, err) } scn = bufio.NewScanner(bytes.NewReader(mountsData)) for scn.Scan() { line := scn.Bytes() if bytes.Contains(line, []byte("sysboxfs")) { return true, nil } } // If we get here, we are _probably_ not running in a container. return false, nil }