ListPlugins produces a list of the plugins available on the system
(dockerCli config.Provider, rootcmd *cobra.Command)
| 124 | |
| 125 | // ListPlugins produces a list of the plugins available on the system |
| 126 | func ListPlugins(dockerCli config.Provider, rootcmd *cobra.Command) ([]Plugin, error) { |
| 127 | pluginDirs := getPluginDirs(dockerCli.ConfigFile()) |
| 128 | candidates := listPluginCandidates(pluginDirs) |
| 129 | if len(candidates) == 0 { |
| 130 | return nil, nil |
| 131 | } |
| 132 | |
| 133 | var plugins []Plugin |
| 134 | var mu sync.Mutex |
| 135 | ctx := rootcmd.Context() |
| 136 | if ctx == nil { |
| 137 | // Fallback, mostly for tests that pass a bare cobra.command |
| 138 | ctx = context.Background() |
| 139 | } |
| 140 | eg, _ := errgroup.WithContext(ctx) |
| 141 | cmds := rootcmd.Commands() |
| 142 | for _, paths := range candidates { |
| 143 | func(paths []string) { |
| 144 | eg.Go(func() error { |
| 145 | if len(paths) == 0 { |
| 146 | return nil |
| 147 | } |
| 148 | c := &candidate{paths[0]} |
| 149 | p, err := newPlugin(c, cmds) |
| 150 | if err != nil { |
| 151 | return err |
| 152 | } |
| 153 | if !errdefs.IsNotFound(p.Err) { |
| 154 | p.ShadowedPaths = paths[1:] |
| 155 | mu.Lock() |
| 156 | defer mu.Unlock() |
| 157 | plugins = append(plugins, p) |
| 158 | } |
| 159 | return nil |
| 160 | }) |
| 161 | }(paths) |
| 162 | } |
| 163 | if err := eg.Wait(); err != nil { |
| 164 | return nil, err |
| 165 | } |
| 166 | |
| 167 | sort.Slice(plugins, func(i, j int) bool { |
| 168 | return sortorder.NaturalLess(plugins[i].Name, plugins[j].Name) |
| 169 | }) |
| 170 | |
| 171 | return plugins, nil |
| 172 | } |
| 173 | |
| 174 | // PluginRunCommand returns an [os/exec.Cmd] which when [os/exec.Cmd.Run] will execute the named plugin. |
| 175 | // The rootcmd argument is referenced to determine the set of builtin commands in order to detect conflicts. |
searching dependent graphs…