diff --git a/cli-plugins/examples/helloworld/main.go b/cli-plugins/examples/helloworld/main.go index ba23f4954ecf..597dc42b0179 100644 --- a/cli-plugins/examples/helloworld/main.go +++ b/cli-plugins/examples/helloworld/main.go @@ -101,5 +101,6 @@ func main() { SchemaVersion: "0.1.0", Vendor: "Docker Inc.", Version: "testing", + Experimental: os.Getenv("HELLO_EXPERIMENTAL") != "", }) } diff --git a/cli-plugins/manager/manager.go b/cli-plugins/manager/manager.go index e7cd2de40aa2..26e8ab715223 100644 --- a/cli-plugins/manager/manager.go +++ b/cli-plugins/manager/manager.go @@ -117,7 +117,7 @@ func ListPlugins(dockerCli command.Cli, rootcmd *cobra.Command) ([]Plugin, error continue } c := &candidate{paths[0]} - p, err := newPlugin(c, rootcmd) + p, err := newPlugin(c, rootcmd, dockerCli.ClientInfo().HasExperimental) if err != nil { return nil, err } @@ -159,13 +159,12 @@ func PluginRunCommand(dockerCli command.Cli, name string, rootcmd *cobra.Command } c := &candidate{path: path} - plugin, err := newPlugin(c, rootcmd) + plugin, err := newPlugin(c, rootcmd, dockerCli.ClientInfo().HasExperimental) if err != nil { return nil, err } if plugin.Err != nil { - // TODO: why are we not returning plugin.Err? - return nil, errPluginNotFound(name) + return nil, plugin.Err } cmd := exec.Command(plugin.Path, args...) // Using dockerCli.{In,Out,Err}() here results in a hang until something is input. diff --git a/cli-plugins/manager/metadata.go b/cli-plugins/manager/metadata.go index d3de778141f6..92a6cc661d5b 100644 --- a/cli-plugins/manager/metadata.go +++ b/cli-plugins/manager/metadata.go @@ -22,4 +22,6 @@ type Metadata struct { ShortDescription string `json:",omitempty"` // URL is a pointer to the plugin's homepage. URL string `json:",omitempty"` + // Experimental specifies whether the plugin is experimental + Experimental bool `json:",omitempty"` } diff --git a/cli-plugins/manager/plugin.go b/cli-plugins/manager/plugin.go index a8ac4fa3a399..8f2e4a75d2ca 100644 --- a/cli-plugins/manager/plugin.go +++ b/cli-plugins/manager/plugin.go @@ -33,7 +33,7 @@ type Plugin struct { // 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. -func newPlugin(c Candidate, rootcmd *cobra.Command) (Plugin, error) { +func newPlugin(c Candidate, rootcmd *cobra.Command, allowExperimental bool) (Plugin, error) { path := c.Path() if path == "" { return Plugin{}, errors.New("plugin candidate path cannot be empty") @@ -94,6 +94,10 @@ func newPlugin(c Candidate, rootcmd *cobra.Command) (Plugin, error) { p.Err = wrapAsPluginError(err, "invalid metadata") return p, nil } + if p.Experimental && !allowExperimental { + p.Err = NewPluginError("plugin candidate %q: requires experimental enabled", p.Name) + return p, nil + } if p.Metadata.SchemaVersion != "0.1.0" { p.Err = NewPluginError("plugin SchemaVersion %q is not valid, must be 0.1.0", p.Metadata.SchemaVersion)