Merge pull request #6340 from thaJeztah/28.x_backport_cleanup_plugins
[28.x backport] cli/command/plugin: fix linting issues, and assorted cleanups
This commit is contained in:
@@ -40,7 +40,7 @@ func validateConfig(path string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// validateContextDir validates the given dir and returns abs path on success.
|
||||
// validateContextDir validates the given dir and returns its absolute path on success.
|
||||
func validateContextDir(contextDir string) (string, error) {
|
||||
absContextDir, err := filepath.Abs(contextDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/cli/cli"
|
||||
@@ -10,27 +9,24 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func newDisableCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var force bool
|
||||
func newDisableCommand(dockerCLI command.Cli) *cobra.Command {
|
||||
var opts types.PluginDisableOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "disable [OPTIONS] PLUGIN",
|
||||
Short: "Disable a plugin",
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runDisable(cmd.Context(), dockerCli, args[0], force)
|
||||
name := args[0]
|
||||
if err := dockerCLI.Client().PluginDisable(cmd.Context(), name, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprintln(dockerCLI.Out(), name)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.BoolVarP(&force, "force", "f", false, "Force the disable of an active plugin")
|
||||
flags.BoolVarP(&opts.Force, "force", "f", false, "Force the disable of an active plugin")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runDisable(ctx context.Context, dockerCli command.Cli, name string, force bool) error {
|
||||
if err := dockerCli.Client().PluginDisable(ctx, name, types.PluginDisableOptions{Force: force}); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), name)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,38 +11,31 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type enableOpts struct {
|
||||
timeout int
|
||||
name string
|
||||
}
|
||||
|
||||
func newEnableCommand(dockerCli command.Cli) *cobra.Command {
|
||||
var opts enableOpts
|
||||
var opts types.PluginEnableOptions
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "enable [OPTIONS] PLUGIN",
|
||||
Short: "Enable a plugin",
|
||||
Args: cli.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
opts.name = args[0]
|
||||
return runEnable(cmd.Context(), dockerCli, &opts)
|
||||
name := args[0]
|
||||
if err := runEnable(cmd.Context(), dockerCli, name, opts); err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = fmt.Fprintln(dockerCli.Out(), name)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
flags.IntVar(&opts.timeout, "timeout", 30, "HTTP client timeout (in seconds)")
|
||||
flags.IntVar(&opts.Timeout, "timeout", 30, "HTTP client timeout (in seconds)")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runEnable(ctx context.Context, dockerCli command.Cli, opts *enableOpts) error {
|
||||
name := opts.name
|
||||
if opts.timeout < 0 {
|
||||
return errors.Errorf("negative timeout %d is invalid", opts.timeout)
|
||||
func runEnable(ctx context.Context, dockerCli command.Cli, name string, opts types.PluginEnableOptions) error {
|
||||
if opts.Timeout < 0 {
|
||||
return errors.Errorf("negative timeout %d is invalid", opts.Timeout)
|
||||
}
|
||||
|
||||
if err := dockerCli.Client().PluginEnable(ctx, name, types.PluginEnableOptions{Timeout: opts.timeout}); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(dockerCli.Out(), name)
|
||||
return nil
|
||||
return dockerCli.Client().PluginEnable(ctx, name, opts)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func TestPluginEnableErrors(t *testing.T) {
|
||||
}))
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
assert.NilError(t, cmd.Flags().Set(key, value))
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
|
||||
@@ -12,6 +12,12 @@ const (
|
||||
|
||||
enabledHeader = "ENABLED"
|
||||
pluginIDHeader = "ID"
|
||||
|
||||
rawFormat = `plugin_id: {{.ID}}
|
||||
name: {{.Name}}
|
||||
description: {{.Description}}
|
||||
enabled: {{.Enabled}}
|
||||
`
|
||||
)
|
||||
|
||||
// NewFormat returns a Format for rendering using a plugin Context
|
||||
@@ -26,7 +32,7 @@ func NewFormat(source string, quiet bool) formatter.Format {
|
||||
if quiet {
|
||||
return `plugin_id: {{.ID}}`
|
||||
}
|
||||
return `plugin_id: {{.ID}}\nname: {{.Name}}\ndescription: {{.Description}}\nenabled: {{.Enabled}}\n`
|
||||
return rawFormat
|
||||
}
|
||||
return formatter.Format(source)
|
||||
}
|
||||
|
||||
@@ -19,85 +19,106 @@ import (
|
||||
func TestPluginContext(t *testing.T) {
|
||||
pluginID := test.RandomID()
|
||||
|
||||
var ctx pluginContext
|
||||
cases := []struct {
|
||||
var pCtx pluginContext
|
||||
tests := []struct {
|
||||
pluginCtx pluginContext
|
||||
expValue string
|
||||
call func() string
|
||||
}{
|
||||
{pluginContext{
|
||||
p: types.Plugin{ID: pluginID},
|
||||
trunc: false,
|
||||
}, pluginID, ctx.ID},
|
||||
{pluginContext{
|
||||
p: types.Plugin{ID: pluginID},
|
||||
trunc: true,
|
||||
}, formatter.TruncateID(pluginID), ctx.ID},
|
||||
{pluginContext{
|
||||
p: types.Plugin{Name: "plugin_name"},
|
||||
}, "plugin_name", ctx.Name},
|
||||
{pluginContext{
|
||||
p: types.Plugin{Config: types.PluginConfig{Description: "plugin_description"}},
|
||||
}, "plugin_description", ctx.Description},
|
||||
{
|
||||
pluginCtx: pluginContext{
|
||||
p: types.Plugin{ID: pluginID},
|
||||
trunc: false,
|
||||
},
|
||||
expValue: pluginID,
|
||||
call: pCtx.ID,
|
||||
},
|
||||
{
|
||||
pluginCtx: pluginContext{
|
||||
p: types.Plugin{ID: pluginID},
|
||||
trunc: true,
|
||||
},
|
||||
expValue: formatter.TruncateID(pluginID),
|
||||
call: pCtx.ID,
|
||||
},
|
||||
{
|
||||
pluginCtx: pluginContext{
|
||||
p: types.Plugin{Name: "plugin_name"},
|
||||
},
|
||||
expValue: "plugin_name",
|
||||
call: pCtx.Name,
|
||||
},
|
||||
{
|
||||
pluginCtx: pluginContext{
|
||||
p: types.Plugin{Config: types.PluginConfig{Description: "plugin_description"}},
|
||||
},
|
||||
expValue: "plugin_description",
|
||||
call: pCtx.Description,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
ctx = c.pluginCtx
|
||||
v := c.call()
|
||||
for _, tc := range tests {
|
||||
pCtx = tc.pluginCtx
|
||||
v := tc.call()
|
||||
if strings.Contains(v, ",") {
|
||||
test.CompareMultipleValues(t, v, c.expValue)
|
||||
} else if v != c.expValue {
|
||||
t.Fatalf("Expected %s, was %s\n", c.expValue, v)
|
||||
test.CompareMultipleValues(t, v, tc.expValue)
|
||||
} else if v != tc.expValue {
|
||||
t.Fatalf("Expected %s, was %s\n", tc.expValue, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginContextWrite(t *testing.T) {
|
||||
cases := []struct {
|
||||
tests := []struct {
|
||||
doc string
|
||||
context formatter.Context
|
||||
expected string
|
||||
}{
|
||||
// Errors
|
||||
{
|
||||
formatter.Context{Format: "{{InvalidFunction}}"},
|
||||
`template parsing error: template: :1: function "InvalidFunction" not defined`,
|
||||
doc: "invalid function",
|
||||
context: formatter.Context{Format: "{{InvalidFunction}}"},
|
||||
expected: `template parsing error: template: :1: function "InvalidFunction" not defined`,
|
||||
},
|
||||
{
|
||||
formatter.Context{Format: "{{nil}}"},
|
||||
`template parsing error: template: :1:2: executing "" at <nil>: nil is not a command`,
|
||||
doc: "nil template",
|
||||
context: formatter.Context{Format: "{{nil}}"},
|
||||
expected: `template parsing error: template: :1:2: executing "" at <nil>: nil is not a command`,
|
||||
},
|
||||
// Table format
|
||||
{
|
||||
formatter.Context{Format: NewFormat("table", false)},
|
||||
`ID NAME DESCRIPTION ENABLED
|
||||
doc: "table format",
|
||||
context: formatter.Context{Format: NewFormat("table", false)},
|
||||
expected: `ID NAME DESCRIPTION ENABLED
|
||||
pluginID1 foobar_baz description 1 true
|
||||
pluginID2 foobar_bar description 2 false
|
||||
`,
|
||||
},
|
||||
{
|
||||
formatter.Context{Format: NewFormat("table", true)},
|
||||
`pluginID1
|
||||
doc: "table format, quiet",
|
||||
context: formatter.Context{Format: NewFormat("table", true)},
|
||||
expected: `pluginID1
|
||||
pluginID2
|
||||
`,
|
||||
},
|
||||
{
|
||||
formatter.Context{Format: NewFormat("table {{.Name}}", false)},
|
||||
`NAME
|
||||
doc: "table format name col",
|
||||
context: formatter.Context{Format: NewFormat("table {{.Name}}", false)},
|
||||
expected: `NAME
|
||||
foobar_baz
|
||||
foobar_bar
|
||||
`,
|
||||
},
|
||||
{
|
||||
formatter.Context{Format: NewFormat("table {{.Name}}", true)},
|
||||
`NAME
|
||||
doc: "table format name col, quiet",
|
||||
context: formatter.Context{Format: NewFormat("table {{.Name}}", true)},
|
||||
expected: `NAME
|
||||
foobar_baz
|
||||
foobar_bar
|
||||
`,
|
||||
},
|
||||
// Raw Format
|
||||
{
|
||||
formatter.Context{Format: NewFormat("raw", false)},
|
||||
`plugin_id: pluginID1
|
||||
doc: "raw format",
|
||||
context: formatter.Context{Format: NewFormat("raw", false)},
|
||||
expected: `plugin_id: pluginID1
|
||||
name: foobar_baz
|
||||
description: description 1
|
||||
enabled: true
|
||||
@@ -110,15 +131,16 @@ enabled: false
|
||||
`,
|
||||
},
|
||||
{
|
||||
formatter.Context{Format: NewFormat("raw", true)},
|
||||
`plugin_id: pluginID1
|
||||
doc: "raw format, quiet",
|
||||
context: formatter.Context{Format: NewFormat("raw", true)},
|
||||
expected: `plugin_id: pluginID1
|
||||
plugin_id: pluginID2
|
||||
`,
|
||||
},
|
||||
// Custom Format
|
||||
{
|
||||
formatter.Context{Format: NewFormat("{{.Name}}", false)},
|
||||
`foobar_baz
|
||||
doc: "custom format",
|
||||
context: formatter.Context{Format: NewFormat("{{.Name}}", false)},
|
||||
expected: `foobar_baz
|
||||
foobar_bar
|
||||
`,
|
||||
},
|
||||
@@ -129,8 +151,8 @@ foobar_bar
|
||||
{ID: "pluginID2", Name: "foobar_bar", Config: types.PluginConfig{Description: "description 2"}, Enabled: false},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(string(tc.context.Format), func(t *testing.T) {
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.doc, func(t *testing.T) {
|
||||
var out bytes.Buffer
|
||||
tc.context.Output = &out
|
||||
|
||||
|
||||
@@ -36,11 +36,9 @@ func newInspectCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runInspect(ctx context.Context, dockerCli command.Cli, opts inspectOptions) error {
|
||||
client := dockerCli.Client()
|
||||
getRef := func(ref string) (any, []byte, error) {
|
||||
return client.PluginInspectWithRaw(ctx, ref)
|
||||
}
|
||||
|
||||
return inspect.Inspect(dockerCli.Out(), opts.pluginNames, opts.format, getRef)
|
||||
func runInspect(ctx context.Context, dockerCLI command.Cli, opts inspectOptions) error {
|
||||
apiClient := dockerCLI.Client()
|
||||
return inspect.Inspect(dockerCLI.Out(), opts.pluginNames, opts.format, func(ref string) (any, []byte, error) {
|
||||
return apiClient.PluginInspectWithRaw(ctx, ref)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,14 +21,14 @@ var pluginFoo = &types.Plugin{
|
||||
Documentation: "plugin foo documentation",
|
||||
Entrypoint: []string{"/foo"},
|
||||
Interface: types.PluginConfigInterface{
|
||||
Socket: "pluginfoo.sock",
|
||||
Socket: "plugin-foo.sock",
|
||||
},
|
||||
Linux: types.PluginConfigLinux{
|
||||
Capabilities: []string{"CAP_SYS_ADMIN"},
|
||||
},
|
||||
WorkDir: "workdir-foo",
|
||||
Rootfs: &types.PluginConfigRootfs{
|
||||
DiffIds: []string{"sha256:8603eedd4ea52cebb2f22b45405a3dc8f78ba3e31bf18f27b4547a9ff930e0bd"},
|
||||
DiffIds: []string{"sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"},
|
||||
Type: "layers",
|
||||
},
|
||||
},
|
||||
@@ -71,7 +71,7 @@ func TestInspectErrors(t *testing.T) {
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
assert.NilError(t, cmd.Flags().Set(key, value))
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
@@ -142,7 +142,7 @@ func TestInspect(t *testing.T) {
|
||||
cmd := newInspectCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
assert.NilError(t, cmd.Flags().Set(key, value))
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.golden)
|
||||
|
||||
@@ -125,7 +125,9 @@ func runInstall(ctx context.Context, dockerCLI command.Cli, opts pluginOptions)
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
defer func() {
|
||||
_ = responseBody.Close()
|
||||
}()
|
||||
if err := jsonstream.Display(ctx, responseBody, dockerCLI.Out()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func TestInstallErrors(t *testing.T) {
|
||||
},
|
||||
{
|
||||
description: "invalid plugin name",
|
||||
args: []string{"UPPERCASE_REPONAME"},
|
||||
args: []string{"UPPERCASE_REPO_NAME"},
|
||||
expectedError: "invalid",
|
||||
},
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestListErrors(t *testing.T) {
|
||||
cmd := newListCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
assert.NilError(t, cmd.Flags().Set(key, value))
|
||||
}
|
||||
cmd.SetOut(io.Discard)
|
||||
cmd.SetErr(io.Discard)
|
||||
@@ -170,7 +170,7 @@ func TestList(t *testing.T) {
|
||||
cmd := newListCommand(cli)
|
||||
cmd.SetArgs(tc.args)
|
||||
for key, value := range tc.flags {
|
||||
cmd.Flags().Set(key, value)
|
||||
assert.NilError(t, cmd.Flags().Set(key, value))
|
||||
}
|
||||
assert.NilError(t, cmd.Execute())
|
||||
golden.Assert(t, cli.OutBuffer().String(), tc.golden)
|
||||
|
||||
@@ -60,7 +60,9 @@ func runPush(ctx context.Context, dockerCli command.Cli, opts pushOptions) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
defer func() {
|
||||
_ = responseBody.Close()
|
||||
}()
|
||||
|
||||
if !opts.untrusted {
|
||||
repoInfo := &trust.RepositoryInfo{
|
||||
|
||||
@@ -64,7 +64,7 @@ func TestRemoveWithForceOption(t *testing.T) {
|
||||
})
|
||||
cmd := newRemoveCommand(cli)
|
||||
cmd.SetArgs([]string{"plugin-foo"})
|
||||
cmd.Flags().Set("force", "true")
|
||||
assert.NilError(t, cmd.Flags().Set("force", "true"))
|
||||
assert.NilError(t, cmd.Execute())
|
||||
assert.Check(t, force)
|
||||
assert.Check(t, is.Equal("plugin-foo\n", cli.OutBuffer().String()))
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func newSetCommand(dockerCli command.Cli) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
return &cobra.Command{
|
||||
Use: "set PLUGIN KEY=VALUE [KEY=VALUE...]",
|
||||
Short: "Change settings for a plugin",
|
||||
Args: cli.RequiresMinArgs(2),
|
||||
@@ -15,6 +15,4 @@ func newSetCommand(dockerCli command.Cli) *cobra.Command {
|
||||
return dockerCli.Client().PluginSet(cmd.Context(), args[0], args[1:])
|
||||
},
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
],
|
||||
"Env": null,
|
||||
"Interface": {
|
||||
"Socket": "pluginfoo.sock",
|
||||
"Socket": "plugin-foo.sock",
|
||||
"Types": null
|
||||
},
|
||||
"IpcHost": false,
|
||||
@@ -36,7 +36,7 @@
|
||||
"WorkDir": "workdir-foo",
|
||||
"rootfs": {
|
||||
"diff_ids": [
|
||||
"sha256:8603eedd4ea52cebb2f22b45405a3dc8f78ba3e31bf18f27b4547a9ff930e0bd"
|
||||
"sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"
|
||||
],
|
||||
"type": "layers"
|
||||
}
|
||||
|
||||
@@ -85,7 +85,9 @@ func runUpgrade(ctx context.Context, dockerCLI command.Cli, opts pluginOptions)
|
||||
}
|
||||
return err
|
||||
}
|
||||
defer responseBody.Close()
|
||||
defer func() {
|
||||
_ = responseBody.Close()
|
||||
}()
|
||||
if err := jsonstream.Display(ctx, responseBody, dockerCLI.Out()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user