Browse code

Fixes ImageList to be retro-compatible with older API

Make sure current client code can talk for ImageList can still talk to
older daemon.

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2016/11/29 06:15:50
Showing 3 changed files
... ...
@@ -144,6 +144,9 @@ func (filters Args) Add(name, value string) {
144 144
 func (filters Args) Del(name, value string) {
145 145
 	if _, ok := filters.fields[name]; ok {
146 146
 		delete(filters.fields[name], value)
147
+		if len(filters.fields[name]) == 0 {
148
+			delete(filters.fields, name)
149
+		}
147 150
 	}
148 151
 }
149 152
 
... ...
@@ -6,6 +6,7 @@ import (
6 6
 
7 7
 	"github.com/docker/docker/api/types"
8 8
 	"github.com/docker/docker/api/types/filters"
9
+	"github.com/docker/docker/api/types/versions"
9 10
 	"golang.org/x/net/context"
10 11
 )
11 12
 
... ...
@@ -14,8 +15,16 @@ func (cli *Client) ImageList(ctx context.Context, options types.ImageListOptions
14 14
 	var images []types.ImageSummary
15 15
 	query := url.Values{}
16 16
 
17
-	if options.Filters.Len() > 0 {
18
-		filterJSON, err := filters.ToParamWithVersion(cli.version, options.Filters)
17
+	optionFilters := options.Filters
18
+	referenceFilters := optionFilters.Get("reference")
19
+	if versions.LessThan(cli.version, "1.25") && len(referenceFilters) > 0 {
20
+		query.Set("filter", referenceFilters[0])
21
+		for _, filterValue := range referenceFilters {
22
+			optionFilters.Del("reference", filterValue)
23
+		}
24
+	}
25
+	if optionFilters.Len() > 0 {
26
+		filterJSON, err := filters.ToParamWithVersion(cli.version, optionFilters)
19 27
 		if err != nil {
20 28
 			return images, err
21 29
 		}
... ...
@@ -109,3 +109,51 @@ func TestImageList(t *testing.T) {
109 109
 		}
110 110
 	}
111 111
 }
112
+
113
+func TestImageListApiBefore125(t *testing.T) {
114
+	expectedFilter := "image:tag"
115
+	client := &Client{
116
+		client: newMockClient(func(req *http.Request) (*http.Response, error) {
117
+			query := req.URL.Query()
118
+			actualFilter := query.Get("filter")
119
+			if actualFilter != expectedFilter {
120
+				return nil, fmt.Errorf("filter not set in URL query properly. Expected '%s', got %s", expectedFilter, actualFilter)
121
+			}
122
+			actualFilters := query.Get("filters")
123
+			if actualFilters != "" {
124
+				return nil, fmt.Errorf("filters should have not been present, were with value: %s", actualFilters)
125
+			}
126
+			content, err := json.Marshal([]types.ImageSummary{
127
+				{
128
+					ID: "image_id2",
129
+				},
130
+				{
131
+					ID: "image_id2",
132
+				},
133
+			})
134
+			if err != nil {
135
+				return nil, err
136
+			}
137
+			return &http.Response{
138
+				StatusCode: http.StatusOK,
139
+				Body:       ioutil.NopCloser(bytes.NewReader(content)),
140
+			}, nil
141
+		}),
142
+		version: "1.24",
143
+	}
144
+
145
+	filters := filters.NewArgs()
146
+	filters.Add("reference", "image:tag")
147
+
148
+	options := types.ImageListOptions{
149
+		Filters: filters,
150
+	}
151
+
152
+	images, err := client.ImageList(context.Background(), options)
153
+	if err != nil {
154
+		t.Fatal(err)
155
+	}
156
+	if len(images) != 2 {
157
+		t.Fatalf("expected 2 images, got %v", images)
158
+	}
159
+}