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

Function newPlugin

cli-plugins/manager/plugin.go:61–129  ·  view source on GitHub ↗

newPlugin determines if the given candidate is valid and returns a Plugin. If the candidate fails one of the tests then `Plugin.Err` is set, and is always a `pluginError`, but the `Plugin` is still returned with no error. An error is only returned due to a non-recoverable error.

(c pluginCandidate, cmds []*cobra.Command)

Source from the content-addressed store, hash-verified

59// returned with no error. An error is only returned due to a
60// non-recoverable error.
61func newPlugin(c pluginCandidate, cmds []*cobra.Command) (Plugin, error) {
62 path := c.Path()
63 if path == "" {
64 return Plugin{}, errors.New("plugin candidate path cannot be empty")
65 }
66
67 // The candidate listing process should have skipped anything
68 // which would fail here, so there are all real errors.
69 fullname := filepath.Base(path)
70 if fullname == "." {
71 return Plugin{}, fmt.Errorf("unable to determine basename of plugin candidate %q", path)
72 }
73 var err error
74 if fullname, err = trimExeSuffix(fullname); err != nil {
75 return Plugin{}, fmt.Errorf("plugin candidate %q: %w", path, err)
76 }
77 if !strings.HasPrefix(fullname, metadata.NamePrefix) {
78 return Plugin{}, fmt.Errorf("plugin candidate %q: does not have %q prefix", path, metadata.NamePrefix)
79 }
80
81 p := Plugin{
82 Name: strings.TrimPrefix(fullname, metadata.NamePrefix),
83 Path: path,
84 }
85
86 // Now apply the candidate tests, so these update p.Err.
87 if !isValidPluginName(p.Name) {
88 p.Err = newPluginError("plugin candidate %q did not match %q", p.Name, pluginNameFormat)
89 return p, nil
90 }
91
92 for _, cmd := range cmds {
93 // Ignore conflicts with commands which are
94 // just plugin stubs (i.e. from a previous
95 // call to AddPluginCommandStubs).
96 if IsPluginCommand(cmd) {
97 continue
98 }
99 if cmd.Name() == p.Name {
100 p.Err = newPluginError("plugin %q duplicates builtin command", p.Name)
101 return p, nil
102 }
103 if cmd.HasAlias(p.Name) {
104 p.Err = newPluginError("plugin %q duplicates an alias of builtin command %q", p.Name, cmd.Name())
105 return p, nil
106 }
107 }
108
109 // We are supposed to check for relevant execute permissions here. Instead we rely on an attempt to execute.
110 meta, err := c.Metadata()
111 if err != nil {
112 p.Err = wrapAsPluginError(err, "failed to fetch metadata")
113 return p, nil
114 }
115
116 if err := json.Unmarshal(meta, &p.Metadata); err != nil {
117 p.Err = wrapAsPluginError(err, "invalid metadata")
118 return p, nil

Callers 4

TestValidateCandidateFunction · 0.85
getPluginFunction · 0.85
ListPluginsFunction · 0.85
PluginRunCommandFunction · 0.85

Calls 9

isValidPluginNameFunction · 0.85
newPluginErrorFunction · 0.85
IsPluginCommandFunction · 0.85
wrapAsPluginErrorFunction · 0.85
validateSchemaVersionFunction · 0.85
trimExeSuffixFunction · 0.70
PathMethod · 0.65
MetadataMethod · 0.65
NameMethod · 0.45

Tested by 1

TestValidateCandidateFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…