forked from cncf-tags/container-device-interface
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pkg/cdi: sketch up an updated API proposal.
Sketch up a proposal for updating the API. This should be better suited for doing CDI device resolution/injection in runtimes. The API now supports (almost, sans TODO's) - CDI Spec/device caching - manual cache refresh - automatic cache refresh (TODO) - device filtering (for vendor, class, and/or name) - device enumeration (filtered listing of devices) - device injection to OCI Spec - resolving devices in OCI Spec (CDI device in OCI device path) - injection of 'all' enumerated devices to OCI Spec (TODO) Signed-off-by: Krisztian Litkey <krisztian.litkey@intel.com>
- Loading branch information
Showing
11 changed files
with
3,147 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
package cdi | ||
|
||
import ( | ||
"strings" | ||
|
||
specs "github.com/container-orchestrated-devices/container-device-interface/specs-go" | ||
oci "github.com/opencontainers/runtime-spec/specs-go" | ||
"github.com/opencontainers/runtime-tools/generate" | ||
|
||
//"github.com/opencontainers/runtime-tools/generate" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
// ContainerEdits represent updates to be applied to an OCI Spec. | ||
type ContainerEdits struct { | ||
*specs.ContainerEdits | ||
} | ||
|
||
// Apply edits to the given OCI Spec. | ||
func (e *ContainerEdits) Apply(spec *oci.Spec) error { | ||
if spec == nil { | ||
return errors.New("nil OCI Spec") | ||
} | ||
if e == nil || e.ContainerEdits == nil { | ||
return nil | ||
} | ||
|
||
g := generate.NewFromSpec(spec) | ||
|
||
if len(e.Env) > 0 { | ||
g.AddMultipleProcessEnv(e.Env) | ||
} | ||
for _, d := range e.DeviceNodes { | ||
g.AddDevice(d.ToOCI()) | ||
} | ||
for _, m := range e.Mounts { | ||
g.AddMount(m.ToOCI()) | ||
} | ||
for _, h := range e.Hooks { | ||
switch h.HookName { | ||
case "prestart": | ||
g.AddPreStartHook(h.ToOCI()) | ||
case "poststart": | ||
g.AddPostStartHook(h.ToOCI()) | ||
case "poststop": | ||
g.AddPostStopHook(h.ToOCI()) | ||
// TODO: Runtime-tools should be updated to support these, too. | ||
case "createRuntime": | ||
ensureSpecHooks(spec) | ||
spec.Hooks.CreateRuntime = append(spec.Hooks.CreateRuntime, h.ToOCI()) | ||
case "createContainer": | ||
ensureSpecHooks(spec) | ||
spec.Hooks.CreateContainer = append(spec.Hooks.CreateContainer, h.ToOCI()) | ||
case "startContainer": | ||
ensureSpecHooks(spec) | ||
spec.Hooks.StartContainer = append(spec.Hooks.StartContainer, h.ToOCI()) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Validate basic sanity of the edits. | ||
func (e *ContainerEdits) Validate() error { | ||
if err := e.validateEnv(e.Env); err != nil { | ||
return errors.Wrap(err, "invalid container edits") | ||
} | ||
if err := e.validateDevices(); err != nil { | ||
return errors.Wrap(err, "invalid container edits") | ||
} | ||
if err := e.validateHooks(); err != nil { | ||
return errors.Wrap(err, "invalid container edits") | ||
} | ||
if err := e.validateMounts(); err != nil { | ||
return errors.Wrap(err, "invalid container edits") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (e *ContainerEdits) validateEnv(env []string) error { | ||
for _, v := range env { | ||
if strings.IndexByte(v, byte('=')) <= 0 { | ||
return errors.Errorf("invalid environment variable %q", v) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (e *ContainerEdits) validateDevices() error { | ||
for _, d := range e.DeviceNodes { | ||
if d.Path == "" { | ||
return errors.New("invalid (empty) device path") | ||
} | ||
if d.Type != "" && d.Type != "b" && d.Type != "c" { | ||
return errors.Errorf("device %q: invalid type %q", d.Path, d.Type) | ||
} | ||
for _, c := range d.Permissions { | ||
if c != 'r' && c != 'w' && c != 'm' { | ||
return errors.Errorf("device %q: invalid permissions %q", d.Path, d.Permissions) | ||
} | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (e *ContainerEdits) validateHooks() error { | ||
for _, h := range e.Hooks { | ||
switch h.HookName { | ||
case "Prestart": | ||
case "CreateRuntime": | ||
case "CreateContainer": | ||
case "StartContainer": | ||
case "PostStart": | ||
case "PostStop": | ||
default: | ||
return errors.Errorf("invalid hook name %q", h.HookName) | ||
} | ||
if h.Path == "" { | ||
return errors.Errorf("invalid hook %q with empty path", h.HookName) | ||
} | ||
if err := e.validateEnv(h.Env); err != nil { | ||
return errors.Wrapf(err, "invalid hook %q", h.HookName) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (e *ContainerEdits) validateMounts() error { | ||
for _, m := range e.Mounts { | ||
if m.HostPath == "" { | ||
return errors.New("invalid mount, empty host path") | ||
} | ||
if m.ContainerPath == "" { | ||
return errors.New("invalid mount, empty container path") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func ensureSpecHooks(spec *oci.Spec) { | ||
if spec.Hooks == nil { | ||
spec.Hooks = &oci.Hooks{} | ||
} | ||
} |
Oops, something went wrong.