MCPcopy Index your code
hub / github.com/docker/cli / PluginRunCommand

Function PluginRunCommand

cli-plugins/manager/manager.go:177–227  ·  view source on GitHub ↗

PluginRunCommand returns an [os/exec.Cmd] which when [os/exec.Cmd.Run] will execute the named plugin. The rootcmd argument is referenced to determine the set of builtin commands in order to detect conflicts. The error returned satisfies the [errdefs.IsNotFound] predicate if no plugin was found or if

(dockerCli config.Provider, name string, rootcmd *cobra.Command)

Source from the content-addressed store, hash-verified

175// The rootcmd argument is referenced to determine the set of builtin commands in order to detect conflicts.
176// The error returned satisfies the [errdefs.IsNotFound] predicate if no plugin was found or if the first candidate plugin was invalid somehow.
177func PluginRunCommand(dockerCli config.Provider, name string, rootcmd *cobra.Command) (*exec.Cmd, error) {
178 // This uses the full original args, not the args which may
179 // have been provided by cobra to our caller. This is because
180 // they lack e.g. global options which we must propagate here.
181 args := os.Args[1:]
182 if !isValidPluginName(name) {
183 // We treat this as "not found" so that callers will
184 // fallback to their "invalid" command path.
185 return nil, errPluginNotFound(name)
186 }
187 exename := addExeSuffix(metadata.NamePrefix + name)
188 pluginDirs := getPluginDirs(dockerCli.ConfigFile())
189
190 for _, d := range pluginDirs {
191 path := filepath.Join(d, exename)
192
193 // We stat here rather than letting the exec tell us
194 // ENOENT because the latter does not distinguish a
195 // file not existing from its dynamic loader or one of
196 // its libraries not existing.
197 if _, err := os.Stat(path); os.IsNotExist(err) {
198 continue
199 }
200
201 c := &candidate{path: path}
202 plugin, err := newPlugin(c, rootcmd.Commands())
203 if err != nil {
204 return nil, err
205 }
206 if plugin.Err != nil {
207 // TODO: why are we not returning plugin.Err?
208 return nil, errPluginNotFound(name)
209 }
210 cmd := exec.Command(plugin.Path, args...) // #nosec G204 -- ignore "Subprocess launched with a potential tainted input or cmd arguments"
211
212 // Using dockerCli.{In,Out,Err}() here results in a hang until something is input.
213 // See: - https://github.com/golang/go/issues/10338
214 // - https://github.com/golang/go/commit/d000e8742a173aa0659584aa01b7ba2834ba28ab
215 // os.Stdin is a *os.File which avoids this behaviour. We don't need the functionality
216 // of the wrappers here anyway.
217 cmd.Stdin = os.Stdin
218 cmd.Stdout = os.Stdout
219 cmd.Stderr = os.Stderr
220
221 cmd.Env = append(cmd.Environ(), metadata.ReexecEnvvar+"="+os.Args[0])
222 cmd.Env = appendPluginResourceAttributesEnvvar(cmd.Env, rootcmd, plugin)
223
224 return cmd, nil
225 }
226 return nil, errPluginNotFound(name)
227}
228
229// IsPluginCommand checks if the given cmd is a plugin-stub.
230func IsPluginCommand(cmd *cobra.Command) bool {

Callers 1

AddPluginCommandStubsFunction · 0.85

Calls 8

isValidPluginNameFunction · 0.85
errPluginNotFoundTypeAlias · 0.85
getPluginDirsFunction · 0.85
newPluginFunction · 0.85
addExeSuffixFunction · 0.70
ConfigFileMethod · 0.65
CommandMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…