|
4 | 4 | package registry
|
5 | 5 |
|
6 | 6 | import (
|
| 7 | + "fmt" |
| 8 | + "os" |
| 9 | + "os/exec" |
| 10 | + "path/filepath" |
| 11 | + "strings" |
7 | 12 | "sync"
|
8 | 13 |
|
9 | 14 | "github.com/lima-vm/lima/pkg/driver"
|
| 15 | + "github.com/lima-vm/lima/pkg/usrlocalsharelima" |
10 | 16 | "github.com/sirupsen/logrus"
|
11 | 17 | )
|
12 | 18 |
|
@@ -68,10 +74,94 @@ func (r *Registry) RegisterPlugin(name, path string) {
|
68 | 74 | }
|
69 | 75 |
|
70 | 76 | func (r *Registry) DiscoverPlugins() error {
|
71 |
| - // TODO: Implement plugin discovery logic |
| 77 | + limaShareDir, err := usrlocalsharelima.Dir() |
| 78 | + if err != nil { |
| 79 | + return fmt.Errorf("failed to determine Lima share directory: %w", err) |
| 80 | + } |
| 81 | + stdPluginDir := filepath.Join(filepath.Dir(limaShareDir), "libexec", "lima", "drivers") |
| 82 | + |
| 83 | + if _, err := os.Stat(stdPluginDir); err == nil { |
| 84 | + if err := r.discoverPluginsInDir(stdPluginDir); err != nil { |
| 85 | + logrus.Warnf("Error discovering plugins in %s: %v", stdPluginDir, err) |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + if pluginPaths := os.Getenv("LIMA_DRIVERS_PATH"); pluginPaths != "" { |
| 90 | + paths := filepath.SplitList(pluginPaths) |
| 91 | + for _, path := range paths { |
| 92 | + if path == "" { |
| 93 | + continue |
| 94 | + } |
| 95 | + |
| 96 | + info, err := os.Stat(path) |
| 97 | + if err != nil { |
| 98 | + logrus.Warnf("Error accessing plugin path %s: %v", path, err) |
| 99 | + continue |
| 100 | + } |
| 101 | + |
| 102 | + if info.IsDir() { |
| 103 | + if err := r.discoverPluginsInDir(path); err != nil { |
| 104 | + logrus.Warnf("Error discovering plugins in %s: %v", path, err) |
| 105 | + } |
| 106 | + } else if isExecutable(info.Mode()) { |
| 107 | + r.registerPluginFile(path) |
| 108 | + } |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + return nil |
| 113 | +} |
| 114 | + |
| 115 | +func (r *Registry) discoverPluginsInDir(dir string) error { |
| 116 | + entries, err := os.ReadDir(dir) |
| 117 | + if err != nil { |
| 118 | + return fmt.Errorf("failed to read plugin directory %s: %w", dir, err) |
| 119 | + } |
| 120 | + |
| 121 | + for _, entry := range entries { |
| 122 | + if entry.IsDir() { |
| 123 | + continue |
| 124 | + } |
| 125 | + |
| 126 | + info, err := entry.Info() |
| 127 | + if err != nil { |
| 128 | + logrus.Warnf("Failed to get info for %s: %v", entry.Name(), err) |
| 129 | + continue |
| 130 | + } |
| 131 | + |
| 132 | + if !isExecutable(info.Mode()) { |
| 133 | + continue |
| 134 | + } |
| 135 | + |
| 136 | + pluginPath := filepath.Join(dir, entry.Name()) |
| 137 | + r.registerPluginFile(pluginPath) |
| 138 | + } |
| 139 | + |
72 | 140 | return nil
|
73 | 141 | }
|
74 | 142 |
|
| 143 | +func (r *Registry) registerPluginFile(path string) { |
| 144 | + base := filepath.Base(path) |
| 145 | + if !strings.HasPrefix(base, "lima-plugin-") { |
| 146 | + return |
| 147 | + } |
| 148 | + |
| 149 | + name := strings.TrimPrefix(base, "lima-plugin-") |
| 150 | + name = strings.TrimSuffix(name, filepath.Ext(name)) |
| 151 | + |
| 152 | + cmd := exec.Command(path, "--version") |
| 153 | + if err := cmd.Run(); err != nil { |
| 154 | + logrus.Warnf("Plugin %s failed version check: %v", path, err) |
| 155 | + return |
| 156 | + } |
| 157 | + |
| 158 | + r.RegisterPlugin(name, path) |
| 159 | +} |
| 160 | + |
| 161 | +func isExecutable(mode os.FileMode) bool { |
| 162 | + return mode&0111 != 0 |
| 163 | +} |
| 164 | + |
75 | 165 | var DefaultRegistry *Registry
|
76 | 166 |
|
77 | 167 | func init() {
|
|
0 commit comments