Skip to content

Commit afd934b

Browse files
committed
Remove redundant CDI annotations
When generating CDI specs for coherent and noncoherent devices, we include CDI device annotations. This increases the minimum CDI spec version to v0.6.0 which is not as widely supported as v0.5.0 or v0.3.0. This change removes these annotations after splitting the generated specs to produce coherent and/or non-coherent specs. Signed-off-by: Evan Lezar <[email protected]>
1 parent 77e8f4b commit afd934b

File tree

2 files changed

+170
-3
lines changed

2 files changed

+170
-3
lines changed

cmd/nvidia-ctk/cdi/generate/generate.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,15 +447,22 @@ type deviceSpecs []specs.Device
447447
func (d deviceSpecs) splitOnAnnotation(key string) map[string][]specs.Device {
448448
splitSpecs := make(map[string][]specs.Device)
449449

450+
var specsToRemoveAnnotations []*specs.Device
450451
for _, deviceSpec := range d {
451-
if len(deviceSpec.Annotations) == 0 {
452-
continue
453-
}
454452
value, ok := deviceSpec.Annotations[key]
455453
if !ok {
456454
continue
457455
}
458456
splitSpecs[key+"="+value] = append(splitSpecs[key+"="+value], deviceSpec)
457+
specsToRemoveAnnotations = append(specsToRemoveAnnotations, &deviceSpec)
458+
}
459+
460+
// We also remove the annotations that were used to split the devices:
461+
for _, deviceSpec := range specsToRemoveAnnotations {
462+
if _, ok := deviceSpec.Annotations[key]; !ok {
463+
continue
464+
}
465+
delete(deviceSpec.Annotations, key)
459466
}
460467

461468
return splitSpecs

cmd/nvidia-ctk/cdi/generate/generate_test.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/NVIDIA/go-nvml/pkg/nvml/mock/dgxa100"
2727
testlog "github.com/sirupsen/logrus/hooks/test"
2828
"github.com/stretchr/testify/require"
29+
"tags.cncf.io/container-device-interface/specs-go"
2930

3031
"github.com/NVIDIA/nvidia-container-toolkit/internal/test"
3132
"github.com/NVIDIA/nvidia-container-toolkit/pkg/nvcdi"
@@ -491,3 +492,162 @@ containerEdits:
491492
})
492493
}
493494
}
495+
496+
func TestSplitOnAnnotation(t *testing.T) {
497+
testCases := []struct {
498+
description string
499+
input deviceSpecs
500+
annotation string
501+
expectedInputPostSplit deviceSpecs
502+
expectedOutput map[string][]specs.Device
503+
}{
504+
{
505+
description: "non-matching annotation",
506+
input: deviceSpecs{
507+
specs.Device{
508+
Name: "foo",
509+
Annotations: map[string]string{
510+
"key": "value",
511+
},
512+
},
513+
},
514+
annotation: "not-key",
515+
expectedInputPostSplit: deviceSpecs{
516+
specs.Device{
517+
Name: "foo",
518+
Annotations: map[string]string{
519+
"key": "value",
520+
},
521+
},
522+
},
523+
expectedOutput: map[string][]specs.Device{},
524+
},
525+
{
526+
description: "single annotation present",
527+
input: deviceSpecs{
528+
specs.Device{
529+
Name: "foo",
530+
Annotations: map[string]string{
531+
"key": "value",
532+
},
533+
},
534+
},
535+
annotation: "key",
536+
expectedInputPostSplit: deviceSpecs{
537+
specs.Device{
538+
Name: "foo",
539+
Annotations: map[string]string{},
540+
},
541+
},
542+
expectedOutput: map[string][]specs.Device{
543+
"key=value": {
544+
{
545+
Name: "foo",
546+
Annotations: map[string]string{},
547+
},
548+
},
549+
},
550+
},
551+
{
552+
description: "non-matching annotations are not removed",
553+
input: deviceSpecs{
554+
specs.Device{
555+
Name: "foo",
556+
Annotations: map[string]string{
557+
"key": "value",
558+
"another": "foo",
559+
},
560+
},
561+
},
562+
annotation: "key",
563+
expectedInputPostSplit: deviceSpecs{
564+
specs.Device{
565+
Name: "foo",
566+
Annotations: map[string]string{"another": "foo"},
567+
},
568+
},
569+
expectedOutput: map[string][]specs.Device{
570+
"key=value": {
571+
{
572+
Name: "foo",
573+
Annotations: map[string]string{"another": "foo"},
574+
},
575+
},
576+
},
577+
},
578+
{
579+
description: "duplicated annotations different names",
580+
input: func() deviceSpecs {
581+
annotations := map[string]string{
582+
"key": "value",
583+
}
584+
return deviceSpecs{
585+
{Name: "0", Annotations: annotations},
586+
{Name: "first", Annotations: annotations},
587+
}
588+
}(),
589+
annotation: "key",
590+
expectedInputPostSplit: deviceSpecs{
591+
specs.Device{Name: "0", Annotations: map[string]string{}},
592+
specs.Device{Name: "first", Annotations: map[string]string{}},
593+
},
594+
expectedOutput: map[string][]specs.Device{
595+
"key=value": {
596+
{Name: "0", Annotations: map[string]string{}},
597+
{Name: "first", Annotations: map[string]string{}},
598+
},
599+
},
600+
},
601+
{
602+
description: "annotation with different values",
603+
input: deviceSpecs{
604+
specs.Device{
605+
Name: "foo",
606+
Annotations: map[string]string{
607+
"key": "value",
608+
},
609+
},
610+
specs.Device{
611+
Name: "bar",
612+
Annotations: map[string]string{
613+
"key": "another",
614+
},
615+
},
616+
},
617+
annotation: "key",
618+
expectedInputPostSplit: deviceSpecs{
619+
specs.Device{
620+
Name: "foo",
621+
Annotations: map[string]string{},
622+
},
623+
specs.Device{
624+
Name: "bar",
625+
Annotations: map[string]string{},
626+
},
627+
},
628+
expectedOutput: map[string][]specs.Device{
629+
"key=value": {
630+
{
631+
Name: "foo",
632+
Annotations: map[string]string{},
633+
},
634+
},
635+
"key=another": {
636+
{
637+
Name: "bar",
638+
Annotations: map[string]string{},
639+
},
640+
},
641+
},
642+
},
643+
}
644+
645+
for _, tc := range testCases {
646+
t.Run(tc.description, func(t *testing.T) {
647+
result := tc.input.splitOnAnnotation(tc.annotation)
648+
649+
require.EqualValues(t, tc.expectedOutput, result)
650+
require.EqualValues(t, tc.expectedInputPostSplit, tc.input)
651+
})
652+
}
653+
}

0 commit comments

Comments
 (0)