Skip to content

Commit

Permalink
pkg/cdi: add functions for Spec name generation.
Browse files Browse the repository at this point in the history
Add convenience functions for generating names for ordinary
and transient Spec files and for removing Spec files created
with WriteSpec().

Signed-off-by: Krisztian Litkey <krisztian.litkey@intel.com>
  • Loading branch information
klihub committed Aug 10, 2022
1 parent bed83d5 commit 93a7e7a
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 3 deletions.
51 changes: 48 additions & 3 deletions pkg/cdi/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
package cdi

import (
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
"sync"

stderr "errors"

cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
"github.com/fsnotify/fsnotify"
"github.com/hashicorp/go-multierror"
Expand Down Expand Up @@ -255,6 +259,19 @@ func (c *Cache) InjectDevices(ociSpec *oci.Spec, devices ...string) ([]string, e
return nil, nil
}

// highestPrioritySpecDir returns the Spec directory with highest priority
// and its priority.
func (c *Cache) highestPrioritySpecDir() (string, int) {
if len(c.specDirs) == 0 {
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 JSON encoding is used with a "json"
Expand All @@ -268,12 +285,11 @@ func (c *Cache) WriteSpec(raw *cdi.Spec, name string) error {
err error
)

if len(c.specDirs) == 0 {
specDir, prio = c.highestPrioritySpecDir()
if specDir == "" {
return errors.New("no Spec directories to write to")
}

prio = len(c.specDirs) - 1
specDir = c.specDirs[prio]
path = filepath.Join(specDir, name)
if ext := filepath.Ext(path); ext != ".json" && ext != ".yaml" {
path += ".json"
Expand All @@ -287,6 +303,35 @@ func (c *Cache) WriteSpec(raw *cdi.Spec, name string) error {
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 previosuly written by WriteSpec() using the same. 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 += ".json"
}

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.
func (c *Cache) GetDevice(device string) *Device {
c.Lock()
Expand Down
1 change: 1 addition & 0 deletions pkg/cdi/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ type RegistrySpecDB interface {
GetVendorSpecs(vendor string) []*Spec
GetSpecErrors(*Spec) []error
WriteSpec(raw *cdi.Spec, name string) error
RemoveSpec(name string) error
}

type registry struct {
Expand Down
53 changes: 53 additions & 0 deletions pkg/cdi/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,56 @@ func validateSpec(raw *cdi.Spec) error {
}
return nil
}

// GetSpecFileBase returns a Spec file basename.
func GetSpecFileBase(vendor, class, tag string) string {
if tag != "" {
return vendor + "-" + class + "-" + tag
}
return vendor + "-" + class

}

// 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. driver can be left empty
// if only a single CDI user is generating transient Spec files for the
// given vendor/class combination on the host. Otherwise driver should
// uniquely identify the caller among those that use the same vendor
// and class. transientID should uniquely identify the external entity
// within the scope of the caller/driver.
//
// 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, driver, transientID string) string {
name := vendor + "-" + class

if driver != "" {
name += "+" + driver
}

name = "transient." + name + "_" + transientID

return name
}

0 comments on commit 93a7e7a

Please sign in to comment.