From ebc92e015a594dfb5aaac6b15ede661ff9b01a80 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 21 Oct 2025 23:14:08 +0200 Subject: [PATCH] client: PluginInspectWithRaw: refactor and rename to PluginInspect Signed-off-by: Sebastiaan van Stijn --- client/client_interfaces.go | 2 +- client/plugin_inspect.go | 33 ++++++++++--------- client/plugin_inspect_test.go | 11 +++---- integration-cli/daemon/daemon_swarm.go | 8 ++--- integration-cli/docker_cli_daemon_test.go | 6 ++-- integration/plugin/common/plugin_test.go | 12 +++---- integration/plugin/volumes/mounts_test.go | 4 +-- integration/service/plugin_test.go | 4 +-- internal/testutil/daemon/plugin.go | 6 ++-- .../moby/moby/client/client_interfaces.go | 2 +- .../moby/moby/client/plugin_inspect.go | 33 ++++++++++--------- 11 files changed, 63 insertions(+), 58 deletions(-) diff --git a/client/client_interfaces.go b/client/client_interfaces.go index 7a42b13e51..5851f5b034 100644 --- a/client/client_interfaces.go +++ b/client/client_interfaces.go @@ -154,7 +154,7 @@ type PluginAPIClient interface { PluginUpgrade(ctx context.Context, name string, options PluginInstallOptions) (io.ReadCloser, error) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) PluginSet(ctx context.Context, name string, args []string) error - PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) + PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error) PluginCreate(ctx context.Context, createContext io.Reader, options PluginCreateOptions) error } diff --git a/client/plugin_inspect.go b/client/plugin_inspect.go index da30f15458..e6853e644d 100644 --- a/client/plugin_inspect.go +++ b/client/plugin_inspect.go @@ -1,32 +1,35 @@ package client import ( - "bytes" "context" - "encoding/json" - "io" "github.com/moby/moby/api/types/plugin" ) -// PluginInspectWithRaw inspects an existing plugin -func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) { +// PluginInspectOptions holds parameters to inspect a plugin. +type PluginInspectOptions struct { + // Add future optional parameters here +} + +// PluginInspectResult holds the result from the [Client.PluginInspect] method. +type PluginInspectResult struct { + Raw []byte + Plugin plugin.Plugin +} + +// PluginInspect inspects an existing plugin +func (cli *Client) PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error) { name, err := trimID("plugin", name) if err != nil { - return nil, nil, err + return PluginInspectResult{}, err } resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, nil, err + return PluginInspectResult{}, err } - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, nil, err - } - var p plugin.Plugin - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&p) - return &p, body, err + var out PluginInspectResult + out.Raw, err = decodeWithRaw(resp, &out.Plugin) + return out, err } diff --git a/client/plugin_inspect_test.go b/client/plugin_inspect_test.go index 7723f48c25..8b1d00599a 100644 --- a/client/plugin_inspect_test.go +++ b/client/plugin_inspect_test.go @@ -2,7 +2,6 @@ package client import ( "bytes" - "context" "encoding/json" "errors" "io" @@ -19,7 +18,7 @@ func TestPluginInspectError(t *testing.T) { client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error"))) assert.NilError(t, err) - _, _, err = client.PluginInspectWithRaw(context.Background(), "nothing") + _, err = client.PluginInspect(t.Context(), "nothing", PluginInspectOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal)) } @@ -28,11 +27,11 @@ func TestPluginInspectWithEmptyID(t *testing.T) { return nil, errors.New("should not make request") })) assert.NilError(t, err) - _, _, err = client.PluginInspectWithRaw(context.Background(), "") + _, err = client.PluginInspect(t.Context(), "", PluginInspectOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) - _, _, err = client.PluginInspectWithRaw(context.Background(), " ") + _, err = client.PluginInspect(t.Context(), " ", PluginInspectOptions{}) assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument)) assert.Check(t, is.ErrorContains(err, "value is empty")) } @@ -56,7 +55,7 @@ func TestPluginInspect(t *testing.T) { })) assert.NilError(t, err) - pluginInspect, _, err := client.PluginInspectWithRaw(context.Background(), "plugin_name") + resp, err := client.PluginInspect(t.Context(), "plugin_name", PluginInspectOptions{}) assert.NilError(t, err) - assert.Check(t, is.Equal(pluginInspect.ID, "plugin_id")) + assert.Check(t, is.Equal(resp.Plugin.ID, "plugin_id")) } diff --git a/integration-cli/daemon/daemon_swarm.go b/integration-cli/daemon/daemon_swarm.go index e12276885d..ab363b59f4 100644 --- a/integration-cli/daemon/daemon_swarm.go +++ b/integration-cli/daemon/daemon_swarm.go @@ -67,12 +67,12 @@ func (d *Daemon) CheckServiceUpdateState(ctx context.Context, service string) fu func (d *Daemon) CheckPluginRunning(ctx context.Context, plugin string) func(c *testing.T) (any, string) { return func(t *testing.T) (any, string) { apiclient := d.NewClientT(t) - resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin) + resp, err := apiclient.PluginInspect(ctx, plugin, client.PluginInspectOptions{}) if cerrdefs.IsNotFound(err) { return false, fmt.Sprintf("%v", err) } assert.NilError(t, err) - return resp.Enabled, fmt.Sprintf("%+v", resp) + return resp.Plugin.Enabled, fmt.Sprintf("%+v", resp.Plugin) } } @@ -80,12 +80,12 @@ func (d *Daemon) CheckPluginRunning(ctx context.Context, plugin string) func(c * func (d *Daemon) CheckPluginImage(ctx context.Context, plugin string) func(c *testing.T) (any, string) { return func(t *testing.T) (any, string) { apiclient := d.NewClientT(t) - resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin) + resp, err := apiclient.PluginInspect(ctx, plugin, client.PluginInspectOptions{}) if cerrdefs.IsNotFound(err) { return false, fmt.Sprintf("%v", err) } assert.NilError(t, err) - return resp.PluginReference, fmt.Sprintf("%+v", resp) + return resp.Plugin.PluginReference, fmt.Sprintf("%+v", resp.Plugin) } } diff --git a/integration-cli/docker_cli_daemon_test.go b/integration-cli/docker_cli_daemon_test.go index 87ba1be002..f8f8d155b8 100644 --- a/integration-cli/docker_cli_daemon_test.go +++ b/integration-cli/docker_cli_daemon_test.go @@ -2225,11 +2225,11 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) { ctx, cancel = context.WithTimeout(testutil.GetContext(c), 30*time.Second) defer cancel() - p, _, err := apiClient.PluginInspectWithRaw(ctx, name) + res, err := apiClient.PluginInspect(ctx, name, client.PluginInspectOptions{}) assert.NilError(c, err) // simulate a bad/partial removal by removing the plugin config. - configPath := filepath.Join(d.Root, "plugins", p.ID, "config.json") + configPath := filepath.Join(d.Root, "plugins", res.Plugin.ID, "config.json") assert.NilError(c, os.Remove(configPath)) d.Restart(c) @@ -2238,7 +2238,7 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) { _, err = apiClient.Ping(ctx) assert.NilError(c, err) - _, _, err = apiClient.PluginInspectWithRaw(ctx, name) + _, err = apiClient.PluginInspect(ctx, name, client.PluginInspectOptions{}) // plugin should be gone since the config.json is gone assert.ErrorContains(c, err, "") } diff --git a/integration/plugin/common/plugin_test.go b/integration/plugin/common/plugin_test.go index edb77b8cfa..c3e76e0618 100644 --- a/integration/plugin/common/plugin_test.go +++ b/integration/plugin/common/plugin_test.go @@ -120,7 +120,7 @@ func TestPluginInstall(t *testing.T) { _, err = io.Copy(io.Discard, rdr) assert.NilError(t, err) - _, _, err = apiclient.PluginInspectWithRaw(ctx, repo) + _, err = apiclient.PluginInspect(ctx, repo, client.PluginInspectOptions{}) assert.NilError(t, err) }) @@ -163,7 +163,7 @@ func TestPluginInstall(t *testing.T) { _, err = io.Copy(io.Discard, rdr) assert.NilError(t, err) - _, _, err = apiclient.PluginInspectWithRaw(ctx, repo) + _, err = apiclient.PluginInspect(ctx, repo, client.PluginInspectOptions{}) assert.NilError(t, err) }) @@ -192,7 +192,7 @@ func TestPluginInstall(t *testing.T) { _, err = io.Copy(io.Discard, rdr) assert.NilError(t, err) - _, _, err = apiclient.PluginInspectWithRaw(ctx, repo) + _, err = apiclient.PluginInspect(ctx, repo, client.PluginInspectOptions{}) assert.NilError(t, err) }) t.Run("with insecure", func(t *testing.T) { @@ -234,15 +234,15 @@ func TestPluginInstall(t *testing.T) { repo := path.Join(regURL, name+":latest") assert.NilError(t, plugin.CreateInRegistry(ctx, repo, nil, plugin.WithInsecureRegistry(regURL))) - apiclient := d.NewClientT(t) - rdr, err := apiclient.PluginInstall(ctx, repo, client.PluginInstallOptions{Disabled: true, RemoteRef: repo}) + apiClient := d.NewClientT(t) + rdr, err := apiClient.PluginInstall(ctx, repo, client.PluginInstallOptions{Disabled: true, RemoteRef: repo}) assert.NilError(t, err) defer rdr.Close() _, err = io.Copy(io.Discard, rdr) assert.NilError(t, err) - _, _, err = apiclient.PluginInspectWithRaw(ctx, repo) + _, err = apiClient.PluginInspect(ctx, repo, client.PluginInspectOptions{}) assert.NilError(t, err) }) // TODO: test insecure registry with https diff --git a/integration/plugin/volumes/mounts_test.go b/integration/plugin/volumes/mounts_test.go index 17a6ab557f..aa818e0314 100644 --- a/integration/plugin/volumes/mounts_test.go +++ b/integration/plugin/volumes/mounts_test.go @@ -54,7 +54,7 @@ func TestPluginWithDevMounts(t *testing.T) { assert.Check(t, err) }() - p, _, err := c.PluginInspectWithRaw(ctx, "test") + resp, err := c.PluginInspect(ctx, "test", client.PluginInspectOptions{}) assert.NilError(t, err) - assert.Assert(t, p.Enabled) + assert.Assert(t, resp.Plugin.Enabled) } diff --git a/integration/service/plugin_test.go b/integration/service/plugin_test.go index 67cdc89fdb..770ab4eb09 100644 --- a/integration/service/plugin_test.go +++ b/integration/service/plugin_test.go @@ -72,10 +72,10 @@ func TestServicePlugin(t *testing.T) { t.Log("No tasks found for plugin service") t.Fail() } - p, _, err := d1.NewClientT(t).PluginInspectWithRaw(ctx, name) + res, err := d1.NewClientT(t).PluginInspect(ctx, name, client.PluginInspectOptions{}) assert.NilError(t, err, "Error inspecting service plugin") found := false - for _, env := range p.Settings.Env { + for _, env := range res.Plugin.Settings.Env { assert.Equal(t, strings.HasPrefix(env, "baz"), false, "Environment variable entry %q is invalid and should not be present", "baz") if strings.HasPrefix(env, "foo=") { found = true diff --git a/internal/testutil/daemon/plugin.go b/internal/testutil/daemon/plugin.go index d3e8a9f1f7..fb25c10b85 100644 --- a/internal/testutil/daemon/plugin.go +++ b/internal/testutil/daemon/plugin.go @@ -33,7 +33,7 @@ func (d *Daemon) PluginIsNotRunning(t testing.TB, name string) func(poll.LogT) p // PluginIsNotPresent provides a poller to check if the specified plugin is not present func (d *Daemon) PluginIsNotPresent(t testing.TB, name string) func(poll.LogT) poll.Result { return withClient(t, d, func(c client.APIClient, t poll.LogT) poll.Result { - _, _, err := c.PluginInspectWithRaw(context.Background(), name) + _, err := c.PluginInspect(context.Background(), name, client.PluginInspectOptions{}) if cerrdefs.IsNotFound(err) { return poll.Success() } @@ -56,14 +56,14 @@ func (d *Daemon) PluginReferenceIs(t testing.TB, name, expectedRef string) func( func withPluginInspect(name string, f func(*plugin.Plugin, poll.LogT) poll.Result) func(client.APIClient, poll.LogT) poll.Result { return func(c client.APIClient, t poll.LogT) poll.Result { - p, _, err := c.PluginInspectWithRaw(context.Background(), name) + res, err := c.PluginInspect(context.Background(), name, client.PluginInspectOptions{}) if cerrdefs.IsNotFound(err) { return poll.Continue("plugin %q not found", name) } if err != nil { return poll.Error(err) } - return f(p, t) + return f(&res.Plugin, t) } } diff --git a/vendor/github.com/moby/moby/client/client_interfaces.go b/vendor/github.com/moby/moby/client/client_interfaces.go index 7a42b13e51..5851f5b034 100644 --- a/vendor/github.com/moby/moby/client/client_interfaces.go +++ b/vendor/github.com/moby/moby/client/client_interfaces.go @@ -154,7 +154,7 @@ type PluginAPIClient interface { PluginUpgrade(ctx context.Context, name string, options PluginInstallOptions) (io.ReadCloser, error) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) PluginSet(ctx context.Context, name string, args []string) error - PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) + PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error) PluginCreate(ctx context.Context, createContext io.Reader, options PluginCreateOptions) error } diff --git a/vendor/github.com/moby/moby/client/plugin_inspect.go b/vendor/github.com/moby/moby/client/plugin_inspect.go index da30f15458..e6853e644d 100644 --- a/vendor/github.com/moby/moby/client/plugin_inspect.go +++ b/vendor/github.com/moby/moby/client/plugin_inspect.go @@ -1,32 +1,35 @@ package client import ( - "bytes" "context" - "encoding/json" - "io" "github.com/moby/moby/api/types/plugin" ) -// PluginInspectWithRaw inspects an existing plugin -func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) { +// PluginInspectOptions holds parameters to inspect a plugin. +type PluginInspectOptions struct { + // Add future optional parameters here +} + +// PluginInspectResult holds the result from the [Client.PluginInspect] method. +type PluginInspectResult struct { + Raw []byte + Plugin plugin.Plugin +} + +// PluginInspect inspects an existing plugin +func (cli *Client) PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error) { name, err := trimID("plugin", name) if err != nil { - return nil, nil, err + return PluginInspectResult{}, err } resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) defer ensureReaderClosed(resp) if err != nil { - return nil, nil, err + return PluginInspectResult{}, err } - body, err := io.ReadAll(resp.Body) - if err != nil { - return nil, nil, err - } - var p plugin.Plugin - rdr := bytes.NewReader(body) - err = json.NewDecoder(rdr).Decode(&p) - return &p, body, err + var out PluginInspectResult + out.Raw, err = decodeWithRaw(resp, &out.Plugin) + return out, err }