go.{mod,sum} bump CDI deps to v1.1.0.

Signed-off-by: Krisztian Litkey <krisztian.litkey@intel.com>
This commit is contained in:
Krisztian Litkey
2025-12-10 14:43:08 +02:00
parent 943fcd91a7
commit 19765c9b7e
8 changed files with 207 additions and 40 deletions

4
go.mod
View File

@@ -87,7 +87,7 @@ require (
k8s.io/client-go v0.34.2
k8s.io/cri-api v0.34.2
k8s.io/klog/v2 v2.130.1
tags.cncf.io/container-device-interface v1.0.2-0.20251114135136-1b24d969689f
tags.cncf.io/container-device-interface v1.1.0
)
require (
@@ -157,5 +157,5 @@ require (
sigs.k8s.io/randfill v1.0.0 // indirect
sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect
sigs.k8s.io/yaml v1.6.0 // indirect
tags.cncf.io/container-device-interface/specs-go v1.0.0 // indirect
tags.cncf.io/container-device-interface/specs-go v1.1.0 // indirect
)

8
go.sum
View File

@@ -582,7 +582,7 @@ sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/
sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
tags.cncf.io/container-device-interface v1.0.2-0.20251114135136-1b24d969689f h1:5kGvyig0u//IrA7XOluYjeElgVHtKkZLoYWjKfBXfls=
tags.cncf.io/container-device-interface v1.0.2-0.20251114135136-1b24d969689f/go.mod h1:kIlIMADdgOVbyLj4ZvEtCvHXqFXqxfbVKKKgBZt8NgQ=
tags.cncf.io/container-device-interface/specs-go v1.0.0 h1:8gLw29hH1ZQP9K1YtAzpvkHCjjyIxHZYzBAvlQ+0vD8=
tags.cncf.io/container-device-interface/specs-go v1.0.0/go.mod h1:u86hoFWqnh3hWz3esofRFKbI261bUlvUfLKGrDhJkgQ=
tags.cncf.io/container-device-interface v1.1.0 h1:RnxNhxF1JOu6CJUVpetTYvrXHdxw9j9jFYgZpI+anSY=
tags.cncf.io/container-device-interface v1.1.0/go.mod h1:76Oj0Yqp9FwTx/pySDc8Bxjpg+VqXfDb50cKAXVJ34Q=
tags.cncf.io/container-device-interface/specs-go v1.1.0 h1:QRZVeAceQM+zTZe12eyfuJuuzp524EKYwhmvLd+h+yQ=
tags.cncf.io/container-device-interface/specs-go v1.1.0/go.mod h1:u86hoFWqnh3hWz3esofRFKbI261bUlvUfLKGrDhJkgQ=

4
vendor/modules.txt vendored
View File

@@ -954,12 +954,12 @@ sigs.k8s.io/structured-merge-diff/v6/value
# sigs.k8s.io/yaml v1.6.0
## explicit; go 1.22
sigs.k8s.io/yaml
# tags.cncf.io/container-device-interface v1.0.2-0.20251114135136-1b24d969689f
# tags.cncf.io/container-device-interface v1.1.0
## explicit; go 1.21
tags.cncf.io/container-device-interface/internal/validation
tags.cncf.io/container-device-interface/internal/validation/k8s
tags.cncf.io/container-device-interface/pkg/cdi
tags.cncf.io/container-device-interface/pkg/parser
# tags.cncf.io/container-device-interface/specs-go v1.0.0
# tags.cncf.io/container-device-interface/specs-go v1.1.0
## explicit; go 1.19
tags.cncf.io/container-device-interface/specs-go

View File

@@ -113,6 +113,14 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
}
}
if len(e.NetDevices) > 0 {
// specgen is currently missing functionality to set Linux NetDevices,
// so we use a locally rolled function for now.
for _, dev := range e.NetDevices {
specgenAddLinuxNetDevice(&specgen, dev.HostInterfaceName, (&LinuxNetDevice{dev}).toOCI())
}
}
if len(e.Mounts) > 0 {
for _, m := range e.Mounts {
specgen.RemoveMount(m.ContainerPath)
@@ -162,6 +170,24 @@ func (e *ContainerEdits) Apply(spec *oci.Spec) error {
return nil
}
func specgenAddLinuxNetDevice(specgen *ocigen.Generator, hostIf string, netDev *oci.LinuxNetDevice) {
if specgen == nil || netDev == nil {
return
}
ensureLinuxNetDevices(specgen.Config)
specgen.Config.Linux.NetDevices[hostIf] = *netDev
}
// Ensure OCI Spec Linux NetDevices map is not nil.
func ensureLinuxNetDevices(spec *oci.Spec) {
if spec.Linux == nil {
spec.Linux = &oci.Linux{}
}
if spec.Linux.NetDevices == nil {
spec.Linux.NetDevices = map[string]oci.LinuxNetDevice{}
}
}
// Validate container edits.
func (e *ContainerEdits) Validate() error {
if e == nil || e.ContainerEdits == nil {
@@ -191,6 +217,9 @@ func (e *ContainerEdits) Validate() error {
return err
}
}
if err := ValidateNetDevices(e.NetDevices); err != nil {
return err
}
return nil
}
@@ -210,6 +239,7 @@ func (e *ContainerEdits) Append(o *ContainerEdits) *ContainerEdits {
e.Env = append(e.Env, o.Env...)
e.DeviceNodes = append(e.DeviceNodes, o.DeviceNodes...)
e.NetDevices = append(e.NetDevices, o.NetDevices...)
e.Hooks = append(e.Hooks, o.Hooks...)
e.Mounts = append(e.Mounts, o.Mounts...)
if o.IntelRdt != nil {
@@ -244,6 +274,9 @@ func (e *ContainerEdits) isEmpty() bool {
if e.IntelRdt != nil {
return false
}
if len(e.NetDevices) > 0 {
return false
}
return true
}
@@ -257,6 +290,49 @@ func ValidateEnv(env []string) error {
return nil
}
// ValidateNetDevices validates the given net devices.
func ValidateNetDevices(devices []*cdi.LinuxNetDevice) error {
var (
hostSeen = map[string]string{}
nameSeen = map[string]string{}
)
for _, dev := range devices {
if err := (&LinuxNetDevice{dev}).Validate(); err != nil {
return err
}
if other, ok := hostSeen[dev.HostInterfaceName]; ok {
return fmt.Errorf("invalid linux net device, duplicate HostInterfaceName %q with names %q and %q",
dev.HostInterfaceName, dev.Name, other)
}
hostSeen[dev.HostInterfaceName] = dev.Name
if other, ok := nameSeen[dev.Name]; ok {
return fmt.Errorf("invalid linux net device, duplicate Name %q with HostInterfaceName %q and %q",
dev.Name, dev.HostInterfaceName, other)
}
nameSeen[dev.Name] = dev.HostInterfaceName
}
return nil
}
// LinuxNetDevice is a CDI Spec LinuxNetDevice wrapper, used for OCI conversion and validating.
type LinuxNetDevice struct {
*cdi.LinuxNetDevice
}
// Validate LinuxNetDevice.
func (d *LinuxNetDevice) Validate() error {
if d.HostInterfaceName == "" {
return errors.New("invalid linux net device, empty HostInterfaceName")
}
if d.Name == "" {
return errors.New("invalid linux net device, empty Name")
}
return nil
}
// DeviceNode is a CDI Spec DeviceNode wrapper, used for validating DeviceNodes.
type DeviceNode struct {
*cdi.DeviceNode

View File

@@ -21,6 +21,7 @@ package cdi
import (
"errors"
"fmt"
"os"
"golang.org/x/sys/unix"
)
@@ -31,16 +32,28 @@ const (
fifoDevice = "p"
)
type deviceInfo struct {
// cgroup properties
deviceType string
major int64
minor int64
// device node properties
fileMode os.FileMode
}
// deviceInfoFromPath takes the path to a device and returns its type,
// major and minor device numbers.
//
// It was adapted from https://github.com/opencontainers/runc/blob/v1.1.9/libcontainer/devices/device_unix.go#L30-L69
func deviceInfoFromPath(path string) (devType string, major, minor int64, _ error) {
func deviceInfoFromPath(path string) (*deviceInfo, error) {
var stat unix.Stat_t
err := unix.Lstat(path, &stat)
if err != nil {
return "", 0, 0, err
return nil, err
}
var devType string
switch stat.Mode & unix.S_IFMT {
case unix.S_IFBLK:
devType = blockDevice
@@ -49,38 +62,71 @@ func deviceInfoFromPath(path string) (devType string, major, minor int64, _ erro
case unix.S_IFIFO:
devType = fifoDevice
default:
return "", 0, 0, errors.New("not a device node")
return nil, errors.New("not a device node")
}
devNumber := uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
return devType, int64(unix.Major(devNumber)), int64(unix.Minor(devNumber)), nil
di := deviceInfo{
deviceType: devType,
major: int64(unix.Major(devNumber)),
minor: int64(unix.Minor(devNumber)),
fileMode: os.FileMode(stat.Mode &^ unix.S_IFMT),
}
return &di, nil
}
// fillMissingInfo fills in missing mandatory attributes from the host device.
func (d *DeviceNode) fillMissingInfo() error {
hasMinimalSpecification := d.Type != "" && (d.Major != 0 || d.Type == fifoDevice)
// Ensure that the host path and the container path match.
if d.HostPath == "" {
d.HostPath = d.Path
}
if d.Type != "" && (d.Major != 0 || d.Type == "p") {
// Try to extract the device info from the host path.
di, err := deviceInfoFromPath(d.HostPath)
if err != nil {
// The error is only considered fatal if the device is not already
// minimally specified since it is allowed for a device vendor to fully
// specify a device node specification.
if !hasMinimalSpecification {
return fmt.Errorf("failed to stat CDI host device %q: %w", d.HostPath, err)
}
return nil
}
deviceType, major, minor, err := deviceInfoFromPath(d.HostPath)
if err != nil {
return fmt.Errorf("failed to stat CDI host device %q: %w", d.HostPath, err)
// Even for minimally-specified device nodes, we update the file mode if
// required. This is useful for rootless containers where device node
// requests may be treated as bind mounts.
if d.FileMode == nil {
d.FileMode = &di.fileMode
}
// If the device is minimally specified, we make no further updates and
// don't perform additional checks.
if hasMinimalSpecification {
return nil
}
if d.Type == "" {
d.Type = deviceType
} else {
if d.Type != deviceType {
return fmt.Errorf("CDI device (%q, %q), host type mismatch (%s, %s)",
d.Path, d.HostPath, d.Type, deviceType)
}
d.Type = di.deviceType
}
if d.Major == 0 && d.Type != "p" {
d.Major = major
d.Minor = minor
if d.Type != di.deviceType {
return fmt.Errorf("CDI device (%q, %q), host type mismatch (%s, %s)",
d.Path, d.HostPath, d.Type, di.deviceType)
}
// For a fifoDevice, we do not update the major and minor number.
if d.Type == fifoDevice {
return nil
}
// Update the major and minor number for the device node if required.
if d.Major == 0 {
d.Major = di.major
d.Minor = di.minor
}
return nil

View File

@@ -56,8 +56,17 @@ func (d *DeviceNode) toOCI() spec.LinuxDevice {
// toOCI returns the opencontainers runtime Spec LinuxIntelRdt for this IntelRdt config.
func (i *IntelRdt) toOCI() *spec.LinuxIntelRdt {
return &spec.LinuxIntelRdt{
ClosID: i.ClosID,
L3CacheSchema: i.L3CacheSchema,
MemBwSchema: i.MemBwSchema,
ClosID: i.ClosID,
L3CacheSchema: i.L3CacheSchema,
MemBwSchema: i.MemBwSchema,
Schemata: i.Schemata,
EnableMonitoring: i.EnableMonitoring,
}
}
// toOCI returns the opencontainers runtime Spec LinuxNetDevice for this LinuxNetDevice.
func (d *LinuxNetDevice) toOCI() *spec.LinuxNetDevice {
return &spec.LinuxNetDevice{
Name: d.Name,
}
}

View File

@@ -24,12 +24,13 @@ type Device struct {
// ContainerEdits are edits a container runtime must make to the OCI spec to expose the device.
type ContainerEdits struct {
Env []string `json:"env,omitempty" yaml:"env,omitempty"`
DeviceNodes []*DeviceNode `json:"deviceNodes,omitempty" yaml:"deviceNodes,omitempty"`
Hooks []*Hook `json:"hooks,omitempty" yaml:"hooks,omitempty"`
Mounts []*Mount `json:"mounts,omitempty" yaml:"mounts,omitempty"`
IntelRdt *IntelRdt `json:"intelRdt,omitempty" yaml:"intelRdt,omitempty"` // Added in v0.7.0
AdditionalGIDs []uint32 `json:"additionalGids,omitempty" yaml:"additionalGids,omitempty"` // Added in v0.7.0
Env []string `json:"env,omitempty" yaml:"env,omitempty"`
DeviceNodes []*DeviceNode `json:"deviceNodes,omitempty" yaml:"deviceNodes,omitempty"`
NetDevices []*LinuxNetDevice `json:"netDevices,omitempty" yaml:"netDevices,omitempty"` // Added in v1.1.0
Hooks []*Hook `json:"hooks,omitempty" yaml:"hooks,omitempty"`
Mounts []*Mount `json:"mounts,omitempty" yaml:"mounts,omitempty"`
IntelRdt *IntelRdt `json:"intelRdt,omitempty" yaml:"intelRdt,omitempty"` // Added in v0.7.0
AdditionalGIDs []uint32 `json:"additionalGids,omitempty" yaml:"additionalGids,omitempty"` // Added in v0.7.0
}
// DeviceNode represents a device node that needs to be added to the OCI spec.
@@ -64,9 +65,15 @@ type Hook struct {
// IntelRdt describes the Linux IntelRdt parameters to set in the OCI spec.
type IntelRdt struct {
ClosID string `json:"closID,omitempty" yaml:"closID,omitempty"`
L3CacheSchema string `json:"l3CacheSchema,omitempty" yaml:"l3CacheSchema,omitempty"`
MemBwSchema string `json:"memBwSchema,omitempty" yaml:"memBwSchema,omitempty"`
EnableCMT bool `json:"enableCMT,omitempty" yaml:"enableCMT,omitempty"`
EnableMBM bool `json:"enableMBM,omitempty" yaml:"enableMBM,omitempty"`
ClosID string `json:"closID,omitempty" yaml:"closID,omitempty"`
L3CacheSchema string `json:"l3CacheSchema,omitempty" yaml:"l3CacheSchema,omitempty"`
MemBwSchema string `json:"memBwSchema,omitempty" yaml:"memBwSchema,omitempty"`
Schemata []string `json:"schemata,omitempty" yaml:"schemata,omitempty"` // Added in v1.1.0.
EnableMonitoring bool `json:"enableMonitoring,omitempty" yaml:"enableMonitoring,omitempty"` // Added in v1.1.0.
}
// LinuxNetDevice represents an OCI LinuxNetDevice to be added to the OCI Spec.
type LinuxNetDevice struct {
HostInterfaceName string `json:"hostInterfaceName" yaml:"hostInterfaceName"`
Name string `json:"name" yaml:"name"`
}

View File

@@ -25,7 +25,7 @@ import (
const (
// CurrentVersion is the current version of the Spec.
CurrentVersion = "1.0.0"
CurrentVersion = "1.1.0"
// vCurrent is the current version as a semver-comparable type
vCurrent version = "v" + CurrentVersion
@@ -40,6 +40,7 @@ const (
v070 version = "v0.7.0"
v080 version = "v0.8.0"
v100 version = "v1.0.0"
v110 version = "v1.1.0"
// vEarliest is the earliest supported version of the CDI specification
vEarliest version = v030
@@ -58,6 +59,7 @@ var validSpecVersions = requiredVersionMap{
v070: requiresV070,
v080: requiresV080,
v100: requiresV100,
v110: requiresV110,
}
// ValidateVersion checks whether the specified spec version is valid.
@@ -140,6 +142,33 @@ func (r requiredVersionMap) requiredVersion(spec *Spec) version {
return minVersion
}
// requiresV110 returns true if the spec uses v1.1.0 features.
func requiresV110(spec *Spec) bool {
if i := spec.ContainerEdits.IntelRdt; i != nil {
if i.Schemata != nil || i.EnableMonitoring {
return true
}
}
if len(spec.ContainerEdits.NetDevices) > 0 {
return true
}
for _, dev := range spec.Devices {
if i := dev.ContainerEdits.IntelRdt; i != nil {
if i.Schemata != nil || i.EnableMonitoring {
return true
}
}
if len(dev.ContainerEdits.NetDevices) > 0 {
return true
}
}
return false
}
// requiresV100 returns true if the spec uses v1.0.0 features.
// Since the v1.0.0 spec bump was due to moving the minimum version checks to
// the spec package, there are no explicit spec changes.