Browse code

client: PluginInspectWithRaw: refactor and rename to PluginInspect

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/10/22 06:14:08
Showing 11 changed files
... ...
@@ -154,7 +154,7 @@ type PluginAPIClient interface {
154 154
 	PluginUpgrade(ctx context.Context, name string, options PluginInstallOptions) (io.ReadCloser, error)
155 155
 	PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error)
156 156
 	PluginSet(ctx context.Context, name string, args []string) error
157
-	PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error)
157
+	PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error)
158 158
 	PluginCreate(ctx context.Context, createContext io.Reader, options PluginCreateOptions) error
159 159
 }
160 160
 
... ...
@@ -1,32 +1,35 @@
1 1
 package client
2 2
 
3 3
 import (
4
-	"bytes"
5 4
 	"context"
6
-	"encoding/json"
7
-	"io"
8 5
 
9 6
 	"github.com/moby/moby/api/types/plugin"
10 7
 )
11 8
 
12
-// PluginInspectWithRaw inspects an existing plugin
13
-func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) {
9
+// PluginInspectOptions holds parameters to inspect a plugin.
10
+type PluginInspectOptions struct {
11
+	// Add future optional parameters here
12
+}
13
+
14
+// PluginInspectResult holds the result from the [Client.PluginInspect] method.
15
+type PluginInspectResult struct {
16
+	Raw    []byte
17
+	Plugin plugin.Plugin
18
+}
19
+
20
+// PluginInspect inspects an existing plugin
21
+func (cli *Client) PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error) {
14 22
 	name, err := trimID("plugin", name)
15 23
 	if err != nil {
16
-		return nil, nil, err
24
+		return PluginInspectResult{}, err
17 25
 	}
18 26
 	resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil)
19 27
 	defer ensureReaderClosed(resp)
20 28
 	if err != nil {
21
-		return nil, nil, err
29
+		return PluginInspectResult{}, err
22 30
 	}
23 31
 
24
-	body, err := io.ReadAll(resp.Body)
25
-	if err != nil {
26
-		return nil, nil, err
27
-	}
28
-	var p plugin.Plugin
29
-	rdr := bytes.NewReader(body)
30
-	err = json.NewDecoder(rdr).Decode(&p)
31
-	return &p, body, err
32
+	var out PluginInspectResult
33
+	out.Raw, err = decodeWithRaw(resp, &out.Plugin)
34
+	return out, err
32 35
 }
... ...
@@ -2,7 +2,6 @@ package client
2 2
 
3 3
 import (
4 4
 	"bytes"
5
-	"context"
6 5
 	"encoding/json"
7 6
 	"errors"
8 7
 	"io"
... ...
@@ -19,7 +18,7 @@ func TestPluginInspectError(t *testing.T) {
19 19
 	client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
20 20
 	assert.NilError(t, err)
21 21
 
22
-	_, _, err = client.PluginInspectWithRaw(context.Background(), "nothing")
22
+	_, err = client.PluginInspect(t.Context(), "nothing", PluginInspectOptions{})
23 23
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
24 24
 }
25 25
 
... ...
@@ -28,11 +27,11 @@ func TestPluginInspectWithEmptyID(t *testing.T) {
28 28
 		return nil, errors.New("should not make request")
29 29
 	}))
30 30
 	assert.NilError(t, err)
31
-	_, _, err = client.PluginInspectWithRaw(context.Background(), "")
31
+	_, err = client.PluginInspect(t.Context(), "", PluginInspectOptions{})
32 32
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
33 33
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
34 34
 
35
-	_, _, err = client.PluginInspectWithRaw(context.Background(), "    ")
35
+	_, err = client.PluginInspect(t.Context(), "    ", PluginInspectOptions{})
36 36
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
37 37
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
38 38
 }
... ...
@@ -56,7 +55,7 @@ func TestPluginInspect(t *testing.T) {
56 56
 	}))
57 57
 	assert.NilError(t, err)
58 58
 
59
-	pluginInspect, _, err := client.PluginInspectWithRaw(context.Background(), "plugin_name")
59
+	resp, err := client.PluginInspect(t.Context(), "plugin_name", PluginInspectOptions{})
60 60
 	assert.NilError(t, err)
61
-	assert.Check(t, is.Equal(pluginInspect.ID, "plugin_id"))
61
+	assert.Check(t, is.Equal(resp.Plugin.ID, "plugin_id"))
62 62
 }
... ...
@@ -67,12 +67,12 @@ func (d *Daemon) CheckServiceUpdateState(ctx context.Context, service string) fu
67 67
 func (d *Daemon) CheckPluginRunning(ctx context.Context, plugin string) func(c *testing.T) (any, string) {
68 68
 	return func(t *testing.T) (any, string) {
69 69
 		apiclient := d.NewClientT(t)
70
-		resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin)
70
+		resp, err := apiclient.PluginInspect(ctx, plugin, client.PluginInspectOptions{})
71 71
 		if cerrdefs.IsNotFound(err) {
72 72
 			return false, fmt.Sprintf("%v", err)
73 73
 		}
74 74
 		assert.NilError(t, err)
75
-		return resp.Enabled, fmt.Sprintf("%+v", resp)
75
+		return resp.Plugin.Enabled, fmt.Sprintf("%+v", resp.Plugin)
76 76
 	}
77 77
 }
78 78
 
... ...
@@ -80,12 +80,12 @@ func (d *Daemon) CheckPluginRunning(ctx context.Context, plugin string) func(c *
80 80
 func (d *Daemon) CheckPluginImage(ctx context.Context, plugin string) func(c *testing.T) (any, string) {
81 81
 	return func(t *testing.T) (any, string) {
82 82
 		apiclient := d.NewClientT(t)
83
-		resp, _, err := apiclient.PluginInspectWithRaw(ctx, plugin)
83
+		resp, err := apiclient.PluginInspect(ctx, plugin, client.PluginInspectOptions{})
84 84
 		if cerrdefs.IsNotFound(err) {
85 85
 			return false, fmt.Sprintf("%v", err)
86 86
 		}
87 87
 		assert.NilError(t, err)
88
-		return resp.PluginReference, fmt.Sprintf("%+v", resp)
88
+		return resp.Plugin.PluginReference, fmt.Sprintf("%+v", resp.Plugin)
89 89
 	}
90 90
 }
91 91
 
... ...
@@ -2225,11 +2225,11 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) {
2225 2225
 
2226 2226
 	ctx, cancel = context.WithTimeout(testutil.GetContext(c), 30*time.Second)
2227 2227
 	defer cancel()
2228
-	p, _, err := apiClient.PluginInspectWithRaw(ctx, name)
2228
+	res, err := apiClient.PluginInspect(ctx, name, client.PluginInspectOptions{})
2229 2229
 	assert.NilError(c, err)
2230 2230
 
2231 2231
 	// simulate a bad/partial removal by removing the plugin config.
2232
-	configPath := filepath.Join(d.Root, "plugins", p.ID, "config.json")
2232
+	configPath := filepath.Join(d.Root, "plugins", res.Plugin.ID, "config.json")
2233 2233
 	assert.NilError(c, os.Remove(configPath))
2234 2234
 
2235 2235
 	d.Restart(c)
... ...
@@ -2238,7 +2238,7 @@ func (s *DockerDaemonSuite) TestFailedPluginRemove(c *testing.T) {
2238 2238
 	_, err = apiClient.Ping(ctx)
2239 2239
 	assert.NilError(c, err)
2240 2240
 
2241
-	_, _, err = apiClient.PluginInspectWithRaw(ctx, name)
2241
+	_, err = apiClient.PluginInspect(ctx, name, client.PluginInspectOptions{})
2242 2242
 	// plugin should be gone since the config.json is gone
2243 2243
 	assert.ErrorContains(c, err, "")
2244 2244
 }
... ...
@@ -120,7 +120,7 @@ func TestPluginInstall(t *testing.T) {
120 120
 		_, err = io.Copy(io.Discard, rdr)
121 121
 		assert.NilError(t, err)
122 122
 
123
-		_, _, err = apiclient.PluginInspectWithRaw(ctx, repo)
123
+		_, err = apiclient.PluginInspect(ctx, repo, client.PluginInspectOptions{})
124 124
 		assert.NilError(t, err)
125 125
 	})
126 126
 
... ...
@@ -163,7 +163,7 @@ func TestPluginInstall(t *testing.T) {
163 163
 		_, err = io.Copy(io.Discard, rdr)
164 164
 		assert.NilError(t, err)
165 165
 
166
-		_, _, err = apiclient.PluginInspectWithRaw(ctx, repo)
166
+		_, err = apiclient.PluginInspect(ctx, repo, client.PluginInspectOptions{})
167 167
 		assert.NilError(t, err)
168 168
 	})
169 169
 
... ...
@@ -192,7 +192,7 @@ func TestPluginInstall(t *testing.T) {
192 192
 		_, err = io.Copy(io.Discard, rdr)
193 193
 		assert.NilError(t, err)
194 194
 
195
-		_, _, err = apiclient.PluginInspectWithRaw(ctx, repo)
195
+		_, err = apiclient.PluginInspect(ctx, repo, client.PluginInspectOptions{})
196 196
 		assert.NilError(t, err)
197 197
 	})
198 198
 	t.Run("with insecure", func(t *testing.T) {
... ...
@@ -234,15 +234,15 @@ func TestPluginInstall(t *testing.T) {
234 234
 		repo := path.Join(regURL, name+":latest")
235 235
 		assert.NilError(t, plugin.CreateInRegistry(ctx, repo, nil, plugin.WithInsecureRegistry(regURL)))
236 236
 
237
-		apiclient := d.NewClientT(t)
238
-		rdr, err := apiclient.PluginInstall(ctx, repo, client.PluginInstallOptions{Disabled: true, RemoteRef: repo})
237
+		apiClient := d.NewClientT(t)
238
+		rdr, err := apiClient.PluginInstall(ctx, repo, client.PluginInstallOptions{Disabled: true, RemoteRef: repo})
239 239
 		assert.NilError(t, err)
240 240
 		defer rdr.Close()
241 241
 
242 242
 		_, err = io.Copy(io.Discard, rdr)
243 243
 		assert.NilError(t, err)
244 244
 
245
-		_, _, err = apiclient.PluginInspectWithRaw(ctx, repo)
245
+		_, err = apiClient.PluginInspect(ctx, repo, client.PluginInspectOptions{})
246 246
 		assert.NilError(t, err)
247 247
 	})
248 248
 	// TODO: test insecure registry with https
... ...
@@ -54,7 +54,7 @@ func TestPluginWithDevMounts(t *testing.T) {
54 54
 		assert.Check(t, err)
55 55
 	}()
56 56
 
57
-	p, _, err := c.PluginInspectWithRaw(ctx, "test")
57
+	resp, err := c.PluginInspect(ctx, "test", client.PluginInspectOptions{})
58 58
 	assert.NilError(t, err)
59
-	assert.Assert(t, p.Enabled)
59
+	assert.Assert(t, resp.Plugin.Enabled)
60 60
 }
... ...
@@ -72,10 +72,10 @@ func TestServicePlugin(t *testing.T) {
72 72
 		t.Log("No tasks found for plugin service")
73 73
 		t.Fail()
74 74
 	}
75
-	p, _, err := d1.NewClientT(t).PluginInspectWithRaw(ctx, name)
75
+	res, err := d1.NewClientT(t).PluginInspect(ctx, name, client.PluginInspectOptions{})
76 76
 	assert.NilError(t, err, "Error inspecting service plugin")
77 77
 	found := false
78
-	for _, env := range p.Settings.Env {
78
+	for _, env := range res.Plugin.Settings.Env {
79 79
 		assert.Equal(t, strings.HasPrefix(env, "baz"), false, "Environment variable entry %q is invalid and should not be present", "baz")
80 80
 		if strings.HasPrefix(env, "foo=") {
81 81
 			found = true
... ...
@@ -33,7 +33,7 @@ func (d *Daemon) PluginIsNotRunning(t testing.TB, name string) func(poll.LogT) p
33 33
 // PluginIsNotPresent provides a poller to check if the specified plugin is not present
34 34
 func (d *Daemon) PluginIsNotPresent(t testing.TB, name string) func(poll.LogT) poll.Result {
35 35
 	return withClient(t, d, func(c client.APIClient, t poll.LogT) poll.Result {
36
-		_, _, err := c.PluginInspectWithRaw(context.Background(), name)
36
+		_, err := c.PluginInspect(context.Background(), name, client.PluginInspectOptions{})
37 37
 		if cerrdefs.IsNotFound(err) {
38 38
 			return poll.Success()
39 39
 		}
... ...
@@ -56,14 +56,14 @@ func (d *Daemon) PluginReferenceIs(t testing.TB, name, expectedRef string) func(
56 56
 
57 57
 func withPluginInspect(name string, f func(*plugin.Plugin, poll.LogT) poll.Result) func(client.APIClient, poll.LogT) poll.Result {
58 58
 	return func(c client.APIClient, t poll.LogT) poll.Result {
59
-		p, _, err := c.PluginInspectWithRaw(context.Background(), name)
59
+		res, err := c.PluginInspect(context.Background(), name, client.PluginInspectOptions{})
60 60
 		if cerrdefs.IsNotFound(err) {
61 61
 			return poll.Continue("plugin %q not found", name)
62 62
 		}
63 63
 		if err != nil {
64 64
 			return poll.Error(err)
65 65
 		}
66
-		return f(p, t)
66
+		return f(&res.Plugin, t)
67 67
 	}
68 68
 }
69 69
 
... ...
@@ -154,7 +154,7 @@ type PluginAPIClient interface {
154 154
 	PluginUpgrade(ctx context.Context, name string, options PluginInstallOptions) (io.ReadCloser, error)
155 155
 	PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error)
156 156
 	PluginSet(ctx context.Context, name string, args []string) error
157
-	PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error)
157
+	PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error)
158 158
 	PluginCreate(ctx context.Context, createContext io.Reader, options PluginCreateOptions) error
159 159
 }
160 160
 
... ...
@@ -1,32 +1,35 @@
1 1
 package client
2 2
 
3 3
 import (
4
-	"bytes"
5 4
 	"context"
6
-	"encoding/json"
7
-	"io"
8 5
 
9 6
 	"github.com/moby/moby/api/types/plugin"
10 7
 )
11 8
 
12
-// PluginInspectWithRaw inspects an existing plugin
13
-func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*plugin.Plugin, []byte, error) {
9
+// PluginInspectOptions holds parameters to inspect a plugin.
10
+type PluginInspectOptions struct {
11
+	// Add future optional parameters here
12
+}
13
+
14
+// PluginInspectResult holds the result from the [Client.PluginInspect] method.
15
+type PluginInspectResult struct {
16
+	Raw    []byte
17
+	Plugin plugin.Plugin
18
+}
19
+
20
+// PluginInspect inspects an existing plugin
21
+func (cli *Client) PluginInspect(ctx context.Context, name string, options PluginInspectOptions) (PluginInspectResult, error) {
14 22
 	name, err := trimID("plugin", name)
15 23
 	if err != nil {
16
-		return nil, nil, err
24
+		return PluginInspectResult{}, err
17 25
 	}
18 26
 	resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil)
19 27
 	defer ensureReaderClosed(resp)
20 28
 	if err != nil {
21
-		return nil, nil, err
29
+		return PluginInspectResult{}, err
22 30
 	}
23 31
 
24
-	body, err := io.ReadAll(resp.Body)
25
-	if err != nil {
26
-		return nil, nil, err
27
-	}
28
-	var p plugin.Plugin
29
-	rdr := bytes.NewReader(body)
30
-	err = json.NewDecoder(rdr).Decode(&p)
31
-	return &p, body, err
32
+	var out PluginInspectResult
33
+	out.Raw, err = decodeWithRaw(resp, &out.Plugin)
34
+	return out, err
32 35
 }