Browse Source

Merge pull request #45392 from thaJeztah/filters_inline_and_simplify

inline filters.Args where possible, and use filters.Arg() when constructing
Tianon Gravi 2 years ago
parent
commit
4597f50deb

+ 4 - 5
client/config_list_test.go

@@ -42,10 +42,6 @@ func TestConfigListError(t *testing.T) {
 func TestConfigList(t *testing.T) {
 	expectedURL := "/v1.30/configs"
 
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
-
 	listCases := []struct {
 		options             types.ConfigListOptions
 		expectedQueryParams map[string]string
@@ -58,7 +54,10 @@ func TestConfigList(t *testing.T) {
 		},
 		{
 			options: types.ConfigListOptions{
-				Filters: filters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+				),
 			},
 			expectedQueryParams: map[string]string{
 				"filters": `{"label":{"label1":true,"label2":true}}`,

+ 11 - 11
client/container_list_test.go

@@ -54,9 +54,9 @@ func TestContainerList(t *testing.T) {
 			if size != "1" {
 				return nil, fmt.Errorf("size not set in URL query properly. Expected '1', got %s", size)
 			}
-			filters := query.Get("filters")
-			if filters != expectedFilters {
-				return nil, fmt.Errorf("expected filters incoherent '%v' with actual filters %v", expectedFilters, filters)
+			fltrs := query.Get("filters")
+			if fltrs != expectedFilters {
+				return nil, fmt.Errorf("expected filters incoherent '%v' with actual filters %v", expectedFilters, fltrs)
 			}
 
 			b, err := json.Marshal([]types.Container{
@@ -78,15 +78,15 @@ func TestContainerList(t *testing.T) {
 		}),
 	}
 
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
-	filters.Add("before", "container")
 	containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{
-		Size:    true,
-		All:     true,
-		Since:   "container",
-		Filters: filters,
+		Size:  true,
+		All:   true,
+		Since: "container",
+		Filters: filters.NewArgs(
+			filters.Arg("label", "label1"),
+			filters.Arg("label", "label2"),
+			filters.Arg("before", "container"),
+		),
 	})
 	if err != nil {
 		t.Fatal(err)

+ 12 - 22
client/container_prune_test.go

@@ -23,9 +23,7 @@ func TestContainersPruneError(t *testing.T) {
 		version: "1.25",
 	}
 
-	filters := filters.NewArgs()
-
-	_, err := client.ContainersPrune(context.Background(), filters)
+	_, err := client.ContainersPrune(context.Background(), filters.Args{})
 	if !errdefs.IsSystem(err) {
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 	}
@@ -34,21 +32,6 @@ func TestContainersPruneError(t *testing.T) {
 func TestContainersPrune(t *testing.T) {
 	expectedURL := "/v1.25/containers/prune"
 
-	danglingFilters := filters.NewArgs()
-	danglingFilters.Add("dangling", "true")
-
-	noDanglingFilters := filters.NewArgs()
-	noDanglingFilters.Add("dangling", "false")
-
-	danglingUntilFilters := filters.NewArgs()
-	danglingUntilFilters.Add("dangling", "true")
-	danglingUntilFilters.Add("until", "2016-12-15T14:00")
-
-	labelFilters := filters.NewArgs()
-	labelFilters.Add("dangling", "true")
-	labelFilters.Add("label", "label1=foo")
-	labelFilters.Add("label", "label2!=bar")
-
 	listCases := []struct {
 		filters             filters.Args
 		expectedQueryParams map[string]string
@@ -62,7 +45,7 @@ func TestContainersPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: danglingFilters,
+			filters: filters.NewArgs(filters.Arg("dangling", "true")),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -70,7 +53,10 @@ func TestContainersPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: danglingUntilFilters,
+			filters: filters.NewArgs(
+				filters.Arg("dangling", "true"),
+				filters.Arg("until", "2016-12-15T14:00"),
+			),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -78,7 +64,7 @@ func TestContainersPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: noDanglingFilters,
+			filters: filters.NewArgs(filters.Arg("dangling", "false")),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -86,7 +72,11 @@ func TestContainersPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: labelFilters,
+			filters: filters.NewArgs(
+				filters.Arg("dangling", "true"),
+				filters.Arg("label", "label1=foo"),
+				filters.Arg("label", "label2!=bar"),
+			),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",

+ 4 - 5
client/events_test.go

@@ -58,10 +58,9 @@ func TestEventsErrorFromServer(t *testing.T) {
 }
 
 func TestEvents(t *testing.T) {
-	expectedURL := "/events"
+	const expectedURL = "/events"
 
-	filters := filters.NewArgs()
-	filters.Add("type", events.ContainerEventType)
+	fltrs := filters.NewArgs(filters.Arg("type", events.ContainerEventType))
 	expectedFiltersJSON := fmt.Sprintf(`{"type":{"%s":true}}`, events.ContainerEventType)
 
 	eventsCases := []struct {
@@ -72,7 +71,7 @@ func TestEvents(t *testing.T) {
 	}{
 		{
 			options: types.EventsOptions{
-				Filters: filters,
+				Filters: fltrs,
 			},
 			expectedQueryParams: map[string]string{
 				"filters": expectedFiltersJSON,
@@ -82,7 +81,7 @@ func TestEvents(t *testing.T) {
 		},
 		{
 			options: types.EventsOptions{
-				Filters: filters,
+				Filters: fltrs,
 			},
 			expectedQueryParams: map[string]string{
 				"filters": expectedFiltersJSON,

+ 8 - 15
client/image_list_test.go

@@ -30,15 +30,7 @@ func TestImageListError(t *testing.T) {
 }
 
 func TestImageList(t *testing.T) {
-	expectedURL := "/images/json"
-
-	noDanglingfilters := filters.NewArgs()
-	noDanglingfilters.Add("dangling", "false")
-
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
-	filters.Add("dangling", "true")
+	const expectedURL = "/images/json"
 
 	listCases := []struct {
 		options             types.ImageListOptions
@@ -54,7 +46,11 @@ func TestImageList(t *testing.T) {
 		},
 		{
 			options: types.ImageListOptions{
-				Filters: filters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+					filters.Arg("dangling", "true"),
+				),
 			},
 			expectedQueryParams: map[string]string{
 				"all":     "",
@@ -64,7 +60,7 @@ func TestImageList(t *testing.T) {
 		},
 		{
 			options: types.ImageListOptions{
-				Filters: noDanglingfilters,
+				Filters: filters.NewArgs(filters.Arg("dangling", "false")),
 			},
 			expectedQueryParams: map[string]string{
 				"all":     "",
@@ -146,11 +142,8 @@ func TestImageListApiBefore125(t *testing.T) {
 		version: "1.24",
 	}
 
-	filters := filters.NewArgs()
-	filters.Add("reference", "image:tag")
-
 	options := types.ImageListOptions{
-		Filters: filters,
+		Filters: filters.NewArgs(filters.Arg("reference", "image:tag")),
 	}
 
 	images, err := client.ImageList(context.Background(), options)

+ 8 - 15
client/image_prune_test.go

@@ -31,18 +31,7 @@ func TestImagesPruneError(t *testing.T) {
 }
 
 func TestImagesPrune(t *testing.T) {
-	expectedURL := "/v1.25/images/prune"
-
-	danglingFilters := filters.NewArgs()
-	danglingFilters.Add("dangling", "true")
-
-	noDanglingFilters := filters.NewArgs()
-	noDanglingFilters.Add("dangling", "false")
-
-	labelFilters := filters.NewArgs()
-	labelFilters.Add("dangling", "true")
-	labelFilters.Add("label", "label1=foo")
-	labelFilters.Add("label", "label2!=bar")
+	const expectedURL = "/v1.25/images/prune"
 
 	listCases := []struct {
 		filters             filters.Args
@@ -57,7 +46,7 @@ func TestImagesPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: danglingFilters,
+			filters: filters.NewArgs(filters.Arg("dangling", "true")),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -65,7 +54,7 @@ func TestImagesPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: noDanglingFilters,
+			filters: filters.NewArgs(filters.Arg("dangling", "false")),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -73,7 +62,11 @@ func TestImagesPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: labelFilters,
+			filters: filters.NewArgs(
+				filters.Arg("dangling", "true"),
+				filters.Arg("label", "label1=foo"),
+				filters.Arg("label", "label2!=bar"),
+			),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",

+ 9 - 10
client/image_search_test.go

@@ -118,12 +118,8 @@ func TestImageSearchWithPrivilegedFuncNoError(t *testing.T) {
 }
 
 func TestImageSearchWithoutErrors(t *testing.T) {
-	expectedURL := "/images/search"
-	filterArgs := filters.NewArgs()
-	filterArgs.Add("is-automated", "true")
-	filterArgs.Add("stars", "3")
-
-	expectedFilters := `{"is-automated":{"true":true},"stars":{"3":true}}`
+	const expectedURL = "/images/search"
+	const expectedFilters = `{"is-automated":{"true":true},"stars":{"3":true}}`
 
 	client := &Client{
 		client: newMockClient(func(req *http.Request) (*http.Response, error) {
@@ -135,9 +131,9 @@ func TestImageSearchWithoutErrors(t *testing.T) {
 			if term != "some-image" {
 				return nil, fmt.Errorf("term not set in URL query properly. Expected 'some-image', got %s", term)
 			}
-			filters := query.Get("filters")
-			if filters != expectedFilters {
-				return nil, fmt.Errorf("filters not set in URL query properly. Expected '%s', got %s", expectedFilters, filters)
+			fltrs := query.Get("filters")
+			if fltrs != expectedFilters {
+				return nil, fmt.Errorf("filters not set in URL query properly. Expected '%s', got %s", expectedFilters, fltrs)
 			}
 			content, err := json.Marshal([]registry.SearchResult{
 				{
@@ -154,7 +150,10 @@ func TestImageSearchWithoutErrors(t *testing.T) {
 		}),
 	}
 	results, err := client.ImageSearch(context.Background(), "some-image", types.ImageSearchOptions{
-		Filters: filterArgs,
+		Filters: filters.NewArgs(
+			filters.Arg("is-automated", "true"),
+			filters.Arg("stars", "3"),
+		),
 	})
 	if err != nil {
 		t.Fatal(err)

+ 15 - 23
client/network_list_test.go

@@ -20,49 +20,41 @@ func TestNetworkListError(t *testing.T) {
 		client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
 	}
 
-	_, err := client.NetworkList(context.Background(), types.NetworkListOptions{
-		Filters: filters.NewArgs(),
-	})
+	_, err := client.NetworkList(context.Background(), types.NetworkListOptions{})
 	if !errdefs.IsSystem(err) {
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 	}
 }
 
 func TestNetworkList(t *testing.T) {
-	expectedURL := "/networks"
-
-	noDanglingFilters := filters.NewArgs()
-	noDanglingFilters.Add("dangling", "false")
-
-	danglingFilters := filters.NewArgs()
-	danglingFilters.Add("dangling", "true")
-
-	labelFilters := filters.NewArgs()
-	labelFilters.Add("label", "label1")
-	labelFilters.Add("label", "label2")
+	const expectedURL = "/networks"
 
 	listCases := []struct {
 		options         types.NetworkListOptions
 		expectedFilters string
 	}{
 		{
-			options: types.NetworkListOptions{
-				Filters: filters.NewArgs(),
-			},
+			options:         types.NetworkListOptions{},
 			expectedFilters: "",
-		}, {
+		},
+		{
 			options: types.NetworkListOptions{
-				Filters: noDanglingFilters,
+				Filters: filters.NewArgs(filters.Arg("dangling", "false")),
 			},
 			expectedFilters: `{"dangling":{"false":true}}`,
-		}, {
+		},
+		{
 			options: types.NetworkListOptions{
-				Filters: danglingFilters,
+				Filters: filters.NewArgs(filters.Arg("dangling", "true")),
 			},
 			expectedFilters: `{"dangling":{"true":true}}`,
-		}, {
+		},
+		{
 			options: types.NetworkListOptions{
-				Filters: labelFilters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+				),
 			},
 			expectedFilters: `{"label":{"label1":true,"label2":true}}`,
 		},

+ 9 - 18
client/network_prune_test.go

@@ -23,27 +23,14 @@ func TestNetworksPruneError(t *testing.T) {
 		version: "1.25",
 	}
 
-	filters := filters.NewArgs()
-
-	_, err := client.NetworksPrune(context.Background(), filters)
+	_, err := client.NetworksPrune(context.Background(), filters.NewArgs())
 	if !errdefs.IsSystem(err) {
 		t.Fatalf("expected a Server Error, got %[1]T: %[1]v", err)
 	}
 }
 
 func TestNetworksPrune(t *testing.T) {
-	expectedURL := "/v1.25/networks/prune"
-
-	danglingFilters := filters.NewArgs()
-	danglingFilters.Add("dangling", "true")
-
-	noDanglingFilters := filters.NewArgs()
-	noDanglingFilters.Add("dangling", "false")
-
-	labelFilters := filters.NewArgs()
-	labelFilters.Add("dangling", "true")
-	labelFilters.Add("label", "label1=foo")
-	labelFilters.Add("label", "label2!=bar")
+	const expectedURL = "/v1.25/networks/prune"
 
 	listCases := []struct {
 		filters             filters.Args
@@ -58,7 +45,7 @@ func TestNetworksPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: danglingFilters,
+			filters: filters.NewArgs(filters.Arg("dangling", "true")),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -66,7 +53,7 @@ func TestNetworksPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: noDanglingFilters,
+			filters: filters.NewArgs(filters.Arg("dangling", "false")),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",
@@ -74,7 +61,11 @@ func TestNetworksPrune(t *testing.T) {
 			},
 		},
 		{
-			filters: labelFilters,
+			filters: filters.NewArgs(
+				filters.Arg("dangling", "true"),
+				filters.Arg("label", "label1=foo"),
+				filters.Arg("label", "label2!=bar"),
+			),
 			expectedQueryParams: map[string]string{
 				"until":   "",
 				"filter":  "",

+ 5 - 6
client/node_list_test.go

@@ -28,11 +28,7 @@ func TestNodeListError(t *testing.T) {
 }
 
 func TestNodeList(t *testing.T) {
-	expectedURL := "/nodes"
-
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
+	const expectedURL = "/nodes"
 
 	listCases := []struct {
 		options             types.NodeListOptions
@@ -46,7 +42,10 @@ func TestNodeList(t *testing.T) {
 		},
 		{
 			options: types.NodeListOptions{
-				Filters: filters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+				),
 			},
 			expectedQueryParams: map[string]string{
 				"filters": `{"label":{"label1":true,"label2":true}}`,

+ 6 - 10
client/plugin_list_test.go

@@ -27,14 +27,7 @@ func TestPluginListError(t *testing.T) {
 }
 
 func TestPluginList(t *testing.T) {
-	expectedURL := "/plugins"
-
-	enabledFilters := filters.NewArgs()
-	enabledFilters.Add("enabled", "true")
-
-	capabilityFilters := filters.NewArgs()
-	capabilityFilters.Add("capability", "volumedriver")
-	capabilityFilters.Add("capability", "authz")
+	const expectedURL = "/plugins"
 
 	listCases := []struct {
 		filters             filters.Args
@@ -49,7 +42,7 @@ func TestPluginList(t *testing.T) {
 			},
 		},
 		{
-			filters: enabledFilters,
+			filters: filters.NewArgs(filters.Arg("enabled", "true")),
 			expectedQueryParams: map[string]string{
 				"all":     "",
 				"filter":  "",
@@ -57,7 +50,10 @@ func TestPluginList(t *testing.T) {
 			},
 		},
 		{
-			filters: capabilityFilters,
+			filters: filters.NewArgs(
+				filters.Arg("capability", "volumedriver"),
+				filters.Arg("capability", "authz"),
+			),
 			expectedQueryParams: map[string]string{
 				"all":     "",
 				"filter":  "",

+ 5 - 6
client/secret_list_test.go

@@ -40,11 +40,7 @@ func TestSecretListError(t *testing.T) {
 }
 
 func TestSecretList(t *testing.T) {
-	expectedURL := "/v1.25/secrets"
-
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
+	const expectedURL = "/v1.25/secrets"
 
 	listCases := []struct {
 		options             types.SecretListOptions
@@ -58,7 +54,10 @@ func TestSecretList(t *testing.T) {
 		},
 		{
 			options: types.SecretListOptions{
-				Filters: filters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+				),
 			},
 			expectedQueryParams: map[string]string{
 				"filters": `{"label":{"label1":true,"label2":true}}`,

+ 5 - 6
client/service_list_test.go

@@ -28,11 +28,7 @@ func TestServiceListError(t *testing.T) {
 }
 
 func TestServiceList(t *testing.T) {
-	expectedURL := "/services"
-
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
+	const expectedURL = "/services"
 
 	listCases := []struct {
 		options             types.ServiceListOptions
@@ -46,7 +42,10 @@ func TestServiceList(t *testing.T) {
 		},
 		{
 			options: types.ServiceListOptions{
-				Filters: filters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+				),
 			},
 			expectedQueryParams: map[string]string{
 				"filters": `{"label":{"label1":true,"label2":true}}`,

+ 5 - 6
client/task_list_test.go

@@ -28,11 +28,7 @@ func TestTaskListError(t *testing.T) {
 }
 
 func TestTaskList(t *testing.T) {
-	expectedURL := "/tasks"
-
-	filters := filters.NewArgs()
-	filters.Add("label", "label1")
-	filters.Add("label", "label2")
+	const expectedURL = "/tasks"
 
 	listCases := []struct {
 		options             types.TaskListOptions
@@ -46,7 +42,10 @@ func TestTaskList(t *testing.T) {
 		},
 		{
 			options: types.TaskListOptions{
-				Filters: filters,
+				Filters: filters.NewArgs(
+					filters.Arg("label", "label1"),
+					filters.Arg("label", "label2"),
+				),
 			},
 			expectedQueryParams: map[string]string{
 				"filters": `{"label":{"label1":true,"label2":true}}`,

+ 7 - 14
client/volume_list_test.go

@@ -27,17 +27,7 @@ func TestVolumeListError(t *testing.T) {
 }
 
 func TestVolumeList(t *testing.T) {
-	expectedURL := "/volumes"
-
-	noDanglingFilters := filters.NewArgs()
-	noDanglingFilters.Add("dangling", "false")
-
-	danglingFilters := filters.NewArgs()
-	danglingFilters.Add("dangling", "true")
-
-	labelFilters := filters.NewArgs()
-	labelFilters.Add("label", "label1")
-	labelFilters.Add("label", "label2")
+	const expectedURL = "/volumes"
 
 	listCases := []struct {
 		filters         filters.Args
@@ -47,13 +37,16 @@ func TestVolumeList(t *testing.T) {
 			filters:         filters.NewArgs(),
 			expectedFilters: "",
 		}, {
-			filters:         noDanglingFilters,
+			filters:         filters.NewArgs(filters.Arg("dangling", "false")),
 			expectedFilters: `{"dangling":{"false":true}}`,
 		}, {
-			filters:         danglingFilters,
+			filters:         filters.NewArgs(filters.Arg("dangling", "true")),
 			expectedFilters: `{"dangling":{"true":true}}`,
 		}, {
-			filters:         labelFilters,
+			filters: filters.NewArgs(
+				filters.Arg("label", "label1"),
+				filters.Arg("label", "label2"),
+			),
 			expectedFilters: `{"label":{"label1":true,"label2":true}}`,
 		},
 	}

+ 5 - 5
daemon/cluster/executor/container/container.go

@@ -717,9 +717,9 @@ func (c *containerConfig) applyPrivileges(hc *enginecontainer.HostConfig) {
 }
 
 func (c containerConfig) eventFilter() filters.Args {
-	filter := filters.NewArgs()
-	filter.Add("type", events.ContainerEventType)
-	filter.Add("name", c.name())
-	filter.Add("label", fmt.Sprintf("%v.task.id=%v", systemLabelPrefix, c.task.ID))
-	return filter
+	return filters.NewArgs(
+		filters.Arg("type", events.ContainerEventType),
+		filters.Arg("name", c.name()),
+		filters.Arg("label", fmt.Sprintf("%v.task.id=%v", systemLabelPrefix, c.task.ID)),
+	)
 }

+ 34 - 40
daemon/cluster/filters_test.go

@@ -7,26 +7,23 @@ import (
 )
 
 func TestNewListSecretsFilters(t *testing.T) {
-	validNameFilter := filters.NewArgs()
-	validNameFilter.Add("name", "test_name")
-
-	validIDFilter := filters.NewArgs()
-	validIDFilter.Add("id", "7c9009d6720f6de3b492f5")
-
-	validLabelFilter := filters.NewArgs()
-	validLabelFilter.Add("label", "type=test")
-	validLabelFilter.Add("label", "storage=ssd")
-	validLabelFilter.Add("label", "memory")
-
-	validNamesFilter := filters.NewArgs()
-	validNamesFilter.Add("names", "test_name")
-
-	validAllFilter := filters.NewArgs()
-	validAllFilter.Add("name", "nodeName")
-	validAllFilter.Add("id", "7c9009d6720f6de3b492f5")
-	validAllFilter.Add("label", "type=test")
-	validAllFilter.Add("label", "memory")
-	validAllFilter.Add("names", "test_name")
+	validNameFilter := filters.NewArgs(filters.Arg("name", "test_name"))
+	validIDFilter := filters.NewArgs(filters.Arg("id", "7c9009d6720f6de3b492f5"))
+
+	validLabelFilter := filters.NewArgs(
+		filters.Arg("label", "type=test"),
+		filters.Arg("label", "storage=ssd"),
+		filters.Arg("label", "memory"),
+	)
+	validNamesFilter := filters.NewArgs(filters.Arg("names", "test_name"))
+
+	validAllFilter := filters.NewArgs(
+		filters.Arg("name", "nodeName"),
+		filters.Arg("id", "7c9009d6720f6de3b492f5"),
+		filters.Arg("label", "type=test"),
+		filters.Arg("label", "memory"),
+		filters.Arg("names", "test_name"),
+	)
 
 	validFilters := []filters.Args{
 		validNameFilter,
@@ -36,8 +33,7 @@ func TestNewListSecretsFilters(t *testing.T) {
 		validAllFilter,
 	}
 
-	invalidTypeFilter := filters.NewArgs()
-	invalidTypeFilter.Add("nonexist", "aaaa")
+	invalidTypeFilter := filters.NewArgs(filters.Arg("nonexist", "aaaa"))
 
 	invalidFilters := []filters.Args{
 		invalidTypeFilter,
@@ -57,22 +53,21 @@ func TestNewListSecretsFilters(t *testing.T) {
 }
 
 func TestNewListConfigsFilters(t *testing.T) {
-	validNameFilter := filters.NewArgs()
-	validNameFilter.Add("name", "test_name")
-
-	validIDFilter := filters.NewArgs()
-	validIDFilter.Add("id", "7c9009d6720f6de3b492f5")
-
-	validLabelFilter := filters.NewArgs()
-	validLabelFilter.Add("label", "type=test")
-	validLabelFilter.Add("label", "storage=ssd")
-	validLabelFilter.Add("label", "memory")
-
-	validAllFilter := filters.NewArgs()
-	validAllFilter.Add("name", "nodeName")
-	validAllFilter.Add("id", "7c9009d6720f6de3b492f5")
-	validAllFilter.Add("label", "type=test")
-	validAllFilter.Add("label", "memory")
+	validNameFilter := filters.NewArgs(filters.Arg("name", "test_name"))
+	validIDFilter := filters.NewArgs(filters.Arg("id", "7c9009d6720f6de3b492f5"))
+
+	validLabelFilter := filters.NewArgs(
+		filters.Arg("label", "type=test"),
+		filters.Arg("label", "storage=ssd"),
+		filters.Arg("label", "memory"),
+	)
+
+	validAllFilter := filters.NewArgs(
+		filters.Arg("name", "nodeName"),
+		filters.Arg("id", "7c9009d6720f6de3b492f5"),
+		filters.Arg("label", "type=test"),
+		filters.Arg("label", "memory"),
+	)
 
 	validFilters := []filters.Args{
 		validNameFilter,
@@ -81,8 +76,7 @@ func TestNewListConfigsFilters(t *testing.T) {
 		validAllFilter,
 	}
 
-	invalidTypeFilter := filters.NewArgs()
-	invalidTypeFilter.Add("nonexist", "aaaa")
+	invalidTypeFilter := filters.NewArgs(filters.Arg("nonexist", "aaaa"))
 
 	invalidFilters := []filters.Args{
 		invalidTypeFilter,

+ 1 - 3
daemon/cluster/swarm.go

@@ -606,10 +606,8 @@ func initClusterSpec(node *swarmnode.Node, spec types.Spec) error {
 
 func (c *Cluster) listContainerForNode(ctx context.Context, nodeID string) ([]string, error) {
 	var ids []string
-	filters := filters.NewArgs()
-	filters.Add("label", fmt.Sprintf("com.docker.swarm.node.id=%s", nodeID))
 	containers, err := c.config.Backend.Containers(ctx, &apitypes.ContainerListOptions{
-		Filters: filters,
+		Filters: filters.NewArgs(filters.Arg("label", "com.docker.swarm.node.id="+nodeID)),
 	})
 	if err != nil {
 		return []string{}, err

+ 1 - 3
daemon/list_test.go

@@ -87,10 +87,8 @@ func TestListInvalidFilter(t *testing.T) {
 		containersReplica: db,
 	}
 
-	f := filters.NewArgs(filters.Arg("invalid", "foo"))
-
 	_, err = d.Containers(context.Background(), &types.ContainerListOptions{
-		Filters: f,
+		Filters: filters.NewArgs(filters.Arg("invalid", "foo")),
 	})
 	assert.Assert(t, is.Error(err, "invalid filter 'invalid'"))
 }

+ 11 - 44
daemon/network/filter_test.go

@@ -55,39 +55,6 @@ func TestFilterNetworks(t *testing.T) {
 		},
 	}
 
-	bridgeDriverFilters := filters.NewArgs()
-	bridgeDriverFilters.Add("driver", "bridge")
-
-	overlayDriverFilters := filters.NewArgs()
-	overlayDriverFilters.Add("driver", "overlay")
-
-	nonameDriverFilters := filters.NewArgs()
-	nonameDriverFilters.Add("driver", "noname")
-
-	customDriverFilters := filters.NewArgs()
-	customDriverFilters.Add("type", "custom")
-
-	builtinDriverFilters := filters.NewArgs()
-	builtinDriverFilters.Add("type", "builtin")
-
-	invalidDriverFilters := filters.NewArgs()
-	invalidDriverFilters.Add("type", "invalid")
-
-	localScopeFilters := filters.NewArgs()
-	localScopeFilters.Add("scope", "local")
-
-	swarmScopeFilters := filters.NewArgs()
-	swarmScopeFilters.Add("scope", "swarm")
-
-	globalScopeFilters := filters.NewArgs()
-	globalScopeFilters.Add("scope", "global")
-
-	trueDanglingFilters := filters.NewArgs()
-	trueDanglingFilters.Add("dangling", "true")
-
-	falseDanglingFilters := filters.NewArgs()
-	falseDanglingFilters.Add("dangling", "false")
-
 	testCases := []struct {
 		filter      filters.Args
 		resultCount int
@@ -96,68 +63,68 @@ func TestFilterNetworks(t *testing.T) {
 		results     []string
 	}{
 		{
-			filter:      bridgeDriverFilters,
+			filter:      filters.NewArgs(filters.Arg("driver", "bridge")),
 			resultCount: 1,
 			err:         "",
 			name:        "bridge driver filters",
 		},
 		{
-			filter:      overlayDriverFilters,
+			filter:      filters.NewArgs(filters.Arg("driver", "overlay")),
 			resultCount: 1,
 			err:         "",
 			name:        "overlay driver filters",
 		},
 		{
-			filter:      nonameDriverFilters,
+			filter:      filters.NewArgs(filters.Arg("driver", "noname")),
 			resultCount: 0,
 			err:         "",
 			name:        "no name driver filters",
 		},
 		{
-			filter:      customDriverFilters,
+			filter:      filters.NewArgs(filters.Arg("type", "custom")),
 			resultCount: 4,
 			err:         "",
 			name:        "custom driver filters",
 		},
 		{
-			filter:      builtinDriverFilters,
+			filter:      filters.NewArgs(filters.Arg("type", "builtin")),
 			resultCount: 3,
 			err:         "",
 			name:        "builtin driver filters",
 		},
 		{
-			filter:      invalidDriverFilters,
+			filter:      filters.NewArgs(filters.Arg("type", "invalid")),
 			resultCount: 0,
 			err:         "invalid filter: 'type'='invalid'",
 			name:        "invalid driver filters",
 		},
 		{
-			filter:      localScopeFilters,
+			filter:      filters.NewArgs(filters.Arg("scope", "local")),
 			resultCount: 5,
 			err:         "",
 			name:        "local scope filters",
 		},
 		{
-			filter:      swarmScopeFilters,
+			filter:      filters.NewArgs(filters.Arg("scope", "swarm")),
 			resultCount: 1,
 			err:         "",
 			name:        "swarm scope filters",
 		},
 		{
-			filter:      globalScopeFilters,
+			filter:      filters.NewArgs(filters.Arg("scope", "global")),
 			resultCount: 1,
 			err:         "",
 			name:        "global scope filters",
 		},
 		{
-			filter:      trueDanglingFilters,
+			filter:      filters.NewArgs(filters.Arg("dangling", "true")),
 			resultCount: 3,
 			err:         "",
 			name:        "dangling filter is 'True'",
 			results:     []string{"myoverlay", "mydrivernet", "mykvnet"},
 		},
 		{
-			filter:      falseDanglingFilters,
+			filter:      filters.NewArgs(filters.Arg("dangling", "false")),
 			resultCount: 4,
 			err:         "",
 			name:        "dangling filter is 'False'",

+ 6 - 16
integration-cli/daemon/daemon_swarm.go

@@ -102,14 +102,9 @@ func (d *Daemon) CheckRunningTaskNetworks(c *testing.T) (interface{}, string) {
 	cli := d.NewClientT(c)
 	defer cli.Close()
 
-	filterArgs := filters.NewArgs()
-	filterArgs.Add("desired-state", "running")
-
-	options := types.TaskListOptions{
-		Filters: filterArgs,
-	}
-
-	tasks, err := cli.TaskList(context.Background(), options)
+	tasks, err := cli.TaskList(context.Background(), types.TaskListOptions{
+		Filters: filters.NewArgs(filters.Arg("desired-state", "running")),
+	})
 	assert.NilError(c, err)
 
 	result := make(map[string]int)
@@ -126,14 +121,9 @@ func (d *Daemon) CheckRunningTaskImages(c *testing.T) (interface{}, string) {
 	cli := d.NewClientT(c)
 	defer cli.Close()
 
-	filterArgs := filters.NewArgs()
-	filterArgs.Add("desired-state", "running")
-
-	options := types.TaskListOptions{
-		Filters: filterArgs,
-	}
-
-	tasks, err := cli.TaskList(context.Background(), options)
+	tasks, err := cli.TaskList(context.Background(), types.TaskListOptions{
+		Filters: filters.NewArgs(filters.Arg("desired-state", "running")),
+	})
 	assert.NilError(c, err)
 
 	result := make(map[string]int)

+ 1 - 3
integration-cli/docker_api_images_test.go

@@ -28,11 +28,9 @@ func (s *DockerAPISuite) TestAPIImagesFilter(c *testing.T) {
 		dockerCmd(c, "tag", "busybox", n)
 	}
 	getImages := func(filter string) []types.ImageSummary {
-		fltrs := filters.NewArgs()
-		fltrs.Add("reference", filter)
 		options := types.ImageListOptions{
 			All:     false,
-			Filters: fltrs,
+			Filters: filters.NewArgs(filters.Arg("reference", filter)),
 		}
 		images, err := apiClient.ImageList(context.Background(), options)
 		assert.NilError(c, err)

+ 2 - 6
integration-cli/docker_api_network_test.go

@@ -286,13 +286,9 @@ func isNetworkAvailable(c *testing.T, name string) bool {
 }
 
 func getNetworkIDByName(c *testing.T, name string) string {
-	var (
-		v          = url.Values{}
-		filterArgs = filters.NewArgs()
-	)
-	filterArgs.Add("name", name)
-	filterJSON, err := filters.ToJSON(filterArgs)
+	filterJSON, err := filters.ToJSON(filters.NewArgs(filters.Arg("name", name)))
 	assert.NilError(c, err)
+	v := url.Values{}
 	v.Set("filters", filterJSON)
 
 	resp, body, err := request.Get("/networks?" + v.Encode())

+ 1 - 3
integration/container/links_linux_test.go

@@ -45,10 +45,8 @@ func TestLinksContainerNames(t *testing.T) {
 	container.Run(ctx, t, client, container.WithName(containerA))
 	container.Run(ctx, t, client, container.WithName(containerB), container.WithLinks(containerA+":"+containerA))
 
-	f := filters.NewArgs(filters.Arg("name", containerA))
-
 	containers, err := client.ContainerList(ctx, types.ContainerListOptions{
-		Filters: f,
+		Filters: filters.NewArgs(filters.Arg("name", containerA)),
 	})
 	assert.NilError(t, err)
 	assert.Check(t, is.Equal(1, len(containers)))

+ 16 - 16
integration/container/ps_test.go

@@ -22,27 +22,27 @@ func TestPsFilter(t *testing.T) {
 
 	containerIDs := func(containers []types.Container) []string {
 		var entries []string
-		for _, container := range containers {
-			entries = append(entries, container.ID)
+		for _, c := range containers {
+			entries = append(entries, c.ID)
 		}
 		return entries
 	}
 
-	f1 := filters.NewArgs()
-	f1.Add("since", top)
-	q1, err := client.ContainerList(ctx, types.ContainerListOptions{
-		All:     true,
-		Filters: f1,
+	t.Run("since", func(t *testing.T) {
+		results, err := client.ContainerList(ctx, types.ContainerListOptions{
+			All:     true,
+			Filters: filters.NewArgs(filters.Arg("since", top)),
+		})
+		assert.NilError(t, err)
+		assert.Check(t, is.Contains(containerIDs(results), next))
 	})
-	assert.NilError(t, err)
-	assert.Check(t, is.Contains(containerIDs(q1), next))
 
-	f2 := filters.NewArgs()
-	f2.Add("before", top)
-	q2, err := client.ContainerList(ctx, types.ContainerListOptions{
-		All:     true,
-		Filters: f2,
+	t.Run("before", func(t *testing.T) {
+		results, err := client.ContainerList(ctx, types.ContainerListOptions{
+			All:     true,
+			Filters: filters.NewArgs(filters.Arg("before", top)),
+		})
+		assert.NilError(t, err)
+		assert.Check(t, is.Contains(containerIDs(results), prev))
 	})
-	assert.NilError(t, err)
-	assert.Check(t, is.Contains(containerIDs(q2), prev))
 }

+ 1 - 2
integration/internal/swarm/states.go

@@ -88,8 +88,7 @@ func RunningTasksCount(client client.ServiceAPIClient, serviceID string, instanc
 // completed additionally, while polling, it verifies that the job never
 // exceeds MaxConcurrent running tasks
 func JobComplete(client client.CommonAPIClient, service swarmtypes.Service) func(log poll.LogT) poll.Result {
-	filter := filters.NewArgs()
-	filter.Add("service", service.ID)
+	filter := filters.NewArgs(filters.Arg("service", service.ID))
 
 	var jobIteration swarmtypes.Version
 	if service.JobStatus != nil {

+ 7 - 12
integration/service/create_test.go

@@ -2,7 +2,6 @@ package service // import "github.com/docker/docker/integration/service"
 
 import (
 	"context"
-	"fmt"
 	"io"
 	"strings"
 	"testing"
@@ -65,9 +64,9 @@ func testServiceCreateInit(daemonEnabled bool) func(t *testing.T) {
 
 func inspectServiceContainer(t *testing.T, client client.APIClient, serviceID string) types.ContainerJSON {
 	t.Helper()
-	filter := filters.NewArgs()
-	filter.Add("label", fmt.Sprintf("com.docker.swarm.service.id=%s", serviceID))
-	containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{Filters: filter})
+	containers, err := client.ContainerList(context.Background(), types.ContainerListOptions{
+		Filters: filters.NewArgs(filters.Arg("label", "com.docker.swarm.service.id="+serviceID)),
+	})
 	assert.NilError(t, err)
 	assert.Check(t, is.Len(containers, 1))
 
@@ -426,11 +425,9 @@ func TestCreateServiceSysctls(t *testing.T) {
 		// earlier version of this test had to get container logs and was much
 		// more complex)
 
-		// get all of the tasks of the service, so we can get the container
-		filter := filters.NewArgs()
-		filter.Add("service", serviceID)
+		// get all tasks of the service, so we can get the container
 		tasks, err := client.TaskList(ctx, types.TaskListOptions{
-			Filters: filter,
+			Filters: filters.NewArgs(filters.Arg("service", serviceID)),
 		})
 		assert.NilError(t, err)
 		assert.Check(t, is.Equal(len(tasks), 1))
@@ -504,11 +501,9 @@ func TestCreateServiceCapabilities(t *testing.T) {
 	// we know that the capabilities is plumbed correctly. everything below that
 	// level has been tested elsewhere.
 
-	// get all of the tasks of the service, so we can get the container
-	filter := filters.NewArgs()
-	filter.Add("service", serviceID)
+	// get all tasks of the service, so we can get the container
 	tasks, err := client.TaskList(ctx, types.TaskListOptions{
-		Filters: filter,
+		Filters: filters.NewArgs(filters.Arg("service", serviceID)),
 	})
 	assert.NilError(t, err)
 	assert.Check(t, is.Equal(len(tasks), 1))

+ 1 - 3
integration/service/list_test.go

@@ -57,10 +57,8 @@ func TestServiceListWithStatuses(t *testing.T) {
 		// serviceContainerCount function does not do. instead, we'll use a
 		// bespoke closure right here.
 		poll.WaitOn(t, func(log poll.LogT) poll.Result {
-			filter := filters.NewArgs()
-			filter.Add("service", id)
 			tasks, err := client.TaskList(context.Background(), types.TaskListOptions{
-				Filters: filter,
+				Filters: filters.NewArgs(filters.Arg("service", id)),
 			})
 
 			running := 0

+ 6 - 4
integration/service/update_test.go

@@ -328,10 +328,12 @@ func TestServiceUpdatePidsLimit(t *testing.T) {
 
 func getServiceTaskContainer(ctx context.Context, t *testing.T, cli client.APIClient, serviceID string) types.ContainerJSON {
 	t.Helper()
-	filter := filters.NewArgs()
-	filter.Add("service", serviceID)
-	filter.Add("desired-state", "running")
-	tasks, err := cli.TaskList(ctx, types.TaskListOptions{Filters: filter})
+	tasks, err := cli.TaskList(ctx, types.TaskListOptions{
+		Filters: filters.NewArgs(
+			filters.Arg("service", serviceID),
+			filters.Arg("desired-state", "running"),
+		),
+	})
 	assert.NilError(t, err)
 	assert.Assert(t, len(tasks) > 0)
 

+ 6 - 7
integration/system/event_test.go

@@ -43,12 +43,11 @@ func TestEventsExecDie(t *testing.T) {
 	)
 	assert.NilError(t, err)
 
-	filters := filters.NewArgs(
-		filters.Arg("container", cID),
-		filters.Arg("event", "exec_die"),
-	)
-	msg, errors := client.Events(ctx, types.EventsOptions{
-		Filters: filters,
+	msg, errs := client.Events(ctx, types.EventsOptions{
+		Filters: filters.NewArgs(
+			filters.Arg("container", cID),
+			filters.Arg("event", "exec_die"),
+		),
 	})
 
 	err = client.ContainerExecStart(ctx, id.ID,
@@ -66,7 +65,7 @@ func TestEventsExecDie(t *testing.T) {
 		assert.Equal(t, m.Action, "exec_die")
 		assert.Equal(t, m.Actor.Attributes["execID"], id.ID)
 		assert.Equal(t, m.Actor.Attributes["exitCode"], "0")
-	case err = <-errors:
+	case err = <-errs:
 		assert.NilError(t, err)
 	case <-time.After(time.Second * 3):
 		t.Fatal("timeout hit")

+ 4 - 3
testutil/daemon/service.go

@@ -55,9 +55,10 @@ func (d *Daemon) GetServiceTasks(t testing.TB, service string, additionalFilters
 	cli := d.NewClientT(t)
 	defer cli.Close()
 
-	filterArgs := filters.NewArgs()
-	filterArgs.Add("desired-state", "running")
-	filterArgs.Add("service", service)
+	filterArgs := filters.NewArgs(
+		filters.Arg("desired-state", "running"),
+		filters.Arg("service", service),
+	)
 	for _, filter := range additionalFilters {
 		filterArgs.Add(filter.Key, filter.Value)
 	}

+ 1 - 3
testutil/environment/clean.go

@@ -48,10 +48,8 @@ func unpauseAllContainers(t testing.TB, client client.ContainerAPIClient) {
 
 func getPausedContainers(ctx context.Context, t testing.TB, client client.ContainerAPIClient) []types.Container {
 	t.Helper()
-	filter := filters.NewArgs()
-	filter.Add("status", "paused")
 	containers, err := client.ContainerList(ctx, types.ContainerListOptions{
-		Filters: filter,
+		Filters: filters.NewArgs(filters.Arg("status", "paused")),
 		All:     true,
 	})
 	assert.Check(t, err, "failed to list containers")

+ 6 - 7
testutil/environment/environment.go

@@ -197,13 +197,12 @@ func (e *Execution) IsUserNamespaceInKernel() bool {
 // Note that this is done by filtering and then checking whether there were any
 // results -- so ambiguous references might result in false-positives.
 func (e *Execution) HasExistingImage(t testing.TB, reference string) bool {
-	client := e.APIClient()
-	filter := filters.NewArgs()
-	filter.Add("dangling", "false")
-	filter.Add("reference", reference)
-	imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
-		All:     true,
-		Filters: filter,
+	imageList, err := e.APIClient().ImageList(context.Background(), types.ImageListOptions{
+		All: true,
+		Filters: filters.NewArgs(
+			filters.Arg("dangling", "false"),
+			filters.Arg("reference", reference),
+		),
 	})
 	assert.NilError(t, err, "failed to list images")
 

+ 1 - 3
testutil/environment/protect.go

@@ -100,11 +100,9 @@ func ProtectImages(t testing.TB, testEnv *Execution) {
 func getExistingImages(t testing.TB, testEnv *Execution) []string {
 	t.Helper()
 	client := testEnv.APIClient()
-	filter := filters.NewArgs()
-	filter.Add("dangling", "false")
 	imageList, err := client.ImageList(context.Background(), types.ImageListOptions{
 		All:     true,
-		Filters: filter,
+		Filters: filters.NewArgs(filters.Arg("dangling", "false")),
 	})
 	assert.NilError(t, err, "failed to list images")
 

+ 19 - 18
volume/service/convert_test.go

@@ -14,9 +14,10 @@ func TestFilterWithPrune(t *testing.T) {
 	assert.Check(t, cmp.Len(f.Get("label"), 1))
 	assert.Check(t, f.Match("label", AnonymousLabel))
 
-	f = filters.NewArgs()
-	f.Add("label", "foo=bar")
-	f.Add("label", "bar=baz")
+	f = filters.NewArgs(
+		filters.Arg("label", "foo=bar"),
+		filters.Arg("label", "bar=baz"),
+	)
 	assert.NilError(t, withPrune(f))
 
 	assert.Check(t, cmp.Len(f.Get("label"), 3))
@@ -24,40 +25,40 @@ func TestFilterWithPrune(t *testing.T) {
 	assert.Check(t, f.Match("label", "foo=bar"))
 	assert.Check(t, f.Match("label", "bar=baz"))
 
-	f = filters.NewArgs()
-	f.Add("label", "foo=bar")
-	f.Add("all", "1")
+	f = filters.NewArgs(
+		filters.Arg("label", "foo=bar"),
+		filters.Arg("all", "1"),
+	)
 	assert.NilError(t, withPrune(f))
 
 	assert.Check(t, cmp.Len(f.Get("label"), 1))
 	assert.Check(t, f.Match("label", "foo=bar"))
 
-	f = filters.NewArgs()
-	f.Add("label", "foo=bar")
-	f.Add("all", "true")
+	f = filters.NewArgs(
+		filters.Arg("label", "foo=bar"),
+		filters.Arg("all", "true"),
+	)
 	assert.NilError(t, withPrune(f))
 
 	assert.Check(t, cmp.Len(f.Get("label"), 1))
 	assert.Check(t, f.Match("label", "foo=bar"))
 
-	f = filters.NewArgs()
-	f.Add("all", "0")
+	f = filters.NewArgs(filters.Arg("all", "0"))
 	assert.NilError(t, withPrune(f))
 	assert.Check(t, cmp.Len(f.Get("label"), 1))
 	assert.Check(t, f.Match("label", AnonymousLabel))
 
-	f = filters.NewArgs()
-	f.Add("all", "false")
+	f = filters.NewArgs(filters.Arg("all", "false"))
 	assert.NilError(t, withPrune(f))
 	assert.Check(t, cmp.Len(f.Get("label"), 1))
 	assert.Check(t, f.Match("label", AnonymousLabel))
 
-	f = filters.NewArgs()
-	f.Add("all", "")
+	f = filters.NewArgs(filters.Arg("all", ""))
 	assert.ErrorContains(t, withPrune(f), "invalid filter 'all'")
 
-	f = filters.NewArgs()
-	f.Add("all", "1")
-	f.Add("all", "0")
+	f = filters.NewArgs(
+		filters.Arg("all", "1"),
+		filters.Arg("all", "0"),
+	)
 	assert.ErrorContains(t, withPrune(f), "invalid filter 'all")
 }