diff --git a/internal/edits/device.go b/internal/edits/device.go index 8f5418de..72e6b06e 100644 --- a/internal/edits/device.go +++ b/internal/edits/device.go @@ -42,8 +42,17 @@ func (d device) toEdits() (*cdi.ContainerEdits, error) { // toSpec converts a discovered Device to a CDI Spec Device. Note // that missing info is filled in when edits are applied by querying the Device node. func (d device) toSpec() (*specs.DeviceNode, error) { + // The HostPath field was added in the v0.5.0 CDI specification. + // The cdi package uses strict unmarshalling when loading specs from file causing failures for + // unexpected fields. + // Since the behaviour for HostPath == "" and HostPath == Path are equivalent, we clear HostPath + // if it is equal to Path to ensure compatibility with the widest range of specs. + hostPath := d.HostPath + if hostPath == d.Path { + hostPath = "" + } s := specs.DeviceNode{ - HostPath: d.HostPath, + HostPath: hostPath, Path: d.Path, } diff --git a/internal/edits/device_test.go b/internal/edits/device_test.go new file mode 100644 index 00000000..44c35098 --- /dev/null +++ b/internal/edits/device_test.go @@ -0,0 +1,69 @@ +/** +# Copyright (c) NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +**/ + +package edits + +import ( + "fmt" + "testing" + + "github.com/NVIDIA/nvidia-container-toolkit/internal/discover" + "github.com/container-orchestrated-devices/container-device-interface/specs-go" + "github.com/stretchr/testify/require" +) + +func TestDeviceToSpec(t *testing.T) { + testCases := []struct { + device discover.Device + expected *specs.DeviceNode + }{ + { + device: discover.Device{ + Path: "/foo", + }, + expected: &specs.DeviceNode{ + Path: "/foo", + }, + }, + { + device: discover.Device{ + Path: "/foo", + HostPath: "/foo", + }, + expected: &specs.DeviceNode{ + Path: "/foo", + }, + }, + { + device: discover.Device{ + Path: "/foo", + HostPath: "/not/foo", + }, + expected: &specs.DeviceNode{ + Path: "/foo", + HostPath: "/not/foo", + }, + }, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + spec, err := device(tc.device).toSpec() + require.NoError(t, err) + require.EqualValues(t, tc.expected, spec) + }) + } +}