diff --git a/go.mod b/go.mod index e8b034eb..cf53907c 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( golang.org/x/mod v0.24.0 golang.org/x/sys v0.31.0 tags.cncf.io/container-device-interface v0.8.1 - tags.cncf.io/container-device-interface/specs-go v0.8.0 + tags.cncf.io/container-device-interface/specs-go v1.0.0 ) require ( diff --git a/go.sum b/go.sum index 7e5c8b3f..a015f6b5 100644 --- a/go.sum +++ b/go.sum @@ -94,5 +94,5 @@ sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= tags.cncf.io/container-device-interface v0.8.1 h1:c0jN4Mt6781jD67NdPajmZlD1qrqQyov/Xfoab37lj0= tags.cncf.io/container-device-interface v0.8.1/go.mod h1:Apb7N4VdILW0EVdEMRYXIDVRZfNJZ+kmEUss2kRRQ6Y= -tags.cncf.io/container-device-interface/specs-go v0.8.0 h1:QYGFzGxvYK/ZLMrjhvY0RjpUavIn4KcmRmVP/JjdBTA= -tags.cncf.io/container-device-interface/specs-go v0.8.0/go.mod h1:BhJIkjjPh4qpys+qm4DAYtUyryaTDg9zris+AczXyws= +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= diff --git a/vendor/modules.txt b/vendor/modules.txt index f0765bc1..c18bec5e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -100,6 +100,6 @@ 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 v0.8.0 +# tags.cncf.io/container-device-interface/specs-go v1.0.0 ## explicit; go 1.19 tags.cncf.io/container-device-interface/specs-go diff --git a/vendor/tags.cncf.io/container-device-interface/specs-go/config.go b/vendor/tags.cncf.io/container-device-interface/specs-go/config.go index d6d6302f..f28657b8 100644 --- a/vendor/tags.cncf.io/container-device-interface/specs-go/config.go +++ b/vendor/tags.cncf.io/container-device-interface/specs-go/config.go @@ -2,72 +2,71 @@ package specs import "os" -// CurrentVersion is the current version of the Spec. -const CurrentVersion = "0.8.0" - // Spec is the base configuration for CDI type Spec struct { - Version string `json:"cdiVersion"` - Kind string `json:"kind"` + Version string `json:"cdiVersion" yaml:"cdiVersion"` + Kind string `json:"kind" yaml:"kind"` // Annotations add meta information per CDI spec. Note these are CDI-specific and do not affect container metadata. - Annotations map[string]string `json:"annotations,omitempty"` - Devices []Device `json:"devices"` - ContainerEdits ContainerEdits `json:"containerEdits,omitempty"` + // Added in v0.6.0. + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + Devices []Device `json:"devices" yaml:"devices"` + ContainerEdits ContainerEdits `json:"containerEdits,omitempty" yaml:"containerEdits,omitempty"` } // Device is a "Device" a container runtime can add to a container type Device struct { - Name string `json:"name"` + Name string `json:"name" yaml:"name"` // Annotations add meta information per device. Note these are CDI-specific and do not affect container metadata. - Annotations map[string]string `json:"annotations,omitempty"` - ContainerEdits ContainerEdits `json:"containerEdits"` + // Added in v0.6.0. + Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` + ContainerEdits ContainerEdits `json:"containerEdits" yaml:"containerEdits"` } // ContainerEdits are edits a container runtime must make to the OCI spec to expose the device. type ContainerEdits struct { - Env []string `json:"env,omitempty"` - DeviceNodes []*DeviceNode `json:"deviceNodes,omitempty"` - Hooks []*Hook `json:"hooks,omitempty"` - Mounts []*Mount `json:"mounts,omitempty"` - IntelRdt *IntelRdt `json:"intelRdt,omitempty"` - AdditionalGIDs []uint32 `json:"additionalGids,omitempty"` + 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 } // DeviceNode represents a device node that needs to be added to the OCI spec. type DeviceNode struct { - Path string `json:"path"` - HostPath string `json:"hostPath,omitempty"` - Type string `json:"type,omitempty"` - Major int64 `json:"major,omitempty"` - Minor int64 `json:"minor,omitempty"` - FileMode *os.FileMode `json:"fileMode,omitempty"` - Permissions string `json:"permissions,omitempty"` - UID *uint32 `json:"uid,omitempty"` - GID *uint32 `json:"gid,omitempty"` + Path string `json:"path" yaml:"path"` + HostPath string `json:"hostPath,omitempty" yaml:"hostPath,omitempty"` // Added in v0.5.0 + Type string `json:"type,omitempty" yaml:"type,omitempty"` + Major int64 `json:"major,omitempty" yaml:"major,omitempty"` + Minor int64 `json:"minor,omitempty" yaml:"minor,omitempty"` + FileMode *os.FileMode `json:"fileMode,omitempty" yaml:"fileMode,omitempty"` + Permissions string `json:"permissions,omitempty" yaml:"permissions,omitempty"` + UID *uint32 `json:"uid,omitempty" yaml:"uid,omitempty"` + GID *uint32 `json:"gid,omitempty" yaml:"gid,omitempty"` } // Mount represents a mount that needs to be added to the OCI spec. type Mount struct { - HostPath string `json:"hostPath"` - ContainerPath string `json:"containerPath"` - Options []string `json:"options,omitempty"` - Type string `json:"type,omitempty"` + HostPath string `json:"hostPath" yaml:"hostPath"` + ContainerPath string `json:"containerPath" yaml:"containerPath"` + Options []string `json:"options,omitempty" yaml:"options,omitempty"` + Type string `json:"type,omitempty" yaml:"type,omitempty"` // Added in v0.4.0 } // Hook represents a hook that needs to be added to the OCI spec. type Hook struct { - HookName string `json:"hookName"` - Path string `json:"path"` - Args []string `json:"args,omitempty"` - Env []string `json:"env,omitempty"` - Timeout *int `json:"timeout,omitempty"` + HookName string `json:"hookName" yaml:"hookName"` + Path string `json:"path" yaml:"path"` + Args []string `json:"args,omitempty" yaml:"args,omitempty"` + Env []string `json:"env,omitempty" yaml:"env,omitempty"` + Timeout *int `json:"timeout,omitempty" yaml:"timeout,omitempty"` } // IntelRdt describes the Linux IntelRdt parameters to set in the OCI spec. type IntelRdt struct { - ClosID string `json:"closID,omitempty"` - L3CacheSchema string `json:"l3CacheSchema,omitempty"` - MemBwSchema string `json:"memBwSchema,omitempty"` - EnableCMT bool `json:"enableCMT,omitempty"` - EnableMBM bool `json:"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"` + EnableCMT bool `json:"enableCMT,omitempty" yaml:"enableCMT,omitempty"` + EnableMBM bool `json:"enableMBM,omitempty" yaml:"enableMBM,omitempty"` } diff --git a/vendor/tags.cncf.io/container-device-interface/specs-go/oci.go b/vendor/tags.cncf.io/container-device-interface/specs-go/oci.go deleted file mode 100644 index ce485cb2..00000000 --- a/vendor/tags.cncf.io/container-device-interface/specs-go/oci.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright © 2021 The CDI Authors - -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 specs - -import "errors" - -// errDeprecated is returned for the ToOCI functions below. -// This should provide better guidance for user when migrating from the API -// below to the APIs provided in the cdi package. -var errDeprecated = errors.New("deprecated; Use cdi package functions instead") - -// ToOCI returns the opencontainers runtime Spec Hook for this Hook. -// -// Deprecated: This function has been moved to tags.cncf.io/container-device-interface/pkg/cdi.Hook.toOCI -// and made private. -func (h *Hook) ToOCI() error { - return errDeprecated -} - -// ToOCI returns the opencontainers runtime Spec Mount for this Mount. -// -// Deprecated: This function has been moved to tags.cncf.io/container-device-interface/pkg/cdi.Mount.toOCI -// and made private. -func (m *Mount) ToOCI() error { - return errDeprecated -} - -// ToOCI returns the opencontainers runtime Spec LinuxDevice for this DeviceNode. -// -// Deprecated: This function has been moved to tags.cncf.io/container-device-interface/pkg/cdi.DeviceNode.toOCI -// and made private. -func (d *DeviceNode) ToOCI() error { - return errDeprecated -} - -// ToOCI returns the opencontainers runtime Spec LinuxIntelRdt for this IntelRdt config. -// -// Deprecated: This function has been moved to tags.cncf.io/container-device-interface/pkg/cdi.IntelRdt.toOCI -// and made private. -func (i *IntelRdt) ToOCI() error { - return errDeprecated -} diff --git a/vendor/tags.cncf.io/container-device-interface/specs-go/version.go b/vendor/tags.cncf.io/container-device-interface/specs-go/version.go new file mode 100644 index 00000000..002e0350 --- /dev/null +++ b/vendor/tags.cncf.io/container-device-interface/specs-go/version.go @@ -0,0 +1,244 @@ +/* + Copyright © The CDI Authors + + 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 specs + +import ( + "fmt" + "strings" + + "golang.org/x/mod/semver" +) + +const ( + // CurrentVersion is the current version of the Spec. + CurrentVersion = "1.0.0" + + // vCurrent is the current version as a semver-comparable type + vCurrent version = "v" + CurrentVersion + + // These represent the released versions of the CDI specification + v010 version = "v0.1.0" + v020 version = "v0.2.0" + v030 version = "v0.3.0" + v040 version = "v0.4.0" + v050 version = "v0.5.0" + v060 version = "v0.6.0" + v070 version = "v0.7.0" + v080 version = "v0.8.0" + v100 version = "v1.0.0" + + // vEarliest is the earliest supported version of the CDI specification + vEarliest version = v030 +) + +// validSpecVersions stores a map of spec versions to functions to check the required versions. +// Adding new fields / spec versions requires that a `requiredFunc` be implemented and +// this map be updated. +var validSpecVersions = requiredVersionMap{ + v010: nil, + v020: nil, + v030: nil, + v040: requiresV040, + v050: requiresV050, + v060: requiresV060, + v070: requiresV070, + v080: requiresV080, + v100: requiresV100, +} + +// ValidateVersion checks whether the specified spec version is valid. +// In addition to checking whether the spec version is in the set of known versions, +// the spec is inspected to determine whether the features used are available in specified +// version. +func ValidateVersion(spec *Spec) error { + if !validSpecVersions.isValidVersion(spec.Version) { + return fmt.Errorf("invalid version %q", spec.Version) + } + minVersion, err := MinimumRequiredVersion(spec) + if err != nil { + return fmt.Errorf("could not determine minimum required version: %w", err) + } + if newVersion(minVersion).isGreaterThan(newVersion(spec.Version)) { + return fmt.Errorf("the spec version must be at least v%v", minVersion) + } + return nil +} + +// MinimumRequiredVersion determines the minimum spec version for the input spec. +func MinimumRequiredVersion(spec *Spec) (string, error) { + minVersion := validSpecVersions.requiredVersion(spec) + return minVersion.String(), nil +} + +// version represents a semantic version string +type version string + +// newVersion creates a version that can be used for semantic version comparisons. +func newVersion(v string) version { + return version("v" + strings.TrimPrefix(v, "v")) +} + +// String returns the string representation of the version. +// This trims a leading v if present. +func (v version) String() string { + return strings.TrimPrefix(string(v), "v") +} + +// isGreaterThan checks with a version is greater than the specified version. +func (v version) isGreaterThan(o version) bool { + return semver.Compare(string(v), string(o)) > 0 +} + +// isLatest checks whether the version is the latest supported version +func (v version) isLatest() bool { + return v == vCurrent +} + +type requiredFunc func(*Spec) bool + +type requiredVersionMap map[version]requiredFunc + +// isValidVersion checks whether the specified version is valid. +// A version is valid if it is contained in the required version map. +func (r requiredVersionMap) isValidVersion(specVersion string) bool { + _, ok := validSpecVersions[newVersion(specVersion)] + + return ok +} + +// requiredVersion returns the minimum version required for the given spec +func (r requiredVersionMap) requiredVersion(spec *Spec) version { + minVersion := vEarliest + + for v, isRequired := range validSpecVersions { + if isRequired == nil { + continue + } + if isRequired(spec) && v.isGreaterThan(minVersion) { + minVersion = v + } + // If we have already detected the latest version then no later version could be detected + if minVersion.isLatest() { + break + } + } + + return minVersion +} + +// 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. +func requiresV100(_ *Spec) bool { + return false +} + +// requiresV080 returns true if the spec uses v0.8.0 features. +// Since the v0.8.0 spec bump was due to the removed .ToOCI functions on the +// spec types, there are no explicit spec changes. +func requiresV080(_ *Spec) bool { + return false +} + +// requiresV070 returns true if the spec uses v0.7.0 features +func requiresV070(spec *Spec) bool { + if spec.ContainerEdits.IntelRdt != nil { + return true + } + // The v0.7.0 spec allows additional GIDs to be specified at a spec level. + if len(spec.ContainerEdits.AdditionalGIDs) > 0 { + return true + } + + for _, d := range spec.Devices { + if d.ContainerEdits.IntelRdt != nil { + return true + } + // The v0.7.0 spec allows additional GIDs to be specified at a device level. + if len(d.ContainerEdits.AdditionalGIDs) > 0 { + return true + } + } + + return false +} + +// requiresV060 returns true if the spec uses v0.6.0 features +func requiresV060(spec *Spec) bool { + // The v0.6.0 spec allows annotations to be specified at a spec level + for range spec.Annotations { + return true + } + + // The v0.6.0 spec allows annotations to be specified at a device level + for _, d := range spec.Devices { + for range d.Annotations { + return true + } + } + + // The v0.6.0 spec allows dots "." in Kind name label (class) + if !strings.Contains(spec.Kind, "/") { + return false + } + class := strings.SplitN(spec.Kind, "/", 2)[1] + return strings.Contains(class, ".") +} + +// requiresV050 returns true if the spec uses v0.5.0 features +func requiresV050(spec *Spec) bool { + var edits []*ContainerEdits + + for _, d := range spec.Devices { + // The v0.5.0 spec allowed device name to start with a digit + if len(d.Name) > 0 && '0' <= d.Name[0] && d.Name[0] <= '9' { + return true + } + edits = append(edits, &d.ContainerEdits) + } + + edits = append(edits, &spec.ContainerEdits) + for _, e := range edits { + for _, dn := range e.DeviceNodes { + // The HostPath field was added in v0.5.0 + if dn.HostPath != "" { + return true + } + } + } + return false +} + +// requiresV040 returns true if the spec uses v0.4.0 features +func requiresV040(spec *Spec) bool { + var edits []*ContainerEdits + + for _, d := range spec.Devices { + edits = append(edits, &d.ContainerEdits) + } + + edits = append(edits, &spec.ContainerEdits) + for _, e := range edits { + for _, m := range e.Mounts { + // The Type field was added in v0.4.0 + if m.Type != "" { + return true + } + } + } + return false +}