registry.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /*
  2. Copyright © 2021 The CDI Authors
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package cdi
  14. import (
  15. "sync"
  16. cdi "github.com/container-orchestrated-devices/container-device-interface/specs-go"
  17. oci "github.com/opencontainers/runtime-spec/specs-go"
  18. )
  19. // Registry keeps a cache of all CDI Specs installed or generated on
  20. // the host. Registry is the primary interface clients should use to
  21. // interact with CDI.
  22. //
  23. // The most commonly used Registry functions are for refreshing the
  24. // registry and injecting CDI devices into an OCI Spec.
  25. type Registry interface {
  26. RegistryResolver
  27. RegistryRefresher
  28. DeviceDB() RegistryDeviceDB
  29. SpecDB() RegistrySpecDB
  30. }
  31. // RegistryRefresher is the registry interface for refreshing the
  32. // cache of CDI Specs and devices.
  33. //
  34. // Configure reconfigures the registry with the given options.
  35. //
  36. // Refresh rescans all CDI Spec directories and updates the
  37. // state of the cache to reflect any changes. It returns any
  38. // errors encountered during the refresh.
  39. //
  40. // GetErrors returns all errors encountered for any of the scanned
  41. // Spec files during the last cache refresh.
  42. //
  43. // GetSpecDirectories returns the set up CDI Spec directories
  44. // currently in use. The directories are returned in the scan
  45. // order of Refresh().
  46. //
  47. // GetSpecDirErrors returns any errors related to the configured
  48. // Spec directories.
  49. type RegistryRefresher interface {
  50. Configure(...Option) error
  51. Refresh() error
  52. GetErrors() map[string][]error
  53. GetSpecDirectories() []string
  54. GetSpecDirErrors() map[string]error
  55. }
  56. // RegistryResolver is the registry interface for injecting CDI
  57. // devices into an OCI Spec.
  58. //
  59. // InjectDevices takes an OCI Spec and injects into it a set of
  60. // CDI devices given by qualified name. It returns the names of
  61. // any unresolved devices and an error if injection fails.
  62. type RegistryResolver interface {
  63. InjectDevices(spec *oci.Spec, device ...string) (unresolved []string, err error)
  64. }
  65. // RegistryDeviceDB is the registry interface for querying devices.
  66. //
  67. // GetDevice returns the CDI device for the given qualified name. If
  68. // the device is not GetDevice returns nil.
  69. //
  70. // ListDevices returns a slice with the names of qualified device
  71. // known. The returned slice is sorted.
  72. type RegistryDeviceDB interface {
  73. GetDevice(device string) *Device
  74. ListDevices() []string
  75. }
  76. // RegistrySpecDB is the registry interface for querying CDI Specs.
  77. //
  78. // ListVendors returns a slice with all vendors known. The returned
  79. // slice is sorted.
  80. //
  81. // ListClasses returns a slice with all classes known. The returned
  82. // slice is sorted.
  83. //
  84. // GetVendorSpecs returns a slice of all Specs for the vendor.
  85. //
  86. // GetSpecErrors returns any errors for the Spec encountered during
  87. // the last cache refresh.
  88. //
  89. // WriteSpec writes the Spec with the given content and name to the
  90. // last Spec directory.
  91. type RegistrySpecDB interface {
  92. ListVendors() []string
  93. ListClasses() []string
  94. GetVendorSpecs(vendor string) []*Spec
  95. GetSpecErrors(*Spec) []error
  96. WriteSpec(raw *cdi.Spec, name string) error
  97. RemoveSpec(name string) error
  98. }
  99. type registry struct {
  100. *Cache
  101. }
  102. var _ Registry = &registry{}
  103. var (
  104. reg *registry
  105. initOnce sync.Once
  106. )
  107. // GetRegistry returns the CDI registry. If any options are given, those
  108. // are applied to the registry.
  109. func GetRegistry(options ...Option) Registry {
  110. var new bool
  111. initOnce.Do(func() {
  112. reg, _ = getRegistry(options...)
  113. new = true
  114. })
  115. if !new && len(options) > 0 {
  116. reg.Configure(options...)
  117. reg.Refresh()
  118. }
  119. return reg
  120. }
  121. // DeviceDB returns the registry interface for querying devices.
  122. func (r *registry) DeviceDB() RegistryDeviceDB {
  123. return r
  124. }
  125. // SpecDB returns the registry interface for querying Specs.
  126. func (r *registry) SpecDB() RegistrySpecDB {
  127. return r
  128. }
  129. func getRegistry(options ...Option) (*registry, error) {
  130. c, err := NewCache(options...)
  131. return &registry{c}, err
  132. }