diff --git a/cmd/nvidia-ctk/cdi/generate/ipc.go b/cmd/nvidia-ctk/cdi/generate/ipc.go index 0f5157ee..e7c940b1 100644 --- a/cmd/nvidia-ctk/cdi/generate/ipc.go +++ b/cmd/nvidia-ctk/cdi/generate/ipc.go @@ -26,7 +26,10 @@ import ( func NewIPCDiscoverer(logger *logrus.Logger, root string) (discover.Discover, error) { d := discover.NewMounts( logger, - lookup.NewFileLocator(logger, root), + lookup.NewFileLocator( + lookup.WithLogger(logger), + lookup.WithRoot(root), + ), root, []string{ "/var/run/nvidia-persistenced/socket", diff --git a/internal/discover/gds.go b/internal/discover/gds.go index dab2f735..7da5e07d 100644 --- a/internal/discover/gds.go +++ b/internal/discover/gds.go @@ -45,7 +45,10 @@ func NewGDSDiscoverer(logger *logrus.Logger, root string) (Discover, error) { cufile := NewMounts( logger, - lookup.NewFileLocator(logger, root), + lookup.NewFileLocator( + lookup.WithLogger(logger), + lookup.WithRoot(root), + ), root, []string{"/etc/cufile.json"}, ) diff --git a/internal/discover/graphics.go b/internal/discover/graphics.go index 4d66832b..ab858405 100644 --- a/internal/discover/graphics.go +++ b/internal/discover/graphics.go @@ -70,7 +70,11 @@ func NewGraphicsMountsDiscoverer(logger *logrus.Logger, root string) (Discover, jsonMounts := NewMounts( logger, - lookup.NewFileLocator(logger, root, "/etc", "/usr/share"), + lookup.NewFileLocator( + lookup.WithLogger(logger), + lookup.WithRoot(root), + lookup.WithSearchPaths("/etc", "/usr/share"), + ), root, []string{ "glvnd/egl_vendor.d/10_nvidia.json", @@ -161,7 +165,10 @@ func (d drmDevicesByPath) getSpecificLinkArgs(devices []Device) ([]string, error selectedDevices[filepath.Base(d.HostPath)] = true } - linkLocator := lookup.NewFileLocator(d.logger, d.root) + linkLocator := lookup.NewFileLocator( + lookup.WithLogger(d.logger), + lookup.WithRoot(d.root), + ) candidates, err := linkLocator.Locate("/dev/dri/by-path/pci-*-*") if err != nil { d.logger.Warningf("Failed to locate by-path links: %v; ignoring", err) diff --git a/internal/lookup/device.go b/internal/lookup/device.go index aa4a2120..dfa774ea 100644 --- a/internal/lookup/device.go +++ b/internal/lookup/device.go @@ -30,13 +30,12 @@ const ( // NewCharDeviceLocator creates a Locator that can be used to find char devices at the specified root. A logger is // also specified. func NewCharDeviceLocator(logger *logrus.Logger, root string) Locator { - l := file{ - logger: logger, - prefixes: getSearchPrefixes(root, "", devRoot), - filter: assertCharDevice, - } - - return &l + return NewFileLocator( + WithLogger(logger), + WithRoot(root), + WithSearchPaths("", devRoot), + WithFilter(assertCharDevice), + ) } // assertCharDevice checks whether the specified path is a char device and returns an error if this is not the case. diff --git a/internal/lookup/dir.go b/internal/lookup/dir.go index f1d0156c..87b32507 100644 --- a/internal/lookup/dir.go +++ b/internal/lookup/dir.go @@ -26,13 +26,11 @@ import ( // NewDirectoryLocator creates a Locator that can be used to find directories at the specified root. A logger // is also specified. func NewDirectoryLocator(logger *log.Logger, root string) Locator { - l := file{ - logger: logger, - prefixes: getSearchPrefixes(root), - filter: assertDirectory, - } - - return &l + return NewFileLocator( + WithLogger(logger), + WithRoot(root), + WithFilter(assertDirectory), + ) } // assertDirectory checks wither the specified path is a directory. diff --git a/internal/lookup/executable.go b/internal/lookup/executable.go index ac27634b..e7ddf450 100644 --- a/internal/lookup/executable.go +++ b/internal/lookup/executable.go @@ -36,12 +36,15 @@ func NewExecutableLocator(logger *log.Logger, root string) Locator { } func newExecutableLocator(logger *log.Logger, root string, paths ...string) *executable { + f := newFileLocator( + WithLogger(logger), + WithRoot(root), + WithSearchPaths(paths...), + WithFilter(assertExecutable), + ) + l := executable{ - file: file{ - logger: logger, - prefixes: getSearchPrefixes(root, paths...), - filter: assertExecutable, - }, + file: *f, } return &l diff --git a/internal/lookup/file.go b/internal/lookup/file.go index 724075a2..94702174 100644 --- a/internal/lookup/file.go +++ b/internal/lookup/file.go @@ -28,31 +28,69 @@ import ( // prefixes. The validity of a file is determined by a filter function. type file struct { logger *log.Logger + root string prefixes []string filter func(string) error } -// NewFileLocator creates a Locator that can be used to find files at the specified root. -// An optional list of prefixes can aslo be specified with each of these being searched in order. -// The specified root is prefixed to each of the prefixes to determine the final search path. -func NewFileLocator(logger *log.Logger, root string, prefixes ...string) Locator { - l := newFileLocator(logger, root, prefixes...) +// Option defines a function for passing options to the NewFileLocator() call +type Option func(*file) - return &l +// WithRoot sets the root for the file locator +func WithRoot(root string) Option { + return func(f *file) { + f.root = root + } } -func newFileLocator(logger *log.Logger, root string, prefixes ...string) file { - - return file{ - logger: logger, - prefixes: getSearchPrefixes(root, prefixes...), - filter: assertFile, +// WithLogger sets the logger for the file locator +func WithLogger(logger *log.Logger) Option { + return func(f *file) { + f.logger = logger } } +// WithSearchPaths sets the search paths for the file locator. +func WithSearchPaths(paths ...string) Option { + return func(f *file) { + f.prefixes = paths + } +} + +// WithFilter sets the filter for the file locator +// The filter is called for each candidate file and candidates that return nil are considered. +func WithFilter(assert func(string) error) Option { + return func(f *file) { + f.filter = assert + } +} + +// NewFileLocator creates a Locator that can be used to find files with the specified options. +func NewFileLocator(opts ...Option) Locator { + return newFileLocator(opts...) +} + +func newFileLocator(opts ...Option) *file { + f := &file{} + for _, opt := range opts { + opt(f) + } + if f.logger == nil { + f.logger = log.StandardLogger() + } + if f.filter == nil { + f.filter = assertFile + } + // Since the `Locate` implementations rely on the root already being specified we update + // the prefixes to include the root. + f.prefixes = getSearchPrefixes(f.root, f.prefixes...) + + return f +} + // getSearchPrefixes generates a list of unique paths to be searched by a file locator. // -// For each of the unique prefixes

specified the path

is searched, where is the +// For each of the unique prefixes

specified, the path

is searched, where is the // specified root. If no prefixes are specified, is returned as the only search prefix. // // Note that an empty root is equivalent to searching relative to the current working directory, and diff --git a/internal/lookup/symlinks.go b/internal/lookup/symlinks.go index 43e37123..0d82a9e1 100644 --- a/internal/lookup/symlinks.go +++ b/internal/lookup/symlinks.go @@ -35,8 +35,9 @@ type symlink struct { // NewSymlinkChainLocator creats a locator that can be used for locating files through symlinks. // A logger can also be specified. func NewSymlinkChainLocator(logger *logrus.Logger, root string) Locator { + f := newFileLocator(WithLogger(logger), WithRoot(root)) l := symlinkChain{ - file: newFileLocator(logger, root), + file: *f, } return &l @@ -45,8 +46,9 @@ func NewSymlinkChainLocator(logger *logrus.Logger, root string) Locator { // NewSymlinkLocator creats a locator that can be used for locating files through symlinks. // A logger can also be specified. func NewSymlinkLocator(logger *logrus.Logger, root string) Locator { + f := newFileLocator(WithLogger(logger), WithRoot(root)) l := symlink{ - file: newFileLocator(logger, root), + file: *f, } return &l diff --git a/internal/modifier/tegra.go b/internal/modifier/tegra.go index b6a7ef22..8ce590a8 100644 --- a/internal/modifier/tegra.go +++ b/internal/modifier/tegra.go @@ -33,7 +33,7 @@ func NewTegraPlatformFiles(logger *logrus.Logger) (oci.SpecModifier, error) { tegraSystemMounts := discover.NewMounts( logger, - lookup.NewFileLocator(logger, ""), + lookup.NewFileLocator(lookup.WithLogger(logger)), "", []string{ "/etc/nv_tegra_release",