@@ -18,9 +18,12 @@ package cdi
1818
1919import (
2020 "path/filepath"
21+ "sort"
22+ "strings"
2123 "sync"
2224
2325 "github.com/hashicorp/go-multierror"
26+ oci "github.com/opencontainers/runtime-spec/specs-go"
2427 "github.com/pkg/errors"
2528)
2629
@@ -145,3 +148,128 @@ func (c *Cache) Refresh() error {
145148
146149 return nil
147150}
151+
152+ // InjectDevices injects the given qualified devices to an OCI Spec. It
153+ // returns any unresolvable devices and an error if injection fails for
154+ // any of the devices.
155+ func (c * Cache ) InjectDevices (ociSpec * oci.Spec , devices ... string ) ([]string , error ) {
156+ var (
157+ unresolved []string
158+ specs = map [* Spec ]struct {}{}
159+ )
160+
161+ if ociSpec == nil {
162+ return devices , errors .Errorf ("can't inject devices, nil OCI Spec" )
163+ }
164+
165+ c .Lock ()
166+ defer c .Unlock ()
167+
168+ for _ , device := range devices {
169+ d := c .devices [device ]
170+ if d == nil {
171+ unresolved = append (unresolved , device )
172+ continue
173+ }
174+ if _ , ok := specs [d .GetSpec ()]; ! ok {
175+ specs [d .GetSpec ()] = struct {}{}
176+ d .GetSpec ().ApplyEdits (ociSpec )
177+ }
178+ d .ApplyEdits (ociSpec )
179+ }
180+
181+ if unresolved != nil {
182+ return unresolved , errors .Errorf ("unresolvable CDI devices %s" ,
183+ strings .Join (devices , ", " ))
184+ }
185+
186+ return nil , nil
187+ }
188+
189+ // GetDevice returns the cached device for the given qualified name.
190+ func (c * Cache ) GetDevice (device string ) * Device {
191+ c .Lock ()
192+ defer c .Unlock ()
193+
194+ return c .devices [device ]
195+ }
196+
197+ // ListDevices lists all cached devices by qualified name.
198+ func (c * Cache ) ListDevices () []string {
199+ var devices []string
200+
201+ c .Lock ()
202+ defer c .Unlock ()
203+
204+ for name := range c .devices {
205+ devices = append (devices , name )
206+ }
207+ sort .Strings (devices )
208+
209+ return devices
210+ }
211+
212+ // ListVendors lists all vendors known to the cache.
213+ func (c * Cache ) ListVendors () []string {
214+ var vendors []string
215+
216+ c .Lock ()
217+ defer c .Unlock ()
218+
219+ for vendor := range c .specs {
220+ vendors = append (vendors , vendor )
221+ }
222+ sort .Strings (vendors )
223+
224+ return vendors
225+ }
226+
227+ // ListClasses lists all device classes known to the cache.
228+ func (c * Cache ) ListClasses () []string {
229+ var (
230+ cmap = map [string ]struct {}{}
231+ classes []string
232+ )
233+
234+ c .Lock ()
235+ defer c .Unlock ()
236+
237+ for _ , specs := range c .specs {
238+ for _ , spec := range specs {
239+ cmap [spec .GetClass ()] = struct {}{}
240+ }
241+ }
242+ for class := range cmap {
243+ classes = append (classes , class )
244+ }
245+ sort .Strings (classes )
246+
247+ return classes
248+ }
249+
250+ // GetVendorSpecs returns all specs for the given vendor.
251+ func (c * Cache ) GetVendorSpecs (vendor string ) []* Spec {
252+ c .Lock ()
253+ defer c .Unlock ()
254+
255+ return c .specs [vendor ]
256+ }
257+
258+ // GetSpecErrors returns all errors encountered for the spec during the
259+ // last cache refresh.
260+ func (c * Cache ) GetSpecErrors (spec * Spec ) []error {
261+ return c .errors [spec .GetPath ()]
262+ }
263+
264+ // GetErrors returns all errors encountered during the last
265+ // cache refresh.
266+ func (c * Cache ) GetErrors () map [string ][]error {
267+ return c .errors
268+ }
269+
270+ // GetSpecDirectories returns the CDI Spec directories currently in use.
271+ func (c * Cache ) GetSpecDirectories () []string {
272+ dirs := make ([]string , len (c .specDirs ))
273+ copy (dirs , c .specDirs )
274+ return dirs
275+ }
0 commit comments