Plumb CRI Devices through to OCI WindowsDevices
There's two mappings of hostpath to IDType and ID in the wild: - dockershim and dockerd-cri (implicitly via docker) use class/ID -- The only supported IDType in Docker is 'class'. -- https://github.com/aarnaud/k8s-directx-device-plugin generates this form - https://github.com/jterry75/cri (windows_port branch) uses IDType://ID -- hcsshim's CRI test suite generates this form `://` is much more easily distinguishable, so I've gone with that one as the generic separator, with `class/` as a special-case. Signed-off-by: Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
This commit is contained in:
@@ -1367,3 +1367,17 @@ func tryReadonlyMounts(mounts []mount.Mount) []mount.Mount {
|
||||
}
|
||||
return mounts
|
||||
}
|
||||
|
||||
// WithWindowsDevice adds a device exposed to a Windows (WCOW or LCOW) Container
|
||||
func WithWindowsDevice(idType, id string) SpecOpts {
|
||||
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||
if idType == "" {
|
||||
return errors.New("missing idType")
|
||||
}
|
||||
if s.Windows == nil {
|
||||
s.Windows = &specs.Windows{}
|
||||
}
|
||||
s.Windows.Devices = append(s.Windows.Devices, specs.WindowsDevice{IDType: idType, ID: id})
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@@ -704,3 +707,75 @@ func TestWithoutMounts(t *testing.T) {
|
||||
t.Fatalf("expected %+v, got %+v", expected, s.Mounts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithWindowsDevice(t *testing.T) {
|
||||
testcases := []struct {
|
||||
name string
|
||||
idType string
|
||||
id string
|
||||
|
||||
expectError bool
|
||||
expectedWindowsDevices []specs.WindowsDevice
|
||||
}{
|
||||
{
|
||||
name: "empty_idType_and_id",
|
||||
idType: "",
|
||||
id: "",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty_idType",
|
||||
idType: "",
|
||||
id: "5B45201D-F2F2-4F3B-85BB-30FF1F953599",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "empty_id",
|
||||
idType: "class",
|
||||
id: "",
|
||||
|
||||
expectError: false,
|
||||
expectedWindowsDevices: []specs.WindowsDevice{{ID: "", IDType: "class"}},
|
||||
},
|
||||
{
|
||||
name: "idType_and_id",
|
||||
idType: "class",
|
||||
id: "5B45201D-F2F2-4F3B-85BB-30FF1F953599",
|
||||
|
||||
expectError: false,
|
||||
expectedWindowsDevices: []specs.WindowsDevice{{ID: "5B45201D-F2F2-4F3B-85BB-30FF1F953599", IDType: "class"}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
spec := Spec{
|
||||
Version: specs.Version,
|
||||
Root: &specs.Root{},
|
||||
Windows: &specs.Windows{},
|
||||
}
|
||||
|
||||
opts := []SpecOpts{
|
||||
WithWindowsDevice(tc.idType, tc.id),
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
if err := opt(nil, nil, nil, &spec); err != nil {
|
||||
if tc.expectError {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(tc.expectedWindowsDevices) != 0 {
|
||||
require.NotNil(t, spec.Windows)
|
||||
require.NotNil(t, spec.Windows.Devices)
|
||||
assert.ElementsMatch(t, spec.Windows.Devices, tc.expectedWindowsDevices)
|
||||
} else if spec.Windows != nil && spec.Windows.Devices != nil {
|
||||
assert.ElementsMatch(t, spec.Windows.Devices, tc.expectedWindowsDevices)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user