Support adding devices by dir

This enables cases where devices exist in a subdirectory of /dev,
particularly where those device names are not portable across machines,
which makes it problematic to specify from a runtime such as cri.

Added this to `ctr` as well so I could test that the code at least
works.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff
2020-12-15 01:28:34 +00:00
parent a1138182d5
commit 7776e5ef2a
8 changed files with 217 additions and 45 deletions

View File

@@ -18,9 +18,14 @@ package oci
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"github.com/containerd/containerd/pkg/testutil"
specs "github.com/opencontainers/runtime-spec/specs-go"
"golang.org/x/sys/unix"
)
func TestAddCaps(t *testing.T) {
@@ -106,3 +111,113 @@ func TestDropCaps(t *testing.T) {
}
}
}
func TestGetDevices(t *testing.T) {
testutil.RequiresRoot(t)
dir, err := ioutil.TempDir("/dev", t.Name())
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
zero := filepath.Join(dir, "zero")
if err := ioutil.WriteFile(zero, nil, 0600); err != nil {
t.Fatal(err)
}
if err := unix.Mount("/dev/zero", zero, "", unix.MS_BIND, ""); err != nil {
t.Fatal(err)
}
defer unix.Unmount(filepath.Join(dir, "zero"), unix.MNT_DETACH)
t.Run("single device", func(t *testing.T) {
t.Run("no container path", func(t *testing.T) {
devices, err := getDevices(dir, "")
if err != nil {
t.Fatal(err)
}
if len(devices) != 1 {
t.Fatalf("expected one device %v", devices)
}
if devices[0].Path != zero {
t.Fatalf("got unexpected device path %s", devices[0].Path)
}
})
t.Run("with container path", func(t *testing.T) {
newPath := "/dev/testNew"
devices, err := getDevices(dir, newPath)
if err != nil {
t.Fatal(err)
}
if len(devices) != 1 {
t.Fatalf("expected one device %v", devices)
}
if devices[0].Path != filepath.Join(newPath, "zero") {
t.Fatalf("got unexpected device path %s", devices[0].Path)
}
})
})
t.Run("With symlink in dir", func(t *testing.T) {
if err := os.Symlink("/dev/zero", filepath.Join(dir, "zerosym")); err != nil {
t.Fatal(err)
}
devices, err := getDevices(dir, "")
if err != nil {
t.Fatal(err)
}
if len(devices) != 1 {
t.Fatalf("expected one device %v", devices)
}
if devices[0].Path != filepath.Join(dir, "zero") {
t.Fatalf("got unexpected device path, expected %q, got %q", filepath.Join(dir, "zero"), devices[0].Path)
}
})
t.Run("No devices", func(t *testing.T) {
dir := dir + "2"
if err := os.MkdirAll(dir, 0755); err != nil {
t.Fatal(err)
}
defer os.RemoveAll(dir)
t.Run("empty dir", func(T *testing.T) {
devices, err := getDevices(dir, "")
if err != nil {
t.Fatal(err)
}
if len(devices) != 0 {
t.Fatalf("expected no devices, got %+v", devices)
}
})
t.Run("symlink to device in dir", func(t *testing.T) {
if err := os.Symlink("/dev/zero", filepath.Join(dir, "zerosym")); err != nil {
t.Fatal(err)
}
defer os.Remove(filepath.Join(dir, "zerosym"))
devices, err := getDevices(dir, "")
if err != nil {
t.Fatal(err)
}
if len(devices) != 0 {
t.Fatalf("expected no devices, got %+v", devices)
}
})
t.Run("regular file in dir", func(t *testing.T) {
if err := ioutil.WriteFile(filepath.Join(dir, "somefile"), []byte("hello"), 0600); err != nil {
t.Fatal(err)
}
defer os.Remove(filepath.Join(dir, "somefile"))
devices, err := getDevices(dir, "")
if err != nil {
t.Fatal(err)
}
if len(devices) != 0 {
t.Fatalf("expected no devices, got %+v", devices)
}
})
})
}