Bump github.com/container-orchestrated-devices/container-device-interface
Bumps [github.com/container-orchestrated-devices/container-device-interface](https://github.com/container-orchestrated-devices/container-device-interface) from 0.5.2 to 0.5.3. - [Release notes](https://github.com/container-orchestrated-devices/container-device-interface/releases) - [Commits](https://github.com/container-orchestrated-devices/container-device-interface/compare/v0.5.2...v0.5.3) --- updated-dependencies: - dependency-name: github.com/container-orchestrated-devices/container-device-interface dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
parent
69ed903b20
commit
fa2b4aeefd
2
go.mod
2
go.mod
|
|
@ -8,7 +8,7 @@ require (
|
||||||
github.com/buger/goterm v1.0.4
|
github.com/buger/goterm v1.0.4
|
||||||
github.com/checkpoint-restore/checkpointctl v0.0.0-20220321135231-33f4a66335f0
|
github.com/checkpoint-restore/checkpointctl v0.0.0-20220321135231-33f4a66335f0
|
||||||
github.com/checkpoint-restore/go-criu/v6 v6.3.0
|
github.com/checkpoint-restore/go-criu/v6 v6.3.0
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.5.2
|
github.com/container-orchestrated-devices/container-device-interface v0.5.3
|
||||||
github.com/containernetworking/cni v1.1.2
|
github.com/containernetworking/cni v1.1.2
|
||||||
github.com/containernetworking/plugins v1.1.1
|
github.com/containernetworking/plugins v1.1.1
|
||||||
github.com/containers/buildah v1.28.1-0.20221029151733-c2cf9fa47ab6
|
github.com/containers/buildah v1.28.1-0.20221029151733-c2cf9fa47ab6
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -163,8 +163,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.5.2 h1:Bf/Zq8UBhbSBtB+pFBVIQ2Rh7sNK/x2ZEr6uW5YjNv8=
|
github.com/container-orchestrated-devices/container-device-interface v0.5.3 h1:4v6FMaa1Pn8SS0IBwgsvCsno8HRXoQvI87Uj1Zu7Tw4=
|
||||||
github.com/container-orchestrated-devices/container-device-interface v0.5.2/go.mod h1:ZToWfSyUH5l9Rk7/bjkUUkNLz4b1mE+CVUVafuikDPY=
|
github.com/container-orchestrated-devices/container-device-interface v0.5.3/go.mod h1:SQohok453ewi9dItvUcO0MrP7K1CEQTxPDNd7OV+nxI=
|
||||||
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
|
||||||
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
|
||||||
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
|
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
|
||||||
|
|
|
||||||
82
vendor/github.com/container-orchestrated-devices/container-device-interface/internal/multierror/multierror.go
generated
vendored
Normal file
82
vendor/github.com/container-orchestrated-devices/container-device-interface/internal/multierror/multierror.go
generated
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2022 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 multierror
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// New combines several errors into a single error. Parameters that are nil are
|
||||||
|
// ignored. If no errors are passed in or all parameters are nil, then the
|
||||||
|
// result is also nil.
|
||||||
|
func New(errors ...error) error {
|
||||||
|
// Filter out nil entries.
|
||||||
|
numErrors := 0
|
||||||
|
for _, err := range errors {
|
||||||
|
if err != nil {
|
||||||
|
errors[numErrors] = err
|
||||||
|
numErrors++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if numErrors == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return multiError(errors[0:numErrors])
|
||||||
|
}
|
||||||
|
|
||||||
|
// multiError is the underlying implementation used by New.
|
||||||
|
//
|
||||||
|
// Beware that a null multiError is not the same as a nil error.
|
||||||
|
type multiError []error
|
||||||
|
|
||||||
|
// multiError returns all individual error strings concatenated with "\n"
|
||||||
|
func (e multiError) Error() string {
|
||||||
|
var builder strings.Builder
|
||||||
|
for i, err := range e {
|
||||||
|
if i > 0 {
|
||||||
|
_, _ = builder.WriteString("\n")
|
||||||
|
}
|
||||||
|
_, _ = builder.WriteString(err.Error())
|
||||||
|
}
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append returns a new multi error all errors concatenated. Errors that are
|
||||||
|
// multi errors get flattened, nil is ignored.
|
||||||
|
func Append(err error, errors ...error) error {
|
||||||
|
var result multiError
|
||||||
|
if m, ok := err.(multiError); ok {
|
||||||
|
result = m
|
||||||
|
} else if err != nil {
|
||||||
|
result = append(result, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, e := range errors {
|
||||||
|
if e == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if m, ok := e.(multiError); ok {
|
||||||
|
result = append(result, m...)
|
||||||
|
} else {
|
||||||
|
result = append(result, e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(result) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
@ -17,14 +17,18 @@
|
||||||
package cdi
|
package cdi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
stderr "errors"
|
||||||
|
|
||||||
|
"github.com/container-orchestrated-devices/container-device-interface/internal/multierror"
|
||||||
cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
oci "github.com/opencontainers/runtime-spec/specs-go"
|
oci "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
@ -123,8 +127,8 @@ func (c *Cache) Refresh() error {
|
||||||
|
|
||||||
// collect and return cached errors, much like refresh() does it
|
// collect and return cached errors, much like refresh() does it
|
||||||
var result error
|
var result error
|
||||||
for _, err := range c.errors {
|
for _, errors := range c.errors {
|
||||||
result = multierror.Append(result, err...)
|
result = multierror.Append(result, errors...)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
@ -194,11 +198,7 @@ func (c *Cache) refresh() error {
|
||||||
c.devices = devices
|
c.devices = devices
|
||||||
c.errors = specErrors
|
c.errors = specErrors
|
||||||
|
|
||||||
if len(result) > 0 {
|
return multierror.New(result...)
|
||||||
return multierror.Append(nil, result...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshIfRequired triggers a refresh if necessary.
|
// RefreshIfRequired triggers a refresh if necessary.
|
||||||
|
|
@ -255,11 +255,22 @@ func (c *Cache) InjectDevices(ociSpec *oci.Spec, devices ...string) ([]string, e
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteSpec writes a Spec file with the given content. Priority is used
|
// highestPrioritySpecDir returns the Spec directory with highest priority
|
||||||
// as an index into the list of Spec directories to pick a directory for
|
// and its priority.
|
||||||
// the file, adjusting for any under- or overflows. If name has a "json"
|
func (c *Cache) highestPrioritySpecDir() (string, int) {
|
||||||
// or "yaml" extension it choses the encoding. Otherwise JSON encoding
|
if len(c.specDirs) == 0 {
|
||||||
// is used with a "json" extension.
|
return "", -1
|
||||||
|
}
|
||||||
|
|
||||||
|
prio := len(c.specDirs) - 1
|
||||||
|
dir := c.specDirs[prio]
|
||||||
|
|
||||||
|
return dir, prio
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteSpec writes a Spec file with the given content into the highest
|
||||||
|
// priority Spec directory. If name has a "json" or "yaml" extension it
|
||||||
|
// choses the encoding. Otherwise the default YAML encoding is used.
|
||||||
func (c *Cache) WriteSpec(raw *cdi.Spec, name string) error {
|
func (c *Cache) WriteSpec(raw *cdi.Spec, name string) error {
|
||||||
var (
|
var (
|
||||||
specDir string
|
specDir string
|
||||||
|
|
@ -269,23 +280,51 @@ func (c *Cache) WriteSpec(raw *cdi.Spec, name string) error {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(c.specDirs) == 0 {
|
specDir, prio = c.highestPrioritySpecDir()
|
||||||
|
if specDir == "" {
|
||||||
return errors.New("no Spec directories to write to")
|
return errors.New("no Spec directories to write to")
|
||||||
}
|
}
|
||||||
|
|
||||||
prio = len(c.specDirs) - 1
|
|
||||||
specDir = c.specDirs[prio]
|
|
||||||
path = filepath.Join(specDir, name)
|
path = filepath.Join(specDir, name)
|
||||||
if ext := filepath.Ext(path); ext != ".json" && ext != ".yaml" {
|
if ext := filepath.Ext(path); ext != ".json" && ext != ".yaml" {
|
||||||
path += ".json"
|
path += defaultSpecExt
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err = NewSpec(raw, path, prio)
|
spec, err = newSpec(raw, path, prio)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec.Write(true)
|
return spec.write(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSpec removes a Spec with the given name from the highest
|
||||||
|
// priority Spec directory. This function can be used to remove a
|
||||||
|
// Spec previously written by WriteSpec(). If the file exists and
|
||||||
|
// its removal fails RemoveSpec returns an error.
|
||||||
|
func (c *Cache) RemoveSpec(name string) error {
|
||||||
|
var (
|
||||||
|
specDir string
|
||||||
|
path string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
specDir, _ = c.highestPrioritySpecDir()
|
||||||
|
if specDir == "" {
|
||||||
|
return errors.New("no Spec directories to remove from")
|
||||||
|
}
|
||||||
|
|
||||||
|
path = filepath.Join(specDir, name)
|
||||||
|
if ext := filepath.Ext(path); ext != ".json" && ext != ".yaml" {
|
||||||
|
path += defaultSpecExt
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.Remove(path)
|
||||||
|
if err != nil && stderr.Is(err, fs.ErrNotExist) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDevice returns the cached device for the given qualified name.
|
// GetDevice returns the cached device for the given qualified name.
|
||||||
|
|
|
||||||
119
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/doc.go
generated
vendored
119
vendor/github.com/container-orchestrated-devices/container-device-interface/pkg/cdi/doc.go
generated
vendored
|
|
@ -124,10 +124,15 @@
|
||||||
//
|
//
|
||||||
// Generated Spec Files, Multiple Directories, Device Precedence
|
// Generated Spec Files, Multiple Directories, Device Precedence
|
||||||
//
|
//
|
||||||
// There are systems where the set of available or usable CDI devices
|
// It is often necessary to generate Spec files dynamically. On some
|
||||||
// changes dynamically and this needs to be reflected in the CDI Specs.
|
// systems the available or usable set of CDI devices might change
|
||||||
// This is done by dynamically regenerating CDI Spec files which are
|
// dynamically which then needs to be reflected in CDI Specs. For
|
||||||
// affected by these changes.
|
// some device classes it makes sense to enumerate the available
|
||||||
|
// devices at every boot and generate Spec file entries for each
|
||||||
|
// device found. Some CDI devices might need special client- or
|
||||||
|
// request-specific configuration which can only be fulfilled by
|
||||||
|
// dynamically generated client-specific entries in transient Spec
|
||||||
|
// files.
|
||||||
//
|
//
|
||||||
// CDI can collect Spec files from multiple directories. Spec files are
|
// CDI can collect Spec files from multiple directories. Spec files are
|
||||||
// automatically assigned priorities according to which directory they
|
// automatically assigned priorities according to which directory they
|
||||||
|
|
@ -141,7 +146,111 @@
|
||||||
// separating dynamically generated CDI Spec files from static ones.
|
// separating dynamically generated CDI Spec files from static ones.
|
||||||
// The default directories are '/etc/cdi' and '/var/run/cdi'. By putting
|
// The default directories are '/etc/cdi' and '/var/run/cdi'. By putting
|
||||||
// dynamically generated Spec files under '/var/run/cdi', those take
|
// dynamically generated Spec files under '/var/run/cdi', those take
|
||||||
// precedence over static ones in '/etc/cdi'.
|
// precedence over static ones in '/etc/cdi'. With this scheme, static
|
||||||
|
// Spec files, typically installed by distro-specific packages, go into
|
||||||
|
// '/etc/cdi' while all the dynamically generated Spec files, transient
|
||||||
|
// or other, go into '/var/run/cdi'.
|
||||||
|
//
|
||||||
|
// Spec File Generation
|
||||||
|
//
|
||||||
|
// CDI offers two functions for writing and removing dynamically generated
|
||||||
|
// Specs from CDI Spec directories. These functions, WriteSpec() and
|
||||||
|
// RemoveSpec() implicitly follow the principle of separating dynamic Specs
|
||||||
|
// from the rest and therefore always write to and remove Specs from the
|
||||||
|
// last configured directory.
|
||||||
|
//
|
||||||
|
// Corresponding functions are also provided for generating names for Spec
|
||||||
|
// files. These functions follow a simple naming convention to ensure that
|
||||||
|
// multiple entities generating Spec files simultaneously on the same host
|
||||||
|
// do not end up using conflicting Spec file names. GenerateSpecName(),
|
||||||
|
// GenerateNameForSpec(), GenerateTransientSpecName(), and
|
||||||
|
// GenerateTransientNameForSpec() all generate names which can be passed
|
||||||
|
// as such to WriteSpec() and subsequently to RemoveSpec().
|
||||||
|
//
|
||||||
|
// Generating a Spec file for a vendor/device class can be done with a
|
||||||
|
// code snippet similar to the following:
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "fmt"
|
||||||
|
// ...
|
||||||
|
// "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
||||||
|
// "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func generateDeviceSpecs() error {
|
||||||
|
// registry := cdi.GetRegistry()
|
||||||
|
// spec := &specs.Spec{
|
||||||
|
// Version: specs.CurrentVersion,
|
||||||
|
// Kind: vendor+"/"+class,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for _, dev := range enumerateDevices() {
|
||||||
|
// spec.Devices = append(spec.Devices, specs.Device{
|
||||||
|
// Name: dev.Name,
|
||||||
|
// ContainerEdits: getContainerEditsForDevice(dev),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// specName, err := cdi.GenerateNameForSpec(spec)
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("failed to generate Spec name: %w", err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return registry.WriteSpec(spec, specName)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Similary, generating and later cleaning up transient Spec files can be
|
||||||
|
// done with code fragments similar to the following. These transient Spec
|
||||||
|
// files are temporary Spec files with container-specific parametrization.
|
||||||
|
// They are typically created before the associated container is created
|
||||||
|
// and removed once that container is removed.
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "fmt"
|
||||||
|
// ...
|
||||||
|
// "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
||||||
|
// "github.com/container-orchestrated-devices/container-device-interface/pkg/cdi"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// func generateTransientSpec(ctr Container) error {
|
||||||
|
// registry := cdi.GetRegistry()
|
||||||
|
// devices := getContainerDevs(ctr, vendor, class)
|
||||||
|
// spec := &specs.Spec{
|
||||||
|
// Version: specs.CurrentVersion,
|
||||||
|
// Kind: vendor+"/"+class,
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// for _, dev := range devices {
|
||||||
|
// spec.Devices = append(spec.Devices, specs.Device{
|
||||||
|
// // the generated name needs to be unique within the
|
||||||
|
// // vendor/class domain on the host/node.
|
||||||
|
// Name: generateUniqueDevName(dev, ctr),
|
||||||
|
// ContainerEdits: getEditsForContainer(dev),
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // transientID is expected to guarantee that the Spec file name
|
||||||
|
// // generated using <vendor, class, transientID> is unique within
|
||||||
|
// // the host/node. If more than one device is allocated with the
|
||||||
|
// // same vendor/class domain, either all generated Spec entries
|
||||||
|
// // should go to a single Spec file (like in this sample snippet),
|
||||||
|
// // or transientID should be unique for each generated Spec file.
|
||||||
|
// transientID := getSomeSufficientlyUniqueIDForContainer(ctr)
|
||||||
|
// specName, err := cdi.GenerateNameForTransientSpec(vendor, class, transientID)
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("failed to generate Spec name: %w", err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return registry.WriteSpec(spec, specName)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func removeTransientSpec(ctr Container) error {
|
||||||
|
// registry := cdi.GetRegistry()
|
||||||
|
// transientID := getSomeSufficientlyUniqueIDForContainer(ctr)
|
||||||
|
// specName := cdi.GenerateNameForTransientSpec(vendor, class, transientID)
|
||||||
|
//
|
||||||
|
// return registry.RemoveSpec(specName)
|
||||||
|
// }
|
||||||
//
|
//
|
||||||
// CDI Spec Validation
|
// CDI Spec Validation
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ type RegistrySpecDB interface {
|
||||||
GetVendorSpecs(vendor string) []*Spec
|
GetVendorSpecs(vendor string) []*Spec
|
||||||
GetSpecErrors(*Spec) []error
|
GetSpecErrors(*Spec) []error
|
||||||
WriteSpec(raw *cdi.Spec, name string) error
|
WriteSpec(raw *cdi.Spec, name string) error
|
||||||
|
RemoveSpec(name string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type registry struct {
|
type registry struct {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
oci "github.com/opencontainers/runtime-spec/specs-go"
|
oci "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
|
@ -30,6 +31,14 @@ import (
|
||||||
cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// CurrentVersion is the current vesion of the CDI Spec.
|
||||||
|
CurrentVersion = cdi.CurrentVersion
|
||||||
|
|
||||||
|
// defaultSpecExt is the file extension for the default encoding.
|
||||||
|
defaultSpecExt = ".yaml"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Valid CDI Spec versions.
|
// Valid CDI Spec versions.
|
||||||
validSpecVersions = map[string]struct{}{
|
validSpecVersions = map[string]struct{}{
|
||||||
|
|
@ -80,7 +89,7 @@ func ReadSpec(path string, priority int) (*Spec, error) {
|
||||||
return nil, errors.Errorf("failed to parse CDI Spec %q, no Spec data", path)
|
return nil, errors.Errorf("failed to parse CDI Spec %q, no Spec data", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := NewSpec(raw, path, priority)
|
spec, err := newSpec(raw, path, priority)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -88,11 +97,11 @@ func ReadSpec(path string, priority int) (*Spec, error) {
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSpec creates a new Spec from the given CDI Spec data. The
|
// newSpec creates a new Spec from the given CDI Spec data. The
|
||||||
// Spec is marked as loaded from the given path with the given
|
// Spec is marked as loaded from the given path with the given
|
||||||
// priority. If Spec data validation fails NewSpec returns a nil
|
// priority. If Spec data validation fails newSpec returns a nil
|
||||||
// Spec and an error.
|
// Spec and an error.
|
||||||
func NewSpec(raw *cdi.Spec, path string, priority int) (*Spec, error) {
|
func newSpec(raw *cdi.Spec, path string, priority int) (*Spec, error) {
|
||||||
err := validateSpec(raw)
|
err := validateSpec(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -104,6 +113,10 @@ func NewSpec(raw *cdi.Spec, path string, priority int) (*Spec, error) {
|
||||||
priority: priority,
|
priority: priority,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ext := filepath.Ext(spec.path); ext != ".yaml" && ext != ".json" {
|
||||||
|
spec.path += defaultSpecExt
|
||||||
|
}
|
||||||
|
|
||||||
spec.vendor, spec.class = ParseQualifier(spec.Kind)
|
spec.vendor, spec.class = ParseQualifier(spec.Kind)
|
||||||
|
|
||||||
if spec.devices, err = spec.validate(); err != nil {
|
if spec.devices, err = spec.validate(); err != nil {
|
||||||
|
|
@ -114,8 +127,8 @@ func NewSpec(raw *cdi.Spec, path string, priority int) (*Spec, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the CDI Spec to the file associated with it during instantiation
|
// Write the CDI Spec to the file associated with it during instantiation
|
||||||
// by NewSpec() or ReadSpec().
|
// by newSpec() or ReadSpec().
|
||||||
func (s *Spec) Write(overwrite bool) error {
|
func (s *Spec) write(overwrite bool) error {
|
||||||
var (
|
var (
|
||||||
data []byte
|
data []byte
|
||||||
dir string
|
dir string
|
||||||
|
|
@ -249,7 +262,7 @@ func ParseSpec(data []byte) (*cdi.Spec, error) {
|
||||||
|
|
||||||
// SetSpecValidator sets a CDI Spec validator function. This function
|
// SetSpecValidator sets a CDI Spec validator function. This function
|
||||||
// is used for extra CDI Spec content validation whenever a Spec file
|
// is used for extra CDI Spec content validation whenever a Spec file
|
||||||
// loaded (using ReadSpec() or NewSpec()) or written (Spec.Write()).
|
// loaded (using ReadSpec() or written (using WriteSpec()).
|
||||||
func SetSpecValidator(fn func(*cdi.Spec) error) {
|
func SetSpecValidator(fn func(*cdi.Spec) error) {
|
||||||
validatorLock.Lock()
|
validatorLock.Lock()
|
||||||
defer validatorLock.Unlock()
|
defer validatorLock.Unlock()
|
||||||
|
|
@ -270,3 +283,68 @@ func validateSpec(raw *cdi.Spec) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateSpecName generates a vendor+class scoped Spec file name. The
|
||||||
|
// name can be passed to WriteSpec() to write a Spec file to the file
|
||||||
|
// system.
|
||||||
|
//
|
||||||
|
// vendor and class should match the vendor and class of the CDI Spec.
|
||||||
|
// The file name is generated without a ".json" or ".yaml" extension.
|
||||||
|
// The caller can append the desired extension to choose a particular
|
||||||
|
// encoding. Otherwise WriteSpec() will use its default encoding.
|
||||||
|
//
|
||||||
|
// This function always returns the same name for the same vendor/class
|
||||||
|
// combination. Therefore it cannot be used as such to generate multiple
|
||||||
|
// Spec file names for a single vendor and class.
|
||||||
|
func GenerateSpecName(vendor, class string) string {
|
||||||
|
return vendor + "-" + class
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateTransientSpecName generates a vendor+class scoped transient
|
||||||
|
// Spec file name. The name can be passed to WriteSpec() to write a Spec
|
||||||
|
// file to the file system.
|
||||||
|
//
|
||||||
|
// Transient Specs are those whose lifecycle is tied to that of some
|
||||||
|
// external entity, for instance a container. vendor and class should
|
||||||
|
// match the vendor and class of the CDI Spec. transientID should be
|
||||||
|
// unique among all CDI users on the same host that might generate
|
||||||
|
// transient Spec files using the same vendor/class combination. If
|
||||||
|
// the external entity to which the lifecycle of the tranient Spec
|
||||||
|
// is tied to has a unique ID of its own, then this is usually a
|
||||||
|
// good choice for transientID.
|
||||||
|
//
|
||||||
|
// The file name is generated without a ".json" or ".yaml" extension.
|
||||||
|
// The caller can append the desired extension to choose a particular
|
||||||
|
// encoding. Otherwise WriteSpec() will use its default encoding.
|
||||||
|
func GenerateTransientSpecName(vendor, class, transientID string) string {
|
||||||
|
transientID = strings.ReplaceAll(transientID, "/", "_")
|
||||||
|
return GenerateSpecName(vendor, class) + "_" + transientID
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateNameForSpec generates a name for the given Spec using
|
||||||
|
// GenerateSpecName with the vendor and class taken from the Spec.
|
||||||
|
// On success it returns the generated name and a nil error. If
|
||||||
|
// the Spec does not contain a valid vendor or class, it returns
|
||||||
|
// an empty name and a non-nil error.
|
||||||
|
func GenerateNameForSpec(raw *cdi.Spec) (string, error) {
|
||||||
|
vendor, class := ParseQualifier(raw.Kind)
|
||||||
|
if vendor == "" {
|
||||||
|
return "", errors.Errorf("invalid vendor/class %q in Spec", raw.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateSpecName(vendor, class), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateNameForTransientSpec generates a name for the given transient
|
||||||
|
// Spec using GenerateTransientSpecName with the vendor and class taken
|
||||||
|
// from the Spec. On success it returns the generated name and a nil error.
|
||||||
|
// If the Spec does not contain a valid vendor or class, it returns an
|
||||||
|
// an empty name and a non-nil error.
|
||||||
|
func GenerateNameForTransientSpec(raw *cdi.Spec, transientID string) (string, error) {
|
||||||
|
vendor, class := ParseQualifier(raw.Kind)
|
||||||
|
if vendor == "" {
|
||||||
|
return "", errors.Errorf("invalid vendor/class %q in Spec", raw.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
return GenerateTransientSpecName(vendor, class, transientID), nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,9 @@ github.com/checkpoint-restore/go-criu/v6/stats
|
||||||
# github.com/chzyer/readline v1.5.1
|
# github.com/chzyer/readline v1.5.1
|
||||||
## explicit; go 1.15
|
## explicit; go 1.15
|
||||||
github.com/chzyer/readline
|
github.com/chzyer/readline
|
||||||
# github.com/container-orchestrated-devices/container-device-interface v0.5.2
|
# github.com/container-orchestrated-devices/container-device-interface v0.5.3
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
|
github.com/container-orchestrated-devices/container-device-interface/internal/multierror
|
||||||
github.com/container-orchestrated-devices/container-device-interface/pkg/cdi
|
github.com/container-orchestrated-devices/container-device-interface/pkg/cdi
|
||||||
github.com/container-orchestrated-devices/container-device-interface/specs-go
|
github.com/container-orchestrated-devices/container-device-interface/specs-go
|
||||||
# github.com/containerd/cgroups v1.0.4
|
# github.com/containerd/cgroups v1.0.4
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue