Browse code

client: refactor NetworkConnect, NetworkDisconnect, NetworkRemove

Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Austin Vazquez authored on 2025/10/22 21:39:57
Showing 34 changed files
... ...
@@ -117,12 +117,12 @@ type ImageAPIClient interface {
117 117
 
118 118
 // NetworkAPIClient defines API client methods for the networks
119 119
 type NetworkAPIClient interface {
120
-	NetworkConnect(ctx context.Context, network, container string, config *network.EndpointSettings) error
120
+	NetworkConnect(ctx context.Context, network string, options NetworkConnectOptions) (NetworkConnectResult, error)
121 121
 	NetworkCreate(ctx context.Context, name string, options NetworkCreateOptions) (network.CreateResponse, error)
122
-	NetworkDisconnect(ctx context.Context, network, container string, force bool) error
122
+	NetworkDisconnect(ctx context.Context, network string, options NetworkDisconnectOptions) (NetworkDisconnectResult, error)
123 123
 	NetworkInspect(ctx context.Context, network string, options NetworkInspectOptions) (NetworkInspectResult, error)
124 124
 	NetworkList(ctx context.Context, options NetworkListOptions) (NetworkListResult, error)
125
-	NetworkRemove(ctx context.Context, network string) error
125
+	NetworkRemove(ctx context.Context, network string, options NetworkRemoveOptions) (NetworkRemoveResult, error)
126 126
 	NetworksPrune(ctx context.Context, opts NetworkPruneOptions) (NetworkPruneResult, error)
127 127
 }
128 128
 
... ...
@@ -6,23 +6,35 @@ import (
6 6
 	"github.com/moby/moby/api/types/network"
7 7
 )
8 8
 
9
+// NetworkConnectOptions represents the data to be used to connect a container to the
10
+// network.
11
+type NetworkConnectOptions struct {
12
+	Container      string
13
+	EndpointConfig *network.EndpointSettings
14
+}
15
+
16
+// NetworkConnectResult represents the result of a NetworkConnect operation.
17
+type NetworkConnectResult struct {
18
+	// Currently empty; placeholder for future fields.
19
+}
20
+
9 21
 // NetworkConnect connects a container to an existent network in the docker host.
10
-func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error {
22
+func (cli *Client) NetworkConnect(ctx context.Context, networkID string, options NetworkConnectOptions) (NetworkConnectResult, error) {
11 23
 	networkID, err := trimID("network", networkID)
12 24
 	if err != nil {
13
-		return err
25
+		return NetworkConnectResult{}, err
14 26
 	}
15 27
 
16
-	containerID, err = trimID("container", containerID)
28
+	containerID, err := trimID("container", options.Container)
17 29
 	if err != nil {
18
-		return err
30
+		return NetworkConnectResult{}, err
19 31
 	}
20 32
 
21
-	req := network.ConnectRequest{
33
+	nc := network.ConnectRequest{
22 34
 		Container:      containerID,
23
-		EndpointConfig: config,
35
+		EndpointConfig: options.EndpointConfig,
24 36
 	}
25
-	resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, req, nil)
37
+	resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil)
26 38
 	defer ensureReaderClosed(resp)
27
-	return err
39
+	return NetworkConnectResult{}, err
28 40
 }
29 41
deleted file mode 100644
... ...
@@ -1,10 +0,0 @@
1
-package client
2
-
3
-import "github.com/moby/moby/api/types/network"
4
-
5
-// NetworkConnectOptions represents the data to be used to connect a container to the
6
-// network.
7
-type NetworkConnectOptions struct {
8
-	Container      string
9
-	EndpointConfig *network.EndpointSettings `json:",omitempty"`
10
-}
... ...
@@ -17,15 +17,19 @@ func TestNetworkConnectError(t *testing.T) {
17 17
 	client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
18 18
 	assert.NilError(t, err)
19 19
 
20
-	err = client.NetworkConnect(context.Background(), "network_id", "container_id", nil)
20
+	_, err = client.NetworkConnect(context.Background(), "network_id", NetworkConnectOptions{
21
+		Container: "container_id",
22
+	})
21 23
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
22 24
 
23 25
 	// Empty network ID or container ID
24
-	err = client.NetworkConnect(context.Background(), "", "container_id", nil)
26
+	_, err = client.NetworkConnect(context.Background(), "", NetworkConnectOptions{
27
+		Container: "container_id",
28
+	})
25 29
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
26 30
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
27 31
 
28
-	err = client.NetworkConnect(context.Background(), "network_id", "", nil)
32
+	_, err = client.NetworkConnect(context.Background(), "network_id", NetworkConnectOptions{})
29 33
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
30 34
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
31 35
 }
... ...
@@ -55,7 +59,9 @@ func TestNetworkConnectEmptyNilEndpointSettings(t *testing.T) {
55 55
 	}))
56 56
 	assert.NilError(t, err)
57 57
 
58
-	err = client.NetworkConnect(context.Background(), "network_id", "container_id", nil)
58
+	_, err = client.NetworkConnect(context.Background(), "network_id", NetworkConnectOptions{
59
+		Container: "container_id",
60
+	})
59 61
 	assert.NilError(t, err)
60 62
 }
61 63
 
... ...
@@ -67,7 +73,7 @@ func TestNetworkConnect(t *testing.T) {
67 67
 			return nil, err
68 68
 		}
69 69
 
70
-		var connect NetworkConnectOptions
70
+		var connect network.ConnectRequest
71 71
 		if err := json.NewDecoder(req.Body).Decode(&connect); err != nil {
72 72
 			return nil, err
73 73
 		}
... ...
@@ -88,8 +94,11 @@ func TestNetworkConnect(t *testing.T) {
88 88
 	}))
89 89
 	assert.NilError(t, err)
90 90
 
91
-	err = client.NetworkConnect(context.Background(), "network_id", "container_id", &network.EndpointSettings{
92
-		NetworkID: "NetworkID",
91
+	_, err = client.NetworkConnect(context.Background(), "network_id", NetworkConnectOptions{
92
+		Container: "container_id",
93
+		EndpointConfig: &network.EndpointSettings{
94
+			NetworkID: "NetworkID",
95
+		},
93 96
 	})
94 97
 	assert.NilError(t, err)
95 98
 }
... ...
@@ -6,23 +6,35 @@ import (
6 6
 	"github.com/moby/moby/api/types/network"
7 7
 )
8 8
 
9
+// NetworkDisconnectOptions represents the data to be used to disconnect a container
10
+// from the network.
11
+type NetworkDisconnectOptions struct {
12
+	Container string
13
+	Force     bool
14
+}
15
+
16
+// NetworkDisconnectResult represents the result of a NetworkDisconnect operation.
17
+type NetworkDisconnectResult struct {
18
+	// Currently empty; placeholder for future fields.
19
+}
20
+
9 21
 // NetworkDisconnect disconnects a container from an existent network in the docker host.
10
-func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error {
22
+func (cli *Client) NetworkDisconnect(ctx context.Context, networkID string, options NetworkDisconnectOptions) (NetworkDisconnectResult, error) {
11 23
 	networkID, err := trimID("network", networkID)
12 24
 	if err != nil {
13
-		return err
25
+		return NetworkDisconnectResult{}, err
14 26
 	}
15 27
 
16
-	containerID, err = trimID("container", containerID)
28
+	containerID, err := trimID("container", options.Container)
17 29
 	if err != nil {
18
-		return err
30
+		return NetworkDisconnectResult{}, err
19 31
 	}
20 32
 
21 33
 	req := network.DisconnectRequest{
22 34
 		Container: containerID,
23
-		Force:     force,
35
+		Force:     options.Force,
24 36
 	}
25 37
 	resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, req, nil)
26 38
 	defer ensureReaderClosed(resp)
27
-	return err
39
+	return NetworkDisconnectResult{}, err
28 40
 }
29 41
deleted file mode 100644
... ...
@@ -1,8 +0,0 @@
1
-package client
2
-
3
-// NetworkDisconnectOptions represents the data to be used to disconnect a container
4
-// from the network.
5
-type NetworkDisconnectOptions struct {
6
-	Container string
7
-	Force     bool
8
-}
... ...
@@ -17,15 +17,19 @@ func TestNetworkDisconnectError(t *testing.T) {
17 17
 	client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
18 18
 	assert.NilError(t, err)
19 19
 
20
-	err = client.NetworkDisconnect(context.Background(), "network_id", "container_id", false)
20
+	_, err = client.NetworkDisconnect(context.Background(), "network_id", NetworkDisconnectOptions{
21
+		Container: "container_id",
22
+	})
21 23
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
22 24
 
23 25
 	// Empty network ID or container ID
24
-	err = client.NetworkDisconnect(context.Background(), "", "container_id", false)
26
+	_, err = client.NetworkDisconnect(context.Background(), "", NetworkDisconnectOptions{
27
+		Container: "container_id",
28
+	})
25 29
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
26 30
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
27 31
 
28
-	err = client.NetworkDisconnect(context.Background(), "network_id", "", false)
32
+	_, err = client.NetworkDisconnect(context.Background(), "network_id", NetworkDisconnectOptions{})
29 33
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
30 34
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
31 35
 }
... ...
@@ -55,6 +59,6 @@ func TestNetworkDisconnect(t *testing.T) {
55 55
 	}))
56 56
 	assert.NilError(t, err)
57 57
 
58
-	err = client.NetworkDisconnect(context.Background(), "network_id", "container_id", true)
58
+	_, err = client.NetworkDisconnect(context.Background(), "network_id", NetworkDisconnectOptions{Container: "container_id", Force: true})
59 59
 	assert.NilError(t, err)
60 60
 }
... ...
@@ -1,14 +1,26 @@
1 1
 package client
2 2
 
3
-import "context"
3
+import (
4
+	"context"
5
+)
6
+
7
+// NetworkRemoveOptions specifies options for removing a network.
8
+type NetworkRemoveOptions struct {
9
+	// No options currently; placeholder for future use.
10
+}
11
+
12
+// NetworkRemoveResult represents the result of a network removal operation.
13
+type NetworkRemoveResult struct {
14
+	// No fields currently; placeholder for future use.
15
+}
4 16
 
5 17
 // NetworkRemove removes an existent network from the docker host.
6
-func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
18
+func (cli *Client) NetworkRemove(ctx context.Context, networkID string, options NetworkRemoveOptions) (NetworkRemoveResult, error) {
7 19
 	networkID, err := trimID("network", networkID)
8 20
 	if err != nil {
9
-		return err
21
+		return NetworkRemoveResult{}, err
10 22
 	}
11 23
 	resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil)
12 24
 	defer ensureReaderClosed(resp)
13
-	return err
25
+	return NetworkRemoveResult{}, err
14 26
 }
... ...
@@ -14,14 +14,14 @@ func TestNetworkRemoveError(t *testing.T) {
14 14
 	client, err := NewClientWithOpts(WithMockClient(errorMock(http.StatusInternalServerError, "Server error")))
15 15
 	assert.NilError(t, err)
16 16
 
17
-	err = client.NetworkRemove(context.Background(), "network_id")
17
+	_, err = client.NetworkRemove(context.Background(), "network_id", NetworkRemoveOptions{})
18 18
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
19 19
 
20
-	err = client.NetworkRemove(context.Background(), "")
20
+	_, err = client.NetworkRemove(context.Background(), "", NetworkRemoveOptions{})
21 21
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
22 22
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
23 23
 
24
-	err = client.NetworkRemove(context.Background(), "    ")
24
+	_, err = client.NetworkRemove(context.Background(), "    ", NetworkRemoveOptions{})
25 25
 	assert.Check(t, is.ErrorType(err, cerrdefs.IsInvalidArgument))
26 26
 	assert.Check(t, is.ErrorContains(err, "value is empty"))
27 27
 }
... ...
@@ -37,6 +37,6 @@ func TestNetworkRemove(t *testing.T) {
37 37
 	}))
38 38
 	assert.NilError(t, err)
39 39
 
40
-	err = client.NetworkRemove(context.Background(), "network_id")
40
+	_, err = client.NetworkRemove(context.Background(), "network_id", NetworkRemoveOptions{})
41 41
 	assert.NilError(t, err)
42 42
 }
... ...
@@ -2,16 +2,16 @@ package networkbackend
2 2
 
3 3
 import "github.com/moby/moby/api/types/network"
4 4
 
5
-// ConnectOptions represents the data to be used to connect a container to the
5
+// ConnectRequest represents the data to be used to connect a container to the
6 6
 // network.
7
-type ConnectOptions struct {
7
+type ConnectRequest struct {
8 8
 	Container      string
9 9
 	EndpointConfig *network.EndpointSettings `json:",omitempty"`
10 10
 }
11 11
 
12
-// DisconnectOptions represents the data to be used to disconnect a container
12
+// DisconnectRequest represents the data to be used to disconnect a container
13 13
 // from the network.
14
-type DisconnectOptions struct {
14
+type DisconnectRequest struct {
15 15
 	Container string
16 16
 	Force     bool
17 17
 }
... ...
@@ -287,7 +287,7 @@ func (n *networkRouter) postNetworkConnect(ctx context.Context, w http.ResponseW
287 287
 		return err
288 288
 	}
289 289
 
290
-	var connect networkbackend.ConnectOptions
290
+	var connect networkbackend.ConnectRequest
291 291
 	if err := httputils.ReadJSON(r, &connect); err != nil {
292 292
 		return err
293 293
 	}
... ...
@@ -304,7 +304,7 @@ func (n *networkRouter) postNetworkDisconnect(ctx context.Context, w http.Respon
304 304
 		return err
305 305
 	}
306 306
 
307
-	var disconnect networkbackend.DisconnectOptions
307
+	var disconnect networkbackend.DisconnectRequest
308 308
 	if err := httputils.ReadJSON(r, &disconnect); err != nil {
309 309
 		return err
310 310
 	}
... ...
@@ -51,6 +51,6 @@ func InspectNoError(ctx context.Context, t *testing.T, apiClient client.APIClien
51 51
 func RemoveNoError(ctx context.Context, t *testing.T, apiClient client.APIClient, name string) {
52 52
 	t.Helper()
53 53
 
54
-	err := apiClient.NetworkRemove(ctx, name)
54
+	_, err := apiClient.NetworkRemove(ctx, name, client.NetworkRemoveOptions{})
55 55
 	assert.NilError(t, err)
56 56
 }
... ...
@@ -1130,7 +1130,7 @@ func TestBridgeIPAMStatus(t *testing.T) {
1130 1130
 				},
1131 1131
 			}),
1132 1132
 		)
1133
-		defer c.NetworkRemove(ctx, netName)
1133
+		defer c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
1134 1134
 
1135 1135
 		checkSubnets(netName, map[netip.Prefix]networktypes.SubnetStatus{
1136 1136
 			cidrv4: {
... ...
@@ -1210,7 +1210,7 @@ func TestBridgeIPAMStatus(t *testing.T) {
1210 1210
 				Subnet: cidr,
1211 1211
 			}),
1212 1212
 		)
1213
-		defer c.NetworkRemove(ctx, netName)
1213
+		defer c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
1214 1214
 
1215 1215
 		checkSubnets(netName, map[netip.Prefix]networktypes.SubnetStatus{
1216 1216
 			cidr: {
... ...
@@ -1255,7 +1255,9 @@ func TestJoinError(t *testing.T) {
1255 1255
 	assert.Equal(t, res.ExitCode, 0)
1256 1256
 
1257 1257
 	// Expect an error when connecting extNet.
1258
-	err := c.NetworkConnect(ctx, extNet, cid, &networktypes.EndpointSettings{})
1258
+	_, err := c.NetworkConnect(ctx, extNet, client.NetworkConnectOptions{
1259
+		Container: cid,
1260
+	})
1259 1261
 	assert.Check(t, is.ErrorContains(err, "failed to set gateway: file exists"))
1260 1262
 
1261 1263
 	// Only intNet should show up in container inspect.
... ...
@@ -1279,7 +1281,9 @@ func TestJoinError(t *testing.T) {
1279 1279
 	assert.Equal(t, res.ExitCode, 0)
1280 1280
 
1281 1281
 	// Check network connect now succeeds.
1282
-	err = c.NetworkConnect(ctx, extNet, cid, &networktypes.EndpointSettings{})
1282
+	_, err = c.NetworkConnect(ctx, extNet, client.NetworkConnectOptions{
1283
+		Container: cid,
1284
+	})
1283 1285
 	assert.Check(t, err)
1284 1286
 	ctrInsp = ctr.Inspect(ctx, t, c, cid)
1285 1287
 	assert.Check(t, is.Len(ctrInsp.NetworkSettings.Networks, 2))
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"errors"
5 5
 	"testing"
6 6
 
7
+	"github.com/moby/moby/client"
7 8
 	"github.com/moby/moby/v2/daemon/libnetwork/drivers/bridge"
8 9
 	"github.com/moby/moby/v2/daemon/libnetwork/nlwrap"
9 10
 	"github.com/moby/moby/v2/integration/internal/network"
... ...
@@ -58,7 +59,7 @@ func TestNetworkInitErrorUserDefined(t *testing.T) {
58 58
 	d.SetEnvVar("DOCKER_TEST_BRIDGE_INIT_ERROR", brName)
59 59
 	d.Restart(t)
60 60
 
61
-	err := c.NetworkRemove(ctx, netName)
61
+	_, err := c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
62 62
 	assert.NilError(t, err)
63 63
 
64 64
 	d.SetEnvVar("DOCKER_TEST_BRIDGE_INIT_ERROR", "")
... ...
@@ -51,7 +51,7 @@ func TestNetworkCreateDelete(t *testing.T) {
51 51
 	assert.Check(t, IsNetworkAvailable(ctx, apiClient, netName))
52 52
 
53 53
 	// delete the network and make sure it is deleted
54
-	err := apiClient.NetworkRemove(ctx, netName)
54
+	_, err := apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
55 55
 	assert.NilError(t, err)
56 56
 	assert.Check(t, IsNetworkNotAvailable(ctx, apiClient, netName))
57 57
 }
... ...
@@ -70,12 +70,12 @@ func TestDockerNetworkDeletePreferID(t *testing.T) {
70 70
 
71 71
 	// Delete the network using a prefix of the first network's ID as name.
72 72
 	// This should the network name with the id-prefix, not the original network.
73
-	err := apiClient.NetworkRemove(ctx, testNet[:12])
73
+	_, err := apiClient.NetworkRemove(ctx, testNet[:12], client.NetworkRemoveOptions{})
74 74
 	assert.NilError(t, err)
75 75
 
76 76
 	// Delete the network using networkID. This should remove the original
77 77
 	// network, not the network with the name equal to the networkID
78
-	err = apiClient.NetworkRemove(ctx, testNet)
78
+	_, err = apiClient.NetworkRemove(ctx, testNet, client.NetworkRemoveOptions{})
79 79
 	assert.NilError(t, err)
80 80
 
81 81
 	// networks "testNet" and "idPrefixNet" should be removed, but "fullIDNet" should still exist
... ...
@@ -29,7 +29,7 @@ func TestDaemonDNSFallback(t *testing.T) {
29 29
 	c := d.NewClientT(t)
30 30
 
31 31
 	network.CreateNoError(ctx, t, c, "test")
32
-	defer c.NetworkRemove(ctx, "test")
32
+	defer c.NetworkRemove(ctx, "test", client.NetworkRemoveOptions{})
33 33
 
34 34
 	cid := container.Run(ctx, t, c, container.WithNetworkMode("test"), container.WithCmd("nslookup", "docker.com"))
35 35
 	defer c.ContainerRemove(ctx, cid, client.ContainerRemoveOptions{Force: true})
... ...
@@ -62,7 +62,8 @@ func TestInspectNetwork(t *testing.T) {
62 62
 	// object) leaking, which prevents other daemons on the same kernel from
63 63
 	// creating a new vxlan link with the same VNI.
64 64
 	defer func() {
65
-		assert.NilError(t, c1.NetworkRemove(ctx, overlayID))
65
+		_, err := c1.NetworkRemove(ctx, overlayID, client.NetworkRemoveOptions{})
66
+		assert.NilError(t, err)
66 67
 		poll.WaitOn(t, network.IsRemoved(ctx, w1, overlayID), swarm.NetworkPoll)
67 68
 	}()
68 69
 
... ...
@@ -12,7 +12,7 @@ import (
12 12
 
13 13
 	"github.com/google/go-cmp/cmp/cmpopts"
14 14
 	"github.com/moby/moby/api/types/network"
15
-	dclient "github.com/moby/moby/client"
15
+	"github.com/moby/moby/client"
16 16
 	"github.com/moby/moby/v2/daemon/libnetwork/netlabel"
17 17
 	"github.com/moby/moby/v2/integration/internal/container"
18 18
 	net "github.com/moby/moby/v2/integration/internal/network"
... ...
@@ -62,7 +62,7 @@ func TestDockerNetworkIpvlan(t *testing.T) {
62 62
 
63 63
 	for _, tc := range []struct {
64 64
 		name string
65
-		test func(*testing.T, context.Context, dclient.APIClient)
65
+		test func(*testing.T, context.Context, client.APIClient)
66 66
 	}{
67 67
 		{
68 68
 			name: "Subinterface",
... ...
@@ -112,27 +112,27 @@ func TestDockerNetworkIpvlan(t *testing.T) {
112 112
 	}
113 113
 }
114 114
 
115
-func testIpvlanSubinterface(t *testing.T, ctx context.Context, client dclient.APIClient) {
115
+func testIpvlanSubinterface(t *testing.T, ctx context.Context, apiClient client.APIClient) {
116 116
 	master := "di-dummy0"
117 117
 	n.CreateMasterDummy(ctx, t, master)
118 118
 	defer n.DeleteInterface(ctx, t, master)
119 119
 
120 120
 	netName := "di-subinterface"
121
-	net.CreateNoError(ctx, t, client, netName,
121
+	net.CreateNoError(ctx, t, apiClient, netName,
122 122
 		net.WithIPvlan("di-dummy0.60", ""),
123 123
 	)
124
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
124
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
125 125
 
126 126
 	// delete the network while preserving the parent link
127
-	err := client.NetworkRemove(ctx, netName)
127
+	_, err := apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
128 128
 	assert.NilError(t, err)
129 129
 
130
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName))
130
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, netName))
131 131
 	// verify the network delete did not delete the predefined link
132 132
 	n.LinkExists(ctx, t, "di-dummy0")
133 133
 }
134 134
 
135
-func testIpvlanOverlapParent(t *testing.T, ctx context.Context, client dclient.APIClient) {
135
+func testIpvlanOverlapParent(t *testing.T, ctx context.Context, client client.APIClient) {
136 136
 	// verify the same parent interface cannot be used if already in use by an existing network
137 137
 	master := "di-dummy0"
138 138
 	parent := master + ".30"
... ...
@@ -153,99 +153,99 @@ func testIpvlanOverlapParent(t *testing.T, ctx context.Context, client dclient.A
153 153
 	assert.Check(t, err != nil)
154 154
 }
155 155
 
156
-func testIpvlanL2NilParent(t *testing.T, ctx context.Context, client dclient.APIClient) {
156
+func testIpvlanL2NilParent(t *testing.T, ctx context.Context, apiClient client.APIClient) {
157 157
 	// ipvlan l2 mode - dummy parent interface is provisioned dynamically
158 158
 	netName := "di-nil-parent"
159
-	net.CreateNoError(ctx, t, client, netName,
159
+	net.CreateNoError(ctx, t, apiClient, netName,
160 160
 		net.WithIPvlan("", ""),
161 161
 	)
162
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
162
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
163 163
 
164
-	id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName))
165
-	id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName))
164
+	id1 := container.Run(ctx, t, apiClient, container.WithNetworkMode(netName))
165
+	id2 := container.Run(ctx, t, apiClient, container.WithNetworkMode(netName))
166 166
 
167
-	_, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1})
167
+	_, err := container.Exec(ctx, apiClient, id2, []string{"ping", "-c", "1", id1})
168 168
 	assert.NilError(t, err)
169 169
 }
170 170
 
171
-func testIpvlanL2InternalMode(t *testing.T, ctx context.Context, client dclient.APIClient) {
171
+func testIpvlanL2InternalMode(t *testing.T, ctx context.Context, apiClient client.APIClient) {
172 172
 	netName := "di-internal"
173
-	net.CreateNoError(ctx, t, client, netName,
173
+	net.CreateNoError(ctx, t, apiClient, netName,
174 174
 		net.WithIPvlan("", ""),
175 175
 		net.WithInternal(),
176 176
 	)
177
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
177
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
178 178
 
179
-	id1 := container.Run(ctx, t, client, container.WithNetworkMode(netName))
180
-	id2 := container.Run(ctx, t, client, container.WithNetworkMode(netName))
179
+	id1 := container.Run(ctx, t, apiClient, container.WithNetworkMode(netName))
180
+	id2 := container.Run(ctx, t, apiClient, container.WithNetworkMode(netName))
181 181
 
182
-	result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"})
182
+	result, _ := container.Exec(ctx, apiClient, id1, []string{"ping", "-c", "1", "8.8.8.8"})
183 183
 	assert.Check(t, is.Contains(result.Combined(), "Network is unreachable"))
184 184
 
185
-	_, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1})
185
+	_, err := container.Exec(ctx, apiClient, id2, []string{"ping", "-c", "1", id1})
186 186
 	assert.NilError(t, err)
187 187
 }
188 188
 
189
-func testIpvlanL3NilParent(t *testing.T, ctx context.Context, client dclient.APIClient) {
189
+func testIpvlanL3NilParent(t *testing.T, ctx context.Context, apiClient client.APIClient) {
190 190
 	netName := "di-nil-parent-l3"
191
-	net.CreateNoError(ctx, t, client, netName,
191
+	net.CreateNoError(ctx, t, apiClient, netName,
192 192
 		net.WithIPvlan("", "l3"),
193 193
 		net.WithIPAM("172.28.230.0/24", ""),
194 194
 		net.WithIPAM("172.28.220.0/24", ""),
195 195
 	)
196
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
196
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
197 197
 
198
-	id1 := container.Run(ctx, t, client,
198
+	id1 := container.Run(ctx, t, apiClient,
199 199
 		container.WithNetworkMode(netName),
200 200
 		container.WithIPv4(netName, "172.28.220.10"),
201 201
 	)
202
-	id2 := container.Run(ctx, t, client,
202
+	id2 := container.Run(ctx, t, apiClient,
203 203
 		container.WithNetworkMode(netName),
204 204
 		container.WithIPv4(netName, "172.28.230.10"),
205 205
 	)
206 206
 
207
-	_, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1})
207
+	_, err := container.Exec(ctx, apiClient, id2, []string{"ping", "-c", "1", id1})
208 208
 	assert.NilError(t, err)
209 209
 }
210 210
 
211
-func testIpvlanL3InternalMode(t *testing.T, ctx context.Context, client dclient.APIClient) {
211
+func testIpvlanL3InternalMode(t *testing.T, ctx context.Context, apiClient client.APIClient) {
212 212
 	netName := "di-internal-l3"
213
-	net.CreateNoError(ctx, t, client, netName,
213
+	net.CreateNoError(ctx, t, apiClient, netName,
214 214
 		net.WithIPvlan("", "l3"),
215 215
 		net.WithInternal(),
216 216
 		net.WithIPAM("172.28.230.0/24", ""),
217 217
 		net.WithIPAM("172.28.220.0/24", ""),
218 218
 	)
219
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
219
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
220 220
 
221
-	id1 := container.Run(ctx, t, client,
221
+	id1 := container.Run(ctx, t, apiClient,
222 222
 		container.WithNetworkMode(netName),
223 223
 		container.WithIPv4(netName, "172.28.220.10"),
224 224
 	)
225
-	id2 := container.Run(ctx, t, client,
225
+	id2 := container.Run(ctx, t, apiClient,
226 226
 		container.WithNetworkMode(netName),
227 227
 		container.WithIPv4(netName, "172.28.230.10"),
228 228
 	)
229 229
 
230
-	result, _ := container.Exec(ctx, client, id1, []string{"ping", "-c", "1", "8.8.8.8"})
230
+	result, _ := container.Exec(ctx, apiClient, id1, []string{"ping", "-c", "1", "8.8.8.8"})
231 231
 	assert.Check(t, is.Contains(result.Combined(), "Network is unreachable"))
232 232
 
233
-	_, err := container.Exec(ctx, client, id2, []string{"ping", "-c", "1", id1})
233
+	_, err := container.Exec(ctx, apiClient, id2, []string{"ping", "-c", "1", id1})
234 234
 	assert.NilError(t, err)
235 235
 }
236 236
 
237
-func testIpvlanL2MultiSubnetWithParent(t *testing.T, ctx context.Context, client dclient.APIClient) {
237
+func testIpvlanL2MultiSubnetWithParent(t *testing.T, ctx context.Context, apiClient client.APIClient) {
238 238
 	const parentIfName = "di-dummy0"
239 239
 	n.CreateMasterDummy(ctx, t, parentIfName)
240 240
 	defer n.DeleteInterface(ctx, t, parentIfName)
241
-	testIpvlanL2MultiSubnet(t, ctx, client, parentIfName)
241
+	testIpvlanL2MultiSubnet(t, ctx, apiClient, parentIfName)
242 242
 }
243 243
 
244
-func testIpvlanL2MultiSubnetNoParent(t *testing.T, ctx context.Context, client dclient.APIClient) {
245
-	testIpvlanL2MultiSubnet(t, ctx, client, "")
244
+func testIpvlanL2MultiSubnetNoParent(t *testing.T, ctx context.Context, apiClient client.APIClient) {
245
+	testIpvlanL2MultiSubnet(t, ctx, apiClient, "")
246 246
 }
247 247
 
248
-func testIpvlanL2MultiSubnet(t *testing.T, ctx context.Context, apiClient dclient.APIClient, parent string) {
248
+func testIpvlanL2MultiSubnet(t *testing.T, ctx context.Context, apiClient client.APIClient, parent string) {
249 249
 	netName := "dualstackl2"
250 250
 	net.CreateNoError(ctx, t, apiClient, netName,
251 251
 		net.WithIPvlan(parent, ""),
... ...
@@ -268,7 +268,7 @@ func testIpvlanL2MultiSubnet(t *testing.T, ctx context.Context, apiClient dclien
268 268
 		container.WithIPv4(netName, "172.28.200.21"),
269 269
 		container.WithIPv6(netName, "2001:db8:abc8::21"),
270 270
 	)
271
-	c1, err := apiClient.ContainerInspect(ctx, id1, dclient.ContainerInspectOptions{})
271
+	c1, err := apiClient.ContainerInspect(ctx, id1, client.ContainerInspectOptions{})
272 272
 	assert.NilError(t, err)
273 273
 	// Inspect the v4 gateway to ensure no default GW was assigned
274 274
 	assert.Check(t, !c1.Container.NetworkSettings.Networks[netName].Gateway.IsValid())
... ...
@@ -293,7 +293,7 @@ func testIpvlanL2MultiSubnet(t *testing.T, ctx context.Context, apiClient dclien
293 293
 		container.WithIPv4(netName, "172.28.202.21"),
294 294
 		container.WithIPv6(netName, "2001:db8:abc6::21"),
295 295
 	)
296
-	c3, err := apiClient.ContainerInspect(ctx, id3, dclient.ContainerInspectOptions{})
296
+	c3, err := apiClient.ContainerInspect(ctx, id3, client.ContainerInspectOptions{})
297 297
 	assert.NilError(t, err)
298 298
 	if parent == "" {
299 299
 		// Inspect the v4 gateway to ensure no default GW was assigned
... ...
@@ -315,9 +315,9 @@ func testIpvlanL2MultiSubnet(t *testing.T, ctx context.Context, apiClient dclien
315 315
 	assert.NilError(t, err)
316 316
 }
317 317
 
318
-func testIpvlanL3MultiSubnet(t *testing.T, ctx context.Context, client dclient.APIClient) {
318
+func testIpvlanL3MultiSubnet(t *testing.T, ctx context.Context, apiClient client.APIClient) {
319 319
 	netName := "dualstackl3"
320
-	net.CreateNoError(ctx, t, client, netName,
320
+	net.CreateNoError(ctx, t, apiClient, netName,
321 321
 		net.WithIPvlan("", "l3"),
322 322
 		net.WithIPv6(),
323 323
 		net.WithIPAM("172.28.10.0/24", ""),
... ...
@@ -325,48 +325,48 @@ func testIpvlanL3MultiSubnet(t *testing.T, ctx context.Context, client dclient.A
325 325
 		net.WithIPAM("2001:db8:abc9::/64", ""),
326 326
 		net.WithIPAM("2001:db8:abc7::/64", "2001:db8:abc7::254"),
327 327
 	)
328
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
328
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
329 329
 
330 330
 	// start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.100.0/24 and 2001:db8:abc2::/64
331
-	id1 := container.Run(ctx, t, client,
331
+	id1 := container.Run(ctx, t, apiClient,
332 332
 		container.WithNetworkMode(netName),
333 333
 		container.WithIPv4(netName, "172.28.10.20"),
334 334
 		container.WithIPv6(netName, "2001:db8:abc9::20"),
335 335
 	)
336
-	id2 := container.Run(ctx, t, client,
336
+	id2 := container.Run(ctx, t, apiClient,
337 337
 		container.WithNetworkMode(netName),
338 338
 		container.WithIPv4(netName, "172.28.10.21"),
339 339
 		container.WithIPv6(netName, "2001:db8:abc9::21"),
340 340
 	)
341
-	c1, err := client.ContainerInspect(ctx, id1, dclient.ContainerInspectOptions{})
341
+	c1, err := apiClient.ContainerInspect(ctx, id1, client.ContainerInspectOptions{})
342 342
 	assert.NilError(t, err)
343 343
 
344 344
 	// verify ipv4 connectivity to the explicit --ipv address second to first
345
-	_, err = container.Exec(ctx, client, id2, []string{"ping", "-c", "1", c1.Container.NetworkSettings.Networks[netName].IPAddress.String()})
345
+	_, err = container.Exec(ctx, apiClient, id2, []string{"ping", "-c", "1", c1.Container.NetworkSettings.Networks[netName].IPAddress.String()})
346 346
 	assert.NilError(t, err)
347 347
 	// verify ipv6 connectivity to the explicit --ipv6 address second to first
348
-	_, err = container.Exec(ctx, client, id2, []string{"ping6", "-c", "1", c1.Container.NetworkSettings.Networks[netName].GlobalIPv6Address.String()})
348
+	_, err = container.Exec(ctx, apiClient, id2, []string{"ping6", "-c", "1", c1.Container.NetworkSettings.Networks[netName].GlobalIPv6Address.String()})
349 349
 	assert.NilError(t, err)
350 350
 
351 351
 	// start dual stack containers and verify the user specified --ip and --ip6 addresses on subnets 172.28.102.0/24 and 2001:db8:abc4::/64
352
-	id3 := container.Run(ctx, t, client,
352
+	id3 := container.Run(ctx, t, apiClient,
353 353
 		container.WithNetworkMode(netName),
354 354
 		container.WithIPv4(netName, "172.28.12.20"),
355 355
 		container.WithIPv6(netName, "2001:db8:abc7::20"),
356 356
 	)
357
-	id4 := container.Run(ctx, t, client,
357
+	id4 := container.Run(ctx, t, apiClient,
358 358
 		container.WithNetworkMode(netName),
359 359
 		container.WithIPv4(netName, "172.28.12.21"),
360 360
 		container.WithIPv6(netName, "2001:db8:abc7::21"),
361 361
 	)
362
-	c3, err := client.ContainerInspect(ctx, id3, dclient.ContainerInspectOptions{})
362
+	c3, err := apiClient.ContainerInspect(ctx, id3, client.ContainerInspectOptions{})
363 363
 	assert.NilError(t, err)
364 364
 
365 365
 	// verify ipv4 connectivity to the explicit --ipv address from third to fourth
366
-	_, err = container.Exec(ctx, client, id4, []string{"ping", "-c", "1", c3.Container.NetworkSettings.Networks[netName].IPAddress.String()})
366
+	_, err = container.Exec(ctx, apiClient, id4, []string{"ping", "-c", "1", c3.Container.NetworkSettings.Networks[netName].IPAddress.String()})
367 367
 	assert.NilError(t, err)
368 368
 	// verify ipv6 connectivity to the explicit --ipv6 address from third to fourth
369
-	_, err = container.Exec(ctx, client, id4, []string{"ping6", "-c", "1", c3.Container.NetworkSettings.Networks[netName].GlobalIPv6Address.String()})
369
+	_, err = container.Exec(ctx, apiClient, id4, []string{"ping6", "-c", "1", c3.Container.NetworkSettings.Networks[netName].GlobalIPv6Address.String()})
370 370
 	assert.NilError(t, err)
371 371
 
372 372
 	// Inspect the v4 gateway to ensure no next hop is assigned in L3 mode
... ...
@@ -381,58 +381,58 @@ func testIpvlanL3MultiSubnet(t *testing.T, ctx context.Context, client dclient.A
381 381
 
382 382
 // Verify ipvlan l2 mode sets the proper default gateway routes via netlink
383 383
 // for either an explicitly set route by the user or inferred via default IPAM
384
-func testIpvlanL2Addressing(t *testing.T, ctx context.Context, client dclient.APIClient) {
384
+func testIpvlanL2Addressing(t *testing.T, ctx context.Context, apiClient client.APIClient) {
385 385
 	const parentIfName = "di-dummy0"
386 386
 	n.CreateMasterDummy(ctx, t, parentIfName)
387 387
 	defer n.DeleteInterface(ctx, t, parentIfName)
388 388
 
389 389
 	netNameL2 := "dualstackl2"
390
-	net.CreateNoError(ctx, t, client, netNameL2,
390
+	net.CreateNoError(ctx, t, apiClient, netNameL2,
391 391
 		net.WithIPvlan(parentIfName, "l2"),
392 392
 		net.WithIPv6(),
393 393
 		net.WithIPAM("172.28.140.0/24", "172.28.140.254"),
394 394
 		net.WithIPAM("2001:db8:abcb::/64", ""),
395 395
 	)
396
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL2))
396
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netNameL2))
397 397
 
398
-	id := container.Run(ctx, t, client,
398
+	id := container.Run(ctx, t, apiClient,
399 399
 		container.WithNetworkMode(netNameL2),
400 400
 	)
401 401
 	// Check the supplied IPv4 gateway address is used in a default route.
402
-	result, err := container.Exec(ctx, client, id, []string{"ip", "route"})
402
+	result, err := container.Exec(ctx, apiClient, id, []string{"ip", "route"})
403 403
 	assert.NilError(t, err)
404 404
 	assert.Check(t, is.Contains(result.Combined(), "default via 172.28.140.254 dev eth0"))
405 405
 	// No gateway address was supplied for IPv6, check that no default gateway was set up.
406
-	result, err = container.Exec(ctx, client, id, []string{"ip", "-6", "route"})
406
+	result, err = container.Exec(ctx, apiClient, id, []string{"ip", "-6", "route"})
407 407
 	assert.NilError(t, err)
408 408
 	assert.Check(t, !strings.Contains(result.Combined(), "default via"),
409 409
 		"result: %s", result.Combined())
410 410
 }
411 411
 
412 412
 // Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops
413
-func testIpvlanL3Addressing(t *testing.T, ctx context.Context, client dclient.APIClient) {
413
+func testIpvlanL3Addressing(t *testing.T, ctx context.Context, apiClient client.APIClient) {
414 414
 	const parentIfName = "di-dummy0"
415 415
 	n.CreateMasterDummy(ctx, t, parentIfName)
416 416
 	defer n.DeleteInterface(ctx, t, parentIfName)
417 417
 
418 418
 	netNameL3 := "dualstackl3"
419
-	net.CreateNoError(ctx, t, client, netNameL3,
419
+	net.CreateNoError(ctx, t, apiClient, netNameL3,
420 420
 		net.WithIPvlan(parentIfName, "l3"),
421 421
 		net.WithIPv6(),
422 422
 		net.WithIPAM("172.28.160.0/24", "172.28.160.254"),
423 423
 		net.WithIPAM("2001:db8:abcd::/64", "2001:db8:abcd::254"),
424 424
 	)
425
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netNameL3))
425
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netNameL3))
426 426
 
427
-	id := container.Run(ctx, t, client,
427
+	id := container.Run(ctx, t, apiClient,
428 428
 		container.WithNetworkMode(netNameL3),
429 429
 	)
430 430
 	// Validate ipvlan l3 mode sets the v4 gateway to dev eth0 and disregards any explicit or inferred next-hops
431
-	result, err := container.Exec(ctx, client, id, []string{"ip", "route"})
431
+	result, err := container.Exec(ctx, apiClient, id, []string{"ip", "route"})
432 432
 	assert.NilError(t, err)
433 433
 	assert.Check(t, is.Contains(result.Combined(), "default dev eth0"))
434 434
 	// Validate ipvlan l3 mode sets the v6 gateway to dev eth0 and disregards any explicit or inferred next-hops
435
-	result, err = container.Exec(ctx, client, id, []string{"ip", "-6", "route"})
435
+	result, err = container.Exec(ctx, apiClient, id, []string{"ip", "-6", "route"})
436 436
 	assert.NilError(t, err)
437 437
 	assert.Check(t, is.Contains(result.Combined(), "default dev eth0"))
438 438
 }
... ...
@@ -488,9 +488,9 @@ func TestIpvlanIPAM(t *testing.T) {
488 488
 	for _, tc := range tests {
489 489
 		t.Run(tc.name, func(t *testing.T) {
490 490
 			ctx := testutil.StartSpan(ctx, t)
491
-			c := d.NewClientT(t, dclient.WithVersion(tc.apiVersion))
491
+			c := d.NewClientT(t, client.WithVersion(tc.apiVersion))
492 492
 
493
-			netOpts := []func(*dclient.NetworkCreateOptions){
493
+			netOpts := []func(*client.NetworkCreateOptions){
494 494
 				net.WithIPvlan("", "l3"),
495 495
 				net.WithIPv4(tc.enableIPv4),
496 496
 				net.WithIPAMConfig(
... ...
@@ -509,11 +509,11 @@ func TestIpvlanIPAM(t *testing.T) {
509 509
 
510 510
 			const netName = "ipvlannet"
511 511
 			net.CreateNoError(ctx, t, c, netName, netOpts...)
512
-			defer c.NetworkRemove(ctx, netName)
512
+			defer c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
513 513
 			assert.Check(t, n.IsNetworkAvailable(ctx, c, netName))
514 514
 
515 515
 			id := container.Run(ctx, t, c, container.WithNetworkMode(netName))
516
-			defer c.ContainerRemove(ctx, id, dclient.ContainerRemoveOptions{Force: true})
516
+			defer c.ContainerRemove(ctx, id, client.ContainerRemoveOptions{Force: true})
517 517
 
518 518
 			loRes := container.ExecT(ctx, t, c, id, []string{"ip", "a", "show", "dev", "lo"})
519 519
 			assert.Check(t, is.Contains(loRes.Combined(), " inet "))
... ...
@@ -551,14 +551,14 @@ func TestIpvlanIPAM(t *testing.T) {
551 551
 			}
552 552
 			assert.Check(t, is.Equal(strings.TrimSpace(sysctlRes.Combined()), expDisableIPv6))
553 553
 
554
-			cc := d.NewClientT(t, dclient.WithVersion("1.52"))
555
-			res, err := cc.NetworkInspect(ctx, netName, dclient.NetworkInspectOptions{})
554
+			cc := d.NewClientT(t, client.WithVersion("1.52"))
555
+			res, err := cc.NetworkInspect(ctx, netName, client.NetworkInspectOptions{})
556 556
 			if assert.Check(t, err) && assert.Check(t, res.Network.Status != nil) {
557 557
 				assert.Check(t, is.DeepEqual(wantSubnetStatus, res.Network.Status.IPAM.Subnets, cmpopts.EquateEmpty()))
558 558
 			}
559 559
 			cc.Close()
560
-			cc = d.NewClientT(t, dclient.WithVersion("1.51"))
561
-			res, err = cc.NetworkInspect(ctx, netName, dclient.NetworkInspectOptions{})
560
+			cc = d.NewClientT(t, client.WithVersion("1.51"))
561
+			res, err = cc.NetworkInspect(ctx, netName, client.NetworkInspectOptions{})
562 562
 			assert.Check(t, err)
563 563
 			assert.Check(t, res.Network.Status == nil)
564 564
 			cc.Close()
... ...
@@ -585,7 +585,7 @@ func TestIpvlanIPAMOverlap(t *testing.T) {
585 585
 
586 586
 	checkNetworkIPAMState := func(networkID string, want map[netip.Prefix]network.SubnetStatus) bool {
587 587
 		t.Helper()
588
-		res, err := c.NetworkInspect(ctx, networkID, dclient.NetworkInspectOptions{})
588
+		res, err := c.NetworkInspect(ctx, networkID, client.NetworkInspectOptions{})
589 589
 		if assert.Check(t, err) && assert.Check(t, res.Network.Status != nil) {
590 590
 			return assert.Check(t, is.DeepEqual(want, res.Network.Status.IPAM.Subnets, cmpopts.EquateEmpty()))
591 591
 		}
... ...
@@ -621,7 +621,7 @@ func TestIpvlanIPAMOverlap(t *testing.T) {
621 621
 			},
622 622
 		),
623 623
 	)
624
-	defer c.NetworkRemove(ctx, netName1)
624
+	defer c.NetworkRemove(ctx, netName1, client.NetworkRemoveOptions{})
625 625
 	assert.Check(t, n.IsNetworkAvailable(ctx, c, netName1))
626 626
 
627 627
 	checkNetworkIPAMState(netName1, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -650,7 +650,7 @@ func TestIpvlanIPAMOverlap(t *testing.T) {
650 650
 		),
651 651
 	)
652 652
 
653
-	defer c.NetworkRemove(ctx, netName2)
653
+	defer c.NetworkRemove(ctx, netName2, client.NetworkRemoveOptions{})
654 654
 	assert.Check(t, n.IsNetworkAvailable(ctx, c, netName2))
655 655
 
656 656
 	checkNetworkIPAMState(netName2, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -679,7 +679,7 @@ func TestIpvlanIPAMOverlap(t *testing.T) {
679 679
 		),
680 680
 	)
681 681
 
682
-	defer c.NetworkRemove(ctx, netName3)
682
+	defer c.NetworkRemove(ctx, netName3, client.NetworkRemoveOptions{})
683 683
 	assert.Check(t, n.IsNetworkAvailable(ctx, c, netName3))
684 684
 
685 685
 	checkNetworkIPAMState(netName3, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -695,7 +695,7 @@ func TestIpvlanIPAMOverlap(t *testing.T) {
695 695
 
696 696
 	// Create a container on one of the networks
697 697
 	id := container.Run(ctx, t, c, container.WithNetworkMode(netName1))
698
-	defer c.ContainerRemove(ctx, id, dclient.ContainerRemoveOptions{Force: true})
698
+	defer c.ContainerRemove(ctx, id, client.ContainerRemoveOptions{Force: true})
699 699
 
700 700
 	// Verify that the IPAM status of all three networks are affected.
701 701
 	checkNetworkIPAMState(netName1, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -787,17 +787,17 @@ func TestIPVlanDNS(t *testing.T) {
787 787
 			name := fmt.Sprintf("Mode=%v/HasParent=%v/Internal=%v", mode, tc.parent != "", tc.internal)
788 788
 			t.Run(name, func(t *testing.T) {
789 789
 				ctx := testutil.StartSpan(ctx, t)
790
-				createOpts := []func(*dclient.NetworkCreateOptions){
790
+				createOpts := []func(*client.NetworkCreateOptions){
791 791
 					net.WithIPvlan(tc.parent, mode),
792 792
 				}
793 793
 				if tc.internal {
794 794
 					createOpts = append(createOpts, net.WithInternal())
795 795
 				}
796 796
 				net.CreateNoError(ctx, t, c, netName, createOpts...)
797
-				defer c.NetworkRemove(ctx, netName)
797
+				defer c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
798 798
 
799 799
 				ctrId := container.Run(ctx, t, c, container.WithNetworkMode(netName))
800
-				defer c.ContainerRemove(ctx, ctrId, dclient.ContainerRemoveOptions{Force: true})
800
+				defer c.ContainerRemove(ctx, ctrId, client.ContainerRemoveOptions{Force: true})
801 801
 				res, err := container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
802 802
 				assert.NilError(t, err)
803 803
 				if tc.expDNS {
... ...
@@ -864,7 +864,7 @@ func TestPointToPoint(t *testing.T) {
864 864
 				container.WithNetworkMode(netName),
865 865
 				container.WithName(ctrName),
866 866
 			)
867
-			defer apiClient.ContainerRemove(ctx, id, dclient.ContainerRemoveOptions{Force: true})
867
+			defer apiClient.ContainerRemove(ctx, id, client.ContainerRemoveOptions{Force: true})
868 868
 
869 869
 			attachCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
870 870
 			defer cancel()
... ...
@@ -872,7 +872,7 @@ func TestPointToPoint(t *testing.T) {
872 872
 				container.WithCmd([]string{"ping", "-c1", "-W3", ctrName}...),
873 873
 				container.WithNetworkMode(netName),
874 874
 			)
875
-			defer apiClient.ContainerRemove(ctx, res.ContainerID, dclient.ContainerRemoveOptions{Force: true})
875
+			defer apiClient.ContainerRemove(ctx, res.ContainerID, client.ContainerRemoveOptions{Force: true})
876 876
 			assert.Check(t, is.Equal(res.ExitCode, 0))
877 877
 			assert.Check(t, is.Equal(res.Stderr.Len(), 0))
878 878
 			assert.Check(t, is.Contains(res.Stdout.String(), "1 packets transmitted, 1 packets received"))
... ...
@@ -903,7 +903,7 @@ func TestEndpointWithCustomIfname(t *testing.T) {
903 903
 				netlabel.Ifname: "foobar",
904 904
 			},
905 905
 		}))
906
-	defer container.Remove(ctx, t, apiClient, ctrID, dclient.ContainerRemoveOptions{Force: true})
906
+	defer container.Remove(ctx, t, apiClient, ctrID, client.ContainerRemoveOptions{Force: true})
907 907
 
908 908
 	out, err := container.Output(ctx, apiClient, ctrID)
909 909
 	assert.NilError(t, err)
... ...
@@ -110,7 +110,7 @@ func TestDockerNetworkMacvlan(t *testing.T) {
110 110
 	}
111 111
 }
112 112
 
113
-func testMacvlanOverlapParent(t *testing.T, ctx context.Context, client client.APIClient) {
113
+func testMacvlanOverlapParent(t *testing.T, ctx context.Context, apiClient client.APIClient) {
114 114
 	// verify the same parent interface can be used if already in use by an existing network
115 115
 	// as long as neither are passthru
116 116
 	master := "dm-dummy0"
... ...
@@ -119,35 +119,35 @@ func testMacvlanOverlapParent(t *testing.T, ctx context.Context, client client.A
119 119
 
120 120
 	netName := "dm-subinterface"
121 121
 	parentName := "dm-dummy0.40"
122
-	net.CreateNoError(ctx, t, client, netName,
122
+	net.CreateNoError(ctx, t, apiClient, netName,
123 123
 		net.WithMacvlan(parentName),
124 124
 	)
125
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
125
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
126 126
 	n.LinkExists(ctx, t, parentName)
127 127
 
128 128
 	overlapNetName := "dm-parent-net-overlap"
129
-	_, err := net.Create(ctx, client, overlapNetName,
129
+	_, err := net.Create(ctx, apiClient, overlapNetName,
130 130
 		net.WithMacvlan(parentName),
131 131
 	)
132 132
 	assert.Check(t, err)
133 133
 
134 134
 	// delete the second network while preserving the parent link
135
-	err = client.NetworkRemove(ctx, overlapNetName)
135
+	_, err = apiClient.NetworkRemove(ctx, overlapNetName, client.NetworkRemoveOptions{})
136 136
 	assert.NilError(t, err)
137
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, overlapNetName))
137
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, overlapNetName))
138 138
 	n.LinkExists(ctx, t, parentName)
139 139
 
140 140
 	// delete the first network
141
-	err = client.NetworkRemove(ctx, netName)
141
+	_, err = apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
142 142
 	assert.NilError(t, err)
143
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName))
143
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, netName))
144 144
 	n.LinkDoesntExist(ctx, t, parentName)
145 145
 
146 146
 	// verify the network delete did not delete the root link
147 147
 	n.LinkExists(ctx, t, master)
148 148
 }
149 149
 
150
-func testMacvlanOverlapParentPassthruFirst(t *testing.T, ctx context.Context, client client.APIClient) {
150
+func testMacvlanOverlapParentPassthruFirst(t *testing.T, ctx context.Context, apiClient client.APIClient) {
151 151
 	// verify creating a second interface sharing a parent with another passthru interface is rejected
152 152
 	master := "dm-dummy0"
153 153
 	n.CreateMasterDummy(ctx, t, master)
... ...
@@ -155,26 +155,26 @@ func testMacvlanOverlapParentPassthruFirst(t *testing.T, ctx context.Context, cl
155 155
 
156 156
 	netName := "dm-subinterface"
157 157
 	parentName := "dm-dummy0.40"
158
-	net.CreateNoError(ctx, t, client, netName,
158
+	net.CreateNoError(ctx, t, apiClient, netName,
159 159
 		net.WithMacvlanPassthru(parentName),
160 160
 	)
161
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
161
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
162 162
 
163
-	_, err := net.Create(ctx, client, "dm-parent-net-overlap",
163
+	_, err := net.Create(ctx, apiClient, "dm-parent-net-overlap",
164 164
 		net.WithMacvlan(parentName),
165 165
 	)
166 166
 	assert.Check(t, err != nil)
167 167
 
168 168
 	// delete the network while preserving the parent link
169
-	err = client.NetworkRemove(ctx, netName)
169
+	_, err = apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
170 170
 	assert.NilError(t, err)
171 171
 
172
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName))
172
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, netName))
173 173
 	// verify the network delete did not delete the predefined link
174 174
 	n.LinkExists(ctx, t, master)
175 175
 }
176 176
 
177
-func testMacvlanOverlapParentPassthruSecond(t *testing.T, ctx context.Context, client client.APIClient) {
177
+func testMacvlanOverlapParentPassthruSecond(t *testing.T, ctx context.Context, apiClient client.APIClient) {
178 178
 	// verify creating a passthru interface sharing a parent with another interface is rejected
179 179
 	master := "dm-dummy0"
180 180
 	n.CreateMasterDummy(ctx, t, master)
... ...
@@ -182,26 +182,26 @@ func testMacvlanOverlapParentPassthruSecond(t *testing.T, ctx context.Context, c
182 182
 
183 183
 	netName := "dm-subinterface"
184 184
 	parentName := "dm-dummy0.40"
185
-	net.CreateNoError(ctx, t, client, netName,
185
+	net.CreateNoError(ctx, t, apiClient, netName,
186 186
 		net.WithMacvlan(parentName),
187 187
 	)
188
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
188
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
189 189
 
190
-	_, err := net.Create(ctx, client, "dm-parent-net-overlap",
190
+	_, err := net.Create(ctx, apiClient, "dm-parent-net-overlap",
191 191
 		net.WithMacvlanPassthru(parentName),
192 192
 	)
193 193
 	assert.Check(t, err != nil)
194 194
 
195 195
 	// delete the network while preserving the parent link
196
-	err = client.NetworkRemove(ctx, netName)
196
+	_, err = apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
197 197
 	assert.NilError(t, err)
198 198
 
199
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName))
199
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, netName))
200 200
 	// verify the network delete did not delete the predefined link
201 201
 	n.LinkExists(ctx, t, master)
202 202
 }
203 203
 
204
-func testMacvlanOverlapDeleteCreatedSecond(t *testing.T, ctx context.Context, client client.APIClient) {
204
+func testMacvlanOverlapDeleteCreatedSecond(t *testing.T, ctx context.Context, apiClient client.APIClient) {
205 205
 	// verify that a shared created parent interface is kept when the original interface is deleted first
206 206
 	master := "dm-dummy0"
207 207
 	n.CreateMasterDummy(ctx, t, master)
... ...
@@ -209,34 +209,34 @@ func testMacvlanOverlapDeleteCreatedSecond(t *testing.T, ctx context.Context, cl
209 209
 
210 210
 	netName := "dm-subinterface"
211 211
 	parentName := "dm-dummy0.40"
212
-	net.CreateNoError(ctx, t, client, netName,
212
+	net.CreateNoError(ctx, t, apiClient, netName,
213 213
 		net.WithMacvlan(parentName),
214 214
 	)
215
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
215
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
216 216
 
217 217
 	overlapNetName := "dm-parent-net-overlap"
218
-	_, err := net.Create(ctx, client, overlapNetName,
218
+	_, err := net.Create(ctx, apiClient, overlapNetName,
219 219
 		net.WithMacvlan(parentName),
220 220
 	)
221 221
 	assert.Check(t, err)
222 222
 
223 223
 	// delete the original network while preserving the parent link
224
-	err = client.NetworkRemove(ctx, netName)
224
+	_, err = apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
225 225
 	assert.NilError(t, err)
226
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName))
226
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, netName))
227 227
 	n.LinkExists(ctx, t, parentName)
228 228
 
229 229
 	// delete the second network
230
-	err = client.NetworkRemove(ctx, overlapNetName)
230
+	_, err = apiClient.NetworkRemove(ctx, overlapNetName, client.NetworkRemoveOptions{})
231 231
 	assert.NilError(t, err)
232
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, overlapNetName))
232
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, overlapNetName))
233 233
 	n.LinkDoesntExist(ctx, t, parentName)
234 234
 
235 235
 	// verify the network delete did not delete the root link
236 236
 	n.LinkExists(ctx, t, master)
237 237
 }
238 238
 
239
-func testMacvlanOverlapKeepExisting(t *testing.T, ctx context.Context, client client.APIClient) {
239
+func testMacvlanOverlapKeepExisting(t *testing.T, ctx context.Context, apiClient client.APIClient) {
240 240
 	// verify that deleting interfaces sharing a previously existing parent doesn't delete the
241 241
 	// parent
242 242
 	master := "dm-dummy0"
... ...
@@ -244,27 +244,27 @@ func testMacvlanOverlapKeepExisting(t *testing.T, ctx context.Context, client cl
244 244
 	defer n.DeleteInterface(ctx, t, master)
245 245
 
246 246
 	netName := "dm-subinterface"
247
-	net.CreateNoError(ctx, t, client, netName,
247
+	net.CreateNoError(ctx, t, apiClient, netName,
248 248
 		net.WithMacvlan(master),
249 249
 	)
250
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
250
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
251 251
 
252 252
 	overlapNetName := "dm-parent-net-overlap"
253
-	_, err := net.Create(ctx, client, overlapNetName,
253
+	_, err := net.Create(ctx, apiClient, overlapNetName,
254 254
 		net.WithMacvlan(master),
255 255
 	)
256 256
 	assert.Check(t, err)
257 257
 
258
-	err = client.NetworkRemove(ctx, overlapNetName)
258
+	_, err = apiClient.NetworkRemove(ctx, overlapNetName, client.NetworkRemoveOptions{})
259 259
 	assert.NilError(t, err)
260
-	err = client.NetworkRemove(ctx, netName)
260
+	_, err = apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
261 261
 	assert.NilError(t, err)
262 262
 
263 263
 	// verify the network delete did not delete the root link
264 264
 	n.LinkExists(ctx, t, master)
265 265
 }
266 266
 
267
-func testMacvlanSubinterface(t *testing.T, ctx context.Context, client client.APIClient) {
267
+func testMacvlanSubinterface(t *testing.T, ctx context.Context, apiClient client.APIClient) {
268 268
 	// verify the same parent interface cannot be used if already in use by an existing network
269 269
 	master := "dm-dummy0"
270 270
 	parentName := "dm-dummy0.20"
... ...
@@ -273,16 +273,16 @@ func testMacvlanSubinterface(t *testing.T, ctx context.Context, client client.AP
273 273
 	n.CreateVlanInterface(ctx, t, master, parentName, "20")
274 274
 
275 275
 	netName := "dm-subinterface"
276
-	net.CreateNoError(ctx, t, client, netName,
276
+	net.CreateNoError(ctx, t, apiClient, netName,
277 277
 		net.WithMacvlan(parentName),
278 278
 	)
279
-	assert.Check(t, n.IsNetworkAvailable(ctx, client, netName))
279
+	assert.Check(t, n.IsNetworkAvailable(ctx, apiClient, netName))
280 280
 
281 281
 	// delete the network while preserving the parent link
282
-	err := client.NetworkRemove(ctx, netName)
282
+	_, err := apiClient.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
283 283
 	assert.NilError(t, err)
284 284
 
285
-	assert.Check(t, n.IsNetworkNotAvailable(ctx, client, netName))
285
+	assert.Check(t, n.IsNetworkNotAvailable(ctx, apiClient, netName))
286 286
 	// verify the network delete did not delete the predefined link
287 287
 	n.LinkExists(ctx, t, parentName)
288 288
 }
... ...
@@ -512,7 +512,7 @@ func TestMacvlanIPAM(t *testing.T) {
512 512
 
513 513
 			const netName = "macvlannet"
514 514
 			net.CreateNoError(ctx, t, c, netName, netOpts...)
515
-			defer c.NetworkRemove(ctx, netName)
515
+			defer c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
516 516
 			assert.Check(t, n.IsNetworkAvailable(ctx, c, netName))
517 517
 
518 518
 			id := container.Run(ctx, t, c, container.WithNetworkMode(netName))
... ...
@@ -624,7 +624,7 @@ func TestMacvlanIPAMOverlap(t *testing.T) {
624 624
 			},
625 625
 		),
626 626
 	)
627
-	defer c.NetworkRemove(ctx, netName1)
627
+	defer c.NetworkRemove(ctx, netName1, client.NetworkRemoveOptions{})
628 628
 	assert.Check(t, n.IsNetworkAvailable(ctx, c, netName1))
629 629
 
630 630
 	checkNetworkIPAMState(netName1, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -653,7 +653,7 @@ func TestMacvlanIPAMOverlap(t *testing.T) {
653 653
 		),
654 654
 	)
655 655
 
656
-	defer c.NetworkRemove(ctx, netName2)
656
+	defer c.NetworkRemove(ctx, netName2, client.NetworkRemoveOptions{})
657 657
 	assert.Check(t, n.IsNetworkAvailable(ctx, c, netName2))
658 658
 
659 659
 	checkNetworkIPAMState(netName2, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -682,7 +682,7 @@ func TestMacvlanIPAMOverlap(t *testing.T) {
682 682
 		),
683 683
 	)
684 684
 
685
-	defer c.NetworkRemove(ctx, netName3)
685
+	defer c.NetworkRemove(ctx, netName3, client.NetworkRemoveOptions{})
686 686
 	assert.Check(t, n.IsNetworkAvailable(ctx, c, netName3))
687 687
 
688 688
 	checkNetworkIPAMState(netName3, map[netip.Prefix]network.SubnetStatus{
... ...
@@ -795,7 +795,7 @@ func TestMACVlanDNS(t *testing.T) {
795 795
 				createOpts = append(createOpts, net.WithInternal())
796 796
 			}
797 797
 			net.CreateNoError(ctx, t, c, netName, createOpts...)
798
-			defer c.NetworkRemove(ctx, netName)
798
+			defer c.NetworkRemove(ctx, netName, client.NetworkRemoveOptions{})
799 799
 
800 800
 			ctrId := container.Run(ctx, t, c, container.WithNetworkMode(netName))
801 801
 			defer c.ContainerRemove(ctx, ctrId, client.ContainerRemoveOptions{Force: true})
... ...
@@ -148,7 +148,7 @@ func TestDefaultNetworkOpts(t *testing.T) {
148 148
 						"com.docker.network.driver.mtu": fmt.Sprint(tc.mtu),
149 149
 					}
150 150
 				})
151
-				defer c.NetworkRemove(ctx, "from-net")
151
+				defer c.NetworkRemove(ctx, "from-net", client.NetworkRemoveOptions{})
152 152
 			}
153 153
 
154 154
 			// Create a new network
... ...
@@ -160,7 +160,7 @@ func TestDefaultNetworkOpts(t *testing.T) {
160 160
 					}
161 161
 				}
162 162
 			})
163
-			defer c.NetworkRemove(ctx, networkName)
163
+			defer c.NetworkRemove(ctx, networkName, client.NetworkRemoveOptions{})
164 164
 
165 165
 			// Check the MTU of the bridge itself, before any devices are connected. (The
166 166
 			// bridge's MTU will be set to the minimum MTU of anything connected to it, but
... ...
@@ -318,26 +318,38 @@ func TestConnectWithPriority(t *testing.T) {
318 318
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 4, "default via fddd:4901:f594::1 dev eth0")
319 319
 
320 320
 	// testnet5 has a negative priority -- the default gateway should not change.
321
-	err := apiClient.NetworkConnect(ctx, "testnet5", ctrID, &networktypes.EndpointSettings{GwPriority: -100})
321
+	_, err := apiClient.NetworkConnect(ctx, "testnet5", client.NetworkConnectOptions{
322
+		Container:      ctrID,
323
+		EndpointConfig: &networktypes.EndpointSettings{GwPriority: -100},
324
+	})
322 325
 	assert.NilError(t, err)
323 326
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 3, "default via 10.100.10.1 dev eth0")
324 327
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 7, "default via fddd:4901:f594::1 dev eth0")
325 328
 
326 329
 	// testnet2 has a higher priority. It should now provide the default gateway.
327
-	err = apiClient.NetworkConnect(ctx, "testnet2", ctrID, &networktypes.EndpointSettings{GwPriority: 100})
330
+	_, err = apiClient.NetworkConnect(ctx, "testnet2", client.NetworkConnectOptions{
331
+		Container:      ctrID,
332
+		EndpointConfig: &networktypes.EndpointSettings{GwPriority: 100},
333
+	})
328 334
 	assert.NilError(t, err)
329 335
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 4, "default via 10.100.20.1 dev eth2")
330 336
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 10, "default via fd83:7683:7008::1 dev eth2")
331 337
 
332 338
 	// testnet3 has a lower priority, so testnet2 should still provide the default gateway.
333
-	err = apiClient.NetworkConnect(ctx, "testnet3", ctrID, &networktypes.EndpointSettings{GwPriority: 10})
339
+	_, err = apiClient.NetworkConnect(ctx, "testnet3", client.NetworkConnectOptions{
340
+		Container:      ctrID,
341
+		EndpointConfig: &networktypes.EndpointSettings{GwPriority: 10},
342
+	})
334 343
 	assert.NilError(t, err)
335 344
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 5, "default via 10.100.20.1 dev eth2")
336 345
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 13, "default via fd83:7683:7008::1 dev eth2")
337 346
 
338 347
 	// testnet4 has the same priority as testnet3, but it sorts after in
339 348
 	// lexicographic order. For now, testnet2 stays the default gateway.
340
-	err = apiClient.NetworkConnect(ctx, "testnet4", ctrID, &networktypes.EndpointSettings{GwPriority: 10})
349
+	_, err = apiClient.NetworkConnect(ctx, "testnet4", client.NetworkConnectOptions{
350
+		Container:      ctrID,
351
+		EndpointConfig: &networktypes.EndpointSettings{GwPriority: 10},
352
+	})
341 353
 	assert.NilError(t, err)
342 354
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 6, "default via 10.100.20.1 dev eth2")
343 355
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 16, "default via fd83:7683:7008::1 dev eth2")
... ...
@@ -352,19 +364,19 @@ func TestConnectWithPriority(t *testing.T) {
352 352
 	// Disconnect testnet2, so testnet3 should now provide the default gateway.
353 353
 	// When two endpoints have the same priority (eg. testnet3 vs testnet4),
354 354
 	// the one that sorts first in lexicographic order is picked.
355
-	err = apiClient.NetworkDisconnect(ctx, "testnet2", ctrID, true)
355
+	_, err = apiClient.NetworkDisconnect(ctx, "testnet2", client.NetworkDisconnectOptions{Container: ctrID, Force: true})
356 356
 	assert.NilError(t, err)
357 357
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 5, "default via 10.100.30.1 dev eth3")
358 358
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 13, "default via fd72:de0:adad::1 dev eth3")
359 359
 
360 360
 	// Disconnect testnet3, so testnet4 should now provide the default gateway.
361
-	err = apiClient.NetworkDisconnect(ctx, "testnet3", ctrID, true)
361
+	_, err = apiClient.NetworkDisconnect(ctx, "testnet3", client.NetworkDisconnectOptions{Container: ctrID, Force: true})
362 362
 	assert.NilError(t, err)
363 363
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 4, "default via 10.100.40.1 dev eth4")
364 364
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 10, "default via fd4c:c927:7d90::1 dev eth4")
365 365
 
366 366
 	// Disconnect testnet4, so testnet1 should now provide the default gateway.
367
-	err = apiClient.NetworkDisconnect(ctx, "testnet4", ctrID, true)
367
+	_, err = apiClient.NetworkDisconnect(ctx, "testnet4", client.NetworkDisconnectOptions{Container: ctrID, Force: true})
368 368
 	assert.NilError(t, err)
369 369
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET, 3, "default via 10.100.10.1 dev eth0")
370 370
 	checkCtrRoutes(t, ctx, apiClient, ctrID, syscall.AF_INET6, 7, "default via fddd:4901:f594::1 dev eth0")
... ...
@@ -511,19 +523,22 @@ func TestMixL3IPVlanAndBridge(t *testing.T) {
511 511
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET6, 10, "default via fd6f:36f8:3005::1 dev bds")
512 512
 
513 513
 			// Disconnect the dual-stack bridge network, expect the ipvlan's default route to be set up.
514
-			c.NetworkDisconnect(ctx, br46NetName, ctrId, false)
514
+			c.NetworkDisconnect(ctx, br46NetName, client.NetworkDisconnectOptions{Container: ctrId, Force: false})
515 515
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET, 2, "default dev eth")
516 516
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET6, 7, "default dev eth")
517 517
 
518 518
 			// Disconnect the ipvlan, expect the IPv6-only network to be the gateway, with no IPv4 gateway.
519 519
 			// (For this to work in the live-restore case the "dstName" of the interface must have been
520 520
 			// restored in the osSbox, based on matching the running interface's IPv6 address.)
521
-			c.NetworkDisconnect(ctx, ipvNetName, ctrId, false)
521
+			c.NetworkDisconnect(ctx, ipvNetName, client.NetworkDisconnectOptions{Container: ctrId, Force: false})
522 522
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET, 0, "")
523 523
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET6, 4, "default via fdc9:adaf:b5da::1 dev bss")
524 524
 
525 525
 			// Reconnect the dual-stack bridge, expect it to be the gateway for both addr families.
526
-			c.NetworkConnect(ctx, br46NetName, ctrId, &networktypes.EndpointSettings{GwPriority: 1})
526
+			c.NetworkConnect(ctx, br46NetName, client.NetworkConnectOptions{
527
+				Container:      ctrId,
528
+				EndpointConfig: &networktypes.EndpointSettings{GwPriority: 1},
529
+			})
527 530
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET, 2, "default via 192.168.123.1 dev bds")
528 531
 			checkCtrRoutes(t, ctx, c, ctrId, syscall.AF_INET6, 7, "default via fd6f:36f8:3005::1 dev bds")
529 532
 		})
... ...
@@ -373,7 +373,7 @@ func TestServiceWithDataPathPortInit(t *testing.T) {
373 373
 	assert.NilError(t, err)
374 374
 	poll.WaitOn(t, noServices(ctx, c), swarm.ServicePoll)
375 375
 	poll.WaitOn(t, swarm.NoTasks(ctx, c), swarm.ServicePoll)
376
-	err = c.NetworkRemove(ctx, overlayID)
376
+	_, err = c.NetworkRemove(ctx, overlayID, client.NetworkRemoveOptions{})
377 377
 	assert.NilError(t, err)
378 378
 	c.Close()
379 379
 	err = d.SwarmLeave(ctx, t, true)
... ...
@@ -406,7 +406,7 @@ func TestServiceWithDataPathPortInit(t *testing.T) {
406 406
 	assert.NilError(t, err)
407 407
 	poll.WaitOn(t, noServices(ctx, nc), swarm.ServicePoll)
408 408
 	poll.WaitOn(t, swarm.NoTasks(ctx, nc), swarm.ServicePoll)
409
-	err = nc.NetworkRemove(ctx, overlayID)
409
+	_, err = nc.NetworkRemove(ctx, overlayID, client.NetworkRemoveOptions{})
410 410
 	assert.NilError(t, err)
411 411
 	err = d.SwarmLeave(ctx, t, true)
412 412
 	assert.NilError(t, err)
... ...
@@ -463,7 +463,7 @@ func TestServiceWithDefaultAddressPoolInit(t *testing.T) {
463 463
 	poll.WaitOn(t, noServices(ctx, cli), swarm.ServicePoll)
464 464
 	poll.WaitOn(t, swarm.NoTasks(ctx, cli), swarm.ServicePoll)
465 465
 	assert.NilError(t, err)
466
-	err = cli.NetworkRemove(ctx, overlayID)
466
+	_, err = cli.NetworkRemove(ctx, overlayID, client.NetworkRemoveOptions{})
467 467
 	assert.NilError(t, err)
468 468
 	err = d.SwarmLeave(ctx, t, true)
469 469
 	assert.NilError(t, err)
... ...
@@ -501,7 +501,7 @@ func TestCustomIfnameIsPreservedOnLiveRestore(t *testing.T) {
501 501
 	// On live-restore, the daemon rebuilds the list of interfaces for all
502 502
 	// containers. Call NetworkDisconnect here to make sure that the right
503 503
 	// dstName is used internally.
504
-	err = apiClient.NetworkDisconnect(ctx, "bridge", ctrId, true)
504
+	_, err = apiClient.NetworkDisconnect(ctx, "bridge", client.NetworkDisconnectOptions{Container: ctrId, Force: true})
505 505
 	assert.NilError(t, err)
506 506
 }
507 507
 
... ...
@@ -525,9 +525,12 @@ func TestCustomIfnameCollidesWithExistingIface(t *testing.T) {
525 525
 		container.WithEndpointSettings("bridge", &networktypes.EndpointSettings{}))
526 526
 	defer container.Remove(ctx, t, apiClient, ctrId, client.ContainerRemoveOptions{Force: true})
527 527
 
528
-	err := apiClient.NetworkConnect(ctx, testnet, ctrId, &networktypes.EndpointSettings{DriverOpts: map[string]string{
529
-		netlabel.Ifname: "eth0",
530
-	}})
528
+	_, err := apiClient.NetworkConnect(ctx, testnet, client.NetworkConnectOptions{
529
+		Container: ctrId,
530
+		EndpointConfig: &networktypes.EndpointSettings{DriverOpts: map[string]string{
531
+			netlabel.Ifname: "eth0",
532
+		}},
533
+	})
531 534
 	assert.ErrorContains(t, err, "error renaming interface")
532 535
 	assert.ErrorContains(t, err, "file exists")
533 536
 }
... ...
@@ -573,18 +576,22 @@ func TestCustomIfnameWithMatchingDynamicPrefix(t *testing.T) {
573 573
 	checkIfaceAddr(t, ctx, apiClient, ctrId, "eth0", "inet 10.0.1.2/24")
574 574
 	checkIfaceAddr(t, ctx, apiClient, ctrId, "eth1", "inet 10.0.0.2/24")
575 575
 
576
-	err := apiClient.NetworkConnect(ctx, "testnet2", ctrId, nil)
576
+	_, err := apiClient.NetworkConnect(ctx, "testnet2", client.NetworkConnectOptions{
577
+		Container: ctrId,
578
+	})
577 579
 	assert.NilError(t, err)
578 580
 	checkIfaceAddr(t, ctx, apiClient, ctrId, "eth2", "inet 10.0.2.2/24")
579 581
 
580 582
 	// Disconnect from testnet1 (ie. eth0), and testnet2 (ie. eth2)
581
-	err = apiClient.NetworkDisconnect(ctx, "testnet1", ctrId, false)
583
+	_, err = apiClient.NetworkDisconnect(ctx, "testnet1", client.NetworkDisconnectOptions{Container: ctrId, Force: false})
582 584
 	assert.NilError(t, err)
583
-	err = apiClient.NetworkDisconnect(ctx, "testnet2", ctrId, false)
585
+	_, err = apiClient.NetworkDisconnect(ctx, "testnet2", client.NetworkDisconnectOptions{Container: ctrId, Force: false})
584 586
 	assert.NilError(t, err)
585 587
 
586 588
 	// Reconnect to testnet2 -- it should now provide eth0.
587
-	err = apiClient.NetworkConnect(ctx, "testnet2", ctrId, nil)
589
+	_, err = apiClient.NetworkConnect(ctx, "testnet2", client.NetworkConnectOptions{
590
+		Container: ctrId,
591
+	})
588 592
 	assert.NilError(t, err)
589 593
 	checkIfaceAddr(t, ctx, apiClient, ctrId, "eth0", "inet 10.0.2.2/24")
590 594
 }
... ...
@@ -1519,7 +1519,9 @@ func TestGatewaySelection(t *testing.T) {
1519 1519
 	// Connect the IPv6-only network. The IPv6 endpoint should become the
1520 1520
 	// gateway for IPv6, the IPv4 endpoint should be reconfigured as the
1521 1521
 	// gateway for IPv4 only.
1522
-	err := c.NetworkConnect(ctx, netId6, ctrId, nil)
1522
+	_, err := c.NetworkConnect(ctx, netId6, client.NetworkConnectOptions{
1523
+		Container: ctrId,
1524
+	})
1523 1525
 	assert.NilError(t, err)
1524 1526
 	checkProxies(ctx, t, c, d.Pid(), []expProxyCfg{
1525 1527
 		{"tcp", "0.0.0.0", "8080", ctrName, netName4, true, "80"},
... ...
@@ -1528,7 +1530,7 @@ func TestGatewaySelection(t *testing.T) {
1528 1528
 
1529 1529
 	// Disconnect the IPv6-only network, the IPv4 should get back the mapping
1530 1530
 	// from host-IPv6.
1531
-	err = c.NetworkDisconnect(ctx, netId6, ctrId, false)
1531
+	_, err = c.NetworkDisconnect(ctx, netId6, client.NetworkDisconnectOptions{Container: ctrId, Force: false})
1532 1532
 	assert.NilError(t, err)
1533 1533
 	checkProxies(ctx, t, c, d.Pid(), []expProxyCfg{
1534 1534
 		{"tcp", "0.0.0.0", "8080", ctrName, netName4, true, "80"},
... ...
@@ -1536,7 +1538,9 @@ func TestGatewaySelection(t *testing.T) {
1536 1536
 	})
1537 1537
 
1538 1538
 	// Connect the dual-stack network, it should become the gateway for v6 and v4.
1539
-	err = c.NetworkConnect(ctx, netId46, ctrId, nil)
1539
+	_, err = c.NetworkConnect(ctx, netId46, client.NetworkConnectOptions{
1540
+		Container: ctrId,
1541
+	})
1540 1542
 	assert.NilError(t, err)
1541 1543
 	checkProxies(ctx, t, c, d.Pid(), []expProxyCfg{
1542 1544
 		{"tcp", "0.0.0.0", "8080", ctrName, netName46, true, "80"},
... ...
@@ -1544,7 +1548,7 @@ func TestGatewaySelection(t *testing.T) {
1544 1544
 	})
1545 1545
 
1546 1546
 	// Go back to the IPv4-only gateway, with proxy from host IPv6.
1547
-	err = c.NetworkDisconnect(ctx, netId46, ctrId, false)
1547
+	_, err = c.NetworkDisconnect(ctx, netId46, client.NetworkDisconnectOptions{Container: ctrId, Force: false})
1548 1548
 	assert.NilError(t, err)
1549 1549
 	checkProxies(ctx, t, c, d.Pid(), []expProxyCfg{
1550 1550
 		{"tcp", "0.0.0.0", "8080", ctrName, netName4, true, "80"},
... ...
@@ -1553,7 +1557,9 @@ func TestGatewaySelection(t *testing.T) {
1553 1553
 
1554 1554
 	// Connect the IPv6-only ipvlan network, its new Endpoint should become the IPv6
1555 1555
 	// gateway, so the IPv4-only bridge is expected to drop its mapping from host IPv6.
1556
-	err = c.NetworkConnect(ctx, netIdIpvlan6, ctrId, nil)
1556
+	_, err = c.NetworkConnect(ctx, netIdIpvlan6, client.NetworkConnectOptions{
1557
+		Container: ctrId,
1558
+	})
1557 1559
 	assert.NilError(t, err)
1558 1560
 	checkProxies(ctx, t, c, d.Pid(), []expProxyCfg{
1559 1561
 		{"tcp", "0.0.0.0", "8080", ctrName, netName4, true, "80"},
... ...
@@ -157,27 +157,31 @@ func TestEtcHostsDisconnect(t *testing.T) {
157 157
 
158 158
 	// Connect a second network (don't do this in the Run, because then the /etc/hosts
159 159
 	// entries for the two networks can end up in either order).
160
-	err = c.NetworkConnect(ctx, netName2, ctrName, nil)
160
+	_, err = c.NetworkConnect(ctx, netName2, client.NetworkConnectOptions{
161
+		Container: ctrName,
162
+	})
161 163
 	assert.Check(t, err)
162 164
 	golden.Assert(t, getEtcHosts(), "TestEtcHostsDisconnect1.golden")
163 165
 
164 166
 	// Disconnect net1, its hosts entries are currently before net2's.
165
-	err = c.NetworkDisconnect(ctx, netName1, ctrName, false)
167
+	_, err = c.NetworkDisconnect(ctx, netName1, client.NetworkDisconnectOptions{Container: ctrName, Force: false})
166 168
 	assert.Check(t, err)
167 169
 	golden.Assert(t, getEtcHosts(), "TestEtcHostsDisconnect2.golden")
168 170
 
169 171
 	// Reconnect net1, so that its entries will follow net2's.
170
-	err = c.NetworkConnect(ctx, netName1, ctrName, nil)
172
+	_, err = c.NetworkConnect(ctx, netName1, client.NetworkConnectOptions{
173
+		Container: ctrName,
174
+	})
171 175
 	assert.Check(t, err)
172 176
 	golden.Assert(t, getEtcHosts(), "TestEtcHostsDisconnect3.golden")
173 177
 
174 178
 	// Disconnect net1 again, removing its entries from the end of the file.
175
-	err = c.NetworkDisconnect(ctx, netName1, ctrName, false)
179
+	_, err = c.NetworkDisconnect(ctx, netName1, client.NetworkDisconnectOptions{Container: ctrName, Force: false})
176 180
 	assert.Check(t, err)
177 181
 	golden.Assert(t, getEtcHosts(), "TestEtcHostsDisconnect4.golden")
178 182
 
179 183
 	// Disconnect net2, the only network.
180
-	err = c.NetworkDisconnect(ctx, netName2, ctrName, false)
184
+	_, err = c.NetworkDisconnect(ctx, netName2, client.NetworkDisconnectOptions{Container: ctrName, Force: false})
181 185
 	assert.Check(t, err)
182 186
 	golden.Assert(t, getEtcHosts(), "TestEtcHostsDisconnect5.golden")
183 187
 }
... ...
@@ -109,7 +109,9 @@ func TestInternalNetworkDNS(t *testing.T) {
109 109
 
110 110
 	// Connect the container to the internal network as well.
111 111
 	// External DNS should still be used.
112
-	err = c.NetworkConnect(ctx, intNetName, ctrId, nil)
112
+	_, err = c.NetworkConnect(ctx, intNetName, client.NetworkConnectOptions{
113
+		Container: ctrId,
114
+	})
113 115
 	assert.NilError(t, err)
114 116
 	res, err = container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
115 117
 	assert.NilError(t, err)
... ...
@@ -118,7 +120,7 @@ func TestInternalNetworkDNS(t *testing.T) {
118 118
 
119 119
 	// Disconnect from the external network.
120 120
 	// Expect no access to the external DNS.
121
-	err = c.NetworkDisconnect(ctx, extNetName, ctrId, true)
121
+	_, err = c.NetworkDisconnect(ctx, extNetName, client.NetworkDisconnectOptions{Container: ctrId, Force: true})
122 122
 	assert.NilError(t, err)
123 123
 	res, err = container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
124 124
 	assert.NilError(t, err)
... ...
@@ -127,7 +129,9 @@ func TestInternalNetworkDNS(t *testing.T) {
127 127
 
128 128
 	// Reconnect the external network.
129 129
 	// Check that the external DNS server is used again.
130
-	err = c.NetworkConnect(ctx, extNetName, ctrId, nil)
130
+	_, err = c.NetworkConnect(ctx, extNetName, client.NetworkConnectOptions{
131
+		Container: ctrId,
132
+	})
131 133
 	assert.NilError(t, err)
132 134
 	res, err = container.Exec(ctx, c, ctrId, []string{"nslookup", "test.example"})
133 135
 	assert.NilError(t, err)
... ...
@@ -122,7 +122,7 @@ func TestCreateServiceMultipleTimes(t *testing.T) {
122 122
 	poll.WaitOn(t, swarm.NoTasksForService(ctx, apiClient, serviceID2), swarm.ServicePoll)
123 123
 
124 124
 	for retry := 0; retry < 5; retry++ {
125
-		err = apiClient.NetworkRemove(ctx, overlayID)
125
+		_, err = apiClient.NetworkRemove(ctx, overlayID, client.NetworkRemoveOptions{})
126 126
 		// TODO(dperny): using strings.Contains for error checking is awful,
127 127
 		// but so is the fact that swarm functions don't return errdefs errors.
128 128
 		// I don't have time at this moment to fix the latter, so I guess I'll
... ...
@@ -47,9 +47,12 @@ func TestDockerNetworkConnectAliasPreV144(t *testing.T) {
47 47
 		}
48 48
 	})
49 49
 
50
-	err := apiClient.NetworkConnect(ctx, name, cID1, &network.EndpointSettings{
51
-		Aliases: []string{
52
-			"aaa",
50
+	_, err := apiClient.NetworkConnect(ctx, name, client.NetworkConnectOptions{
51
+		Container: cID1,
52
+		EndpointConfig: &network.EndpointSettings{
53
+			Aliases: []string{
54
+				"aaa",
55
+			},
53 56
 		},
54 57
 	})
55 58
 	assert.NilError(t, err)
... ...
@@ -70,9 +73,12 @@ func TestDockerNetworkConnectAliasPreV144(t *testing.T) {
70 70
 		}
71 71
 	})
72 72
 
73
-	err = apiClient.NetworkConnect(ctx, name, cID2, &network.EndpointSettings{
74
-		Aliases: []string{
75
-			"bbb",
73
+	_, err = apiClient.NetworkConnect(ctx, name, client.NetworkConnectOptions{
74
+		Container: cID2,
75
+		EndpointConfig: &network.EndpointSettings{
76
+			Aliases: []string{
77
+				"bbb",
78
+			},
76 79
 		},
77 80
 	})
78 81
 	assert.NilError(t, err)
... ...
@@ -108,7 +114,10 @@ func TestDockerNetworkReConnect(t *testing.T) {
108 108
 		}
109 109
 	})
110 110
 
111
-	err := apiClient.NetworkConnect(ctx, name, c1, &network.EndpointSettings{})
111
+	_, err := apiClient.NetworkConnect(ctx, name, client.NetworkConnectOptions{
112
+		Container:      c1,
113
+		EndpointConfig: &network.EndpointSettings{},
114
+	})
112 115
 	assert.NilError(t, err)
113 116
 
114 117
 	_, err = apiClient.ContainerStart(ctx, c1, client.ContainerStartOptions{})
... ...
@@ -117,7 +126,10 @@ func TestDockerNetworkReConnect(t *testing.T) {
117 117
 	n1, err := apiClient.ContainerInspect(ctx, c1, client.ContainerInspectOptions{})
118 118
 	assert.NilError(t, err)
119 119
 
120
-	err = apiClient.NetworkConnect(ctx, name, c1, &network.EndpointSettings{})
120
+	_, err = apiClient.NetworkConnect(ctx, name, client.NetworkConnectOptions{
121
+		Container:      c1,
122
+		EndpointConfig: &network.EndpointSettings{},
123
+	})
121 124
 	assert.ErrorContains(t, err, "is already attached to network")
122 125
 
123 126
 	n2, err := apiClient.ContainerInspect(ctx, c1, client.ContainerInspectOptions{})
... ...
@@ -275,7 +275,7 @@ func TestServiceUpdateNetwork(t *testing.T) {
275 275
 	assert.NilError(t, err)
276 276
 	assert.Assert(t, len(netInfo.Network.Containers) == 0, "Load balancing endpoint still exists in network")
277 277
 
278
-	err = apiClient.NetworkRemove(ctx, overlayID)
278
+	_, err = apiClient.NetworkRemove(ctx, overlayID, client.NetworkRemoveOptions{})
279 279
 	assert.NilError(t, err)
280 280
 
281 281
 	_, err = apiClient.ServiceRemove(ctx, serviceID, client.ServiceRemoveOptions{})
... ...
@@ -157,7 +157,7 @@ func deleteAllNetworks(ctx context.Context, t testing.TB, c client.NetworkAPICli
157 157
 			// nat is a pre-defined network on Windows and cannot be removed
158 158
 			continue
159 159
 		}
160
-		err := c.NetworkRemove(ctx, nw.ID)
160
+		_, err := c.NetworkRemove(ctx, nw.ID, client.NetworkRemoveOptions{})
161 161
 		assert.Check(t, err, "failed to remove network %s", nw.ID)
162 162
 	}
163 163
 }
... ...
@@ -117,12 +117,12 @@ type ImageAPIClient interface {
117 117
 
118 118
 // NetworkAPIClient defines API client methods for the networks
119 119
 type NetworkAPIClient interface {
120
-	NetworkConnect(ctx context.Context, network, container string, config *network.EndpointSettings) error
120
+	NetworkConnect(ctx context.Context, network string, options NetworkConnectOptions) (NetworkConnectResult, error)
121 121
 	NetworkCreate(ctx context.Context, name string, options NetworkCreateOptions) (network.CreateResponse, error)
122
-	NetworkDisconnect(ctx context.Context, network, container string, force bool) error
122
+	NetworkDisconnect(ctx context.Context, network string, options NetworkDisconnectOptions) (NetworkDisconnectResult, error)
123 123
 	NetworkInspect(ctx context.Context, network string, options NetworkInspectOptions) (NetworkInspectResult, error)
124 124
 	NetworkList(ctx context.Context, options NetworkListOptions) (NetworkListResult, error)
125
-	NetworkRemove(ctx context.Context, network string) error
125
+	NetworkRemove(ctx context.Context, network string, options NetworkRemoveOptions) (NetworkRemoveResult, error)
126 126
 	NetworksPrune(ctx context.Context, opts NetworkPruneOptions) (NetworkPruneResult, error)
127 127
 }
128 128
 
... ...
@@ -6,23 +6,35 @@ import (
6 6
 	"github.com/moby/moby/api/types/network"
7 7
 )
8 8
 
9
+// NetworkConnectOptions represents the data to be used to connect a container to the
10
+// network.
11
+type NetworkConnectOptions struct {
12
+	Container      string
13
+	EndpointConfig *network.EndpointSettings
14
+}
15
+
16
+// NetworkConnectResult represents the result of a NetworkConnect operation.
17
+type NetworkConnectResult struct {
18
+	// Currently empty; placeholder for future fields.
19
+}
20
+
9 21
 // NetworkConnect connects a container to an existent network in the docker host.
10
-func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error {
22
+func (cli *Client) NetworkConnect(ctx context.Context, networkID string, options NetworkConnectOptions) (NetworkConnectResult, error) {
11 23
 	networkID, err := trimID("network", networkID)
12 24
 	if err != nil {
13
-		return err
25
+		return NetworkConnectResult{}, err
14 26
 	}
15 27
 
16
-	containerID, err = trimID("container", containerID)
28
+	containerID, err := trimID("container", options.Container)
17 29
 	if err != nil {
18
-		return err
30
+		return NetworkConnectResult{}, err
19 31
 	}
20 32
 
21
-	req := network.ConnectRequest{
33
+	nc := network.ConnectRequest{
22 34
 		Container:      containerID,
23
-		EndpointConfig: config,
35
+		EndpointConfig: options.EndpointConfig,
24 36
 	}
25
-	resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, req, nil)
37
+	resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil)
26 38
 	defer ensureReaderClosed(resp)
27
-	return err
39
+	return NetworkConnectResult{}, err
28 40
 }
29 41
deleted file mode 100644
... ...
@@ -1,10 +0,0 @@
1
-package client
2
-
3
-import "github.com/moby/moby/api/types/network"
4
-
5
-// NetworkConnectOptions represents the data to be used to connect a container to the
6
-// network.
7
-type NetworkConnectOptions struct {
8
-	Container      string
9
-	EndpointConfig *network.EndpointSettings `json:",omitempty"`
10
-}
... ...
@@ -6,23 +6,35 @@ import (
6 6
 	"github.com/moby/moby/api/types/network"
7 7
 )
8 8
 
9
+// NetworkDisconnectOptions represents the data to be used to disconnect a container
10
+// from the network.
11
+type NetworkDisconnectOptions struct {
12
+	Container string
13
+	Force     bool
14
+}
15
+
16
+// NetworkDisconnectResult represents the result of a NetworkDisconnect operation.
17
+type NetworkDisconnectResult struct {
18
+	// Currently empty; placeholder for future fields.
19
+}
20
+
9 21
 // NetworkDisconnect disconnects a container from an existent network in the docker host.
10
-func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error {
22
+func (cli *Client) NetworkDisconnect(ctx context.Context, networkID string, options NetworkDisconnectOptions) (NetworkDisconnectResult, error) {
11 23
 	networkID, err := trimID("network", networkID)
12 24
 	if err != nil {
13
-		return err
25
+		return NetworkDisconnectResult{}, err
14 26
 	}
15 27
 
16
-	containerID, err = trimID("container", containerID)
28
+	containerID, err := trimID("container", options.Container)
17 29
 	if err != nil {
18
-		return err
30
+		return NetworkDisconnectResult{}, err
19 31
 	}
20 32
 
21 33
 	req := network.DisconnectRequest{
22 34
 		Container: containerID,
23
-		Force:     force,
35
+		Force:     options.Force,
24 36
 	}
25 37
 	resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, req, nil)
26 38
 	defer ensureReaderClosed(resp)
27
-	return err
39
+	return NetworkDisconnectResult{}, err
28 40
 }
29 41
deleted file mode 100644
... ...
@@ -1,8 +0,0 @@
1
-package client
2
-
3
-// NetworkDisconnectOptions represents the data to be used to disconnect a container
4
-// from the network.
5
-type NetworkDisconnectOptions struct {
6
-	Container string
7
-	Force     bool
8
-}
... ...
@@ -1,14 +1,26 @@
1 1
 package client
2 2
 
3
-import "context"
3
+import (
4
+	"context"
5
+)
6
+
7
+// NetworkRemoveOptions specifies options for removing a network.
8
+type NetworkRemoveOptions struct {
9
+	// No options currently; placeholder for future use.
10
+}
11
+
12
+// NetworkRemoveResult represents the result of a network removal operation.
13
+type NetworkRemoveResult struct {
14
+	// No fields currently; placeholder for future use.
15
+}
4 16
 
5 17
 // NetworkRemove removes an existent network from the docker host.
6
-func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error {
18
+func (cli *Client) NetworkRemove(ctx context.Context, networkID string, options NetworkRemoveOptions) (NetworkRemoveResult, error) {
7 19
 	networkID, err := trimID("network", networkID)
8 20
 	if err != nil {
9
-		return err
21
+		return NetworkRemoveResult{}, err
10 22
 	}
11 23
 	resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil)
12 24
 	defer ensureReaderClosed(resp)
13
-	return err
25
+	return NetworkRemoveResult{}, err
14 26
 }