Merge pull request #54127 from corhere/fix-network-ls-filter-test

daemon/network: match any type filter value
This commit is contained in:
Sebastiaan van Stijn authored and GitHub committed 2026-11-04 23:08:21 +01:00
commit 99e4cd4d36
5 files changed
+124 -95

No files matched your search

+4 -8
View File
@@ -1,6 +1,7 @@
package network
import (
"slices"
"time"
"github.com/moby/moby/v2/daemon/internal/filters"
@@ -176,13 +177,8 @@ func matchesUse(danglingOnly bool, nw FilterNetwork) bool {
}
func matchesType(netTypes []string, nw FilterNetwork) bool {
for _, netType := range netTypes {
switch netType {
case "builtin":
return IsPredefined(nw.Name())
case "custom":
return !IsPredefined(nw.Name())
}
if IsPredefined(nw.Name()) {
return slices.Contains(netTypes, "builtin")
}
return false
return slices.Contains(netTypes, "custom")
}
+5
View File
@@ -173,6 +173,11 @@ func TestFilter(t *testing.T) {
filter: filters.NewArgs(filters.Arg("type", "builtin")),
results: []string{network.NetworkHost, network.NetworkBridge, network.NetworkNone},
},
{
subtest: "type=builtin,type=custom",
filter: filters.NewArgs(filters.Arg("type", "builtin"), filters.Arg("type", "custom")),
results: []string{network.NetworkHost, network.NetworkBridge, network.NetworkNone, "myoverlay", "mydrivernet", "mykvnet", "networkwithcontainer", "networkwithservice", "idoverlap"},
},
{
subtest: "type=invalid",
filter: filters.NewArgs(filters.Arg("type", "invalid")),
@@ -273,22 +273,6 @@ func isNwPresent(t *testing.T, name string) bool {
return false
}
// assertNwList checks network list retrieved with ls command
// equals to expected network list
// note: out should be `network ls [option]` result
func assertNwList(t *testing.T, out string, expectNws []string) {
lines := strings.Split(out, "\n")
var nwList []string
for _, line := range lines[1 : len(lines)-1] {
netFields := strings.Fields(line)
// wrap all network name in nwList
nwList = append(nwList, netFields[1])
}
// network ls should contains all expected networks
assert.DeepEqual(t, nwList, expectNws)
}
func getNwResource(t *testing.T, name string) *network.Inspect {
out := cli.DockerCmd(t, "network", "inspect", name).Stdout()
var nr []network.Inspect
@@ -306,63 +290,6 @@ func (s *DockerNetworkSuite) TestDockerNetworkCreateHostBind(c *testing.T) {
assert.Assert(c, is.Contains(out, "192.168.10.1:5000->5000/tcp"))
}
func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *testing.T) {
testRequires(c, func() bool { return OnlyDefaultNetworks(testutil.GetContext(c)) })
testNet := "testnet1"
testLabel := "foo"
testValue := "bar"
out := cli.DockerCmd(c, "network", "create", "dev").Stdout()
defer func() {
cli.DockerCmd(c, "network", "rm", "dev")
cli.DockerCmd(c, "network", "rm", testNet)
}()
networkID := strings.TrimSpace(out)
// filter with partial ID
// only show 'dev' network
out = cli.DockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5]).Stdout()
assertNwList(c, out, []string{"dev"})
out = cli.DockerCmd(c, "network", "ls", "-f", "name=dge").Stdout()
assertNwList(c, out, []string{"bridge"})
// only show built-in network (bridge, none, host)
out = cli.DockerCmd(c, "network", "ls", "-f", "type=builtin").Stdout()
assertNwList(c, out, []string{"bridge", "host", "none"})
// only show custom networks (dev)
out = cli.DockerCmd(c, "network", "ls", "-f", "type=custom").Stdout()
assertNwList(c, out, []string{"dev"})
// show all networks with filter
// it should be equivalent of ls without option
out = cli.DockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin").Stdout()
assertNwList(c, out, []string{"bridge", "dev", "host", "none"})
cli.DockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet)
assertNwIsAvailable(c, testNet)
out = cli.DockerCmd(c, "network", "ls", "-f", "label="+testLabel).Stdout()
assertNwList(c, out, []string{testNet})
out = cli.DockerCmd(c, "network", "ls", "-f", "label="+testLabel+"="+testValue).Stdout()
assertNwList(c, out, []string{testNet})
out = cli.DockerCmd(c, "network", "ls", "-f", "label=nonexistent").Stdout()
outArr := strings.Split(strings.TrimSpace(out), "\n")
assert.Equal(c, len(outArr), 1, out+"\n")
out = cli.DockerCmd(c, "network", "ls", "-f", "driver=null").Stdout()
assertNwList(c, out, []string{"none"})
out = cli.DockerCmd(c, "network", "ls", "-f", "driver=host").Stdout()
assertNwList(c, out, []string{"host"})
out = cli.DockerCmd(c, "network", "ls", "-f", "driver=bridge").Stdout()
assertNwList(c, out, []string{"bridge", "dev", testNet})
}
func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *testing.T) {
cli.DockerCmd(c, "network", "create", "test")
assertNwIsAvailable(c, "test")
-14
View File
@@ -1,7 +1,6 @@
package main
import (
"context"
"errors"
"net"
"net/http"
@@ -16,7 +15,6 @@ import (
"github.com/containerd/containerd/v2/plugins"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/client"
"github.com/moby/moby/v2/internal/testutil/registry"
)
@@ -28,18 +26,6 @@ func DaemonIsLinux() bool {
return testEnv.DaemonInfo.OSType == "linux"
}
func OnlyDefaultNetworks(ctx context.Context) bool {
apiClient, err := client.New(client.FromEnv)
if err != nil {
return false
}
res, err := apiClient.NetworkList(ctx, client.NetworkListOptions{})
if err != nil || len(res.Items) > 0 {
return false
}
return true
}
func IsAmd64() bool {
return testEnv.DaemonInfo.Architecture == "amd64"
}
+115
View File
@@ -232,6 +232,121 @@ func TestForbidDuplicateNetworkNames(t *testing.T) {
assert.Error(t, err, "Error response from daemon: network with name testnet already exists", "2nd NetworkCreate call should have failed")
}
// TestNetworkListFilters checks the id, name, type, label and driver filter
// terms of GET /networks. Expectations that depend on which other networks
// the daemon has are derived from the unfiltered list.
func TestNetworkListFilters(t *testing.T) {
ctx := setupTest(t)
apiClient := testEnv.APIClient()
const (
devName = "test-list-filters-dev"
labelledName = "test-list-filters-labelled"
labelKey = "com.example.test-list-filters"
labelValue = "bar"
)
devID := network.CreateNoError(ctx, t, apiClient, devName)
defer network.RemoveNoError(ctx, t, apiClient, devName)
network.CreateNoError(ctx, t, apiClient, labelledName, func(o *client.NetworkCreateOptions) {
o.Labels = map[string]string{labelKey: labelValue}
})
defer network.RemoveNoError(ctx, t, apiClient, labelledName)
list := func(t *testing.T, filters client.Filters) []networktypes.Summary {
t.Helper()
res, err := apiClient.NetworkList(ctx, client.NetworkListOptions{Filters: filters})
assert.NilError(t, err)
return res.Items
}
names := func(nws []networktypes.Summary, match func(networktypes.Summary) bool) []string {
out := []string{}
for _, nw := range nws {
if match(nw) {
out = append(out, nw.Name)
}
}
slices.Sort(out)
return out
}
anyNetwork := func(networktypes.Summary) bool { return true }
all := list(t, nil)
assert.Assert(t, is.Contains(names(all, anyNetwork), devName))
assert.Assert(t, is.Contains(names(all, anyNetwork), labelledName))
predefined := []string{networktypes.NetworkBridge, networktypes.NetworkHost, networktypes.NetworkNone}
tests := []struct {
name string
filters client.Filters
expected []string
}{
{
name: "id prefix",
filters: make(client.Filters).Add("id", devID[:12]),
expected: []string{devName},
},
{
name: "name substring",
filters: make(client.Filters).Add("name", "list-filters-dev"),
expected: []string{devName},
},
{
name: "type=builtin",
filters: make(client.Filters).Add("type", "builtin"),
expected: predefined,
},
{
name: "type=custom",
filters: make(client.Filters).Add("type", "custom"),
expected: names(all, func(nw networktypes.Summary) bool {
return !slices.Contains(predefined, nw.Name)
}),
},
{
name: "type=builtin and type=custom",
filters: make(client.Filters).Add("type", "builtin", "custom"),
expected: names(all, anyNetwork),
},
{
name: "label key",
filters: make(client.Filters).Add("label", labelKey),
expected: []string{labelledName},
},
{
name: "label key=value",
filters: make(client.Filters).Add("label", labelKey+"="+labelValue),
expected: []string{labelledName},
},
{
name: "label key not set",
filters: make(client.Filters).Add("label", labelKey+".unset"),
expected: []string{},
},
{
name: "driver=null",
filters: make(client.Filters).Add("driver", "null"),
expected: []string{networktypes.NetworkNone},
},
{
name: "driver=host",
filters: make(client.Filters).Add("driver", "host"),
expected: []string{networktypes.NetworkHost},
},
{
name: "driver=bridge",
filters: make(client.Filters).Add("driver", "bridge"),
expected: names(all, func(nw networktypes.Summary) bool {
return nw.Driver == "bridge"
}),
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Check(t, is.DeepEqual(names(list(t, tc.filters), anyNetwork), tc.expected))
})
}
}
// TestHostGatewayFromDocker0 checks that, when docker0 has IPv6, host-gateway maps to both IPv4 and IPv6.
func TestHostGatewayFromDocker0(t *testing.T) {
ctx := testutil.StartSpan(baseContext, t)