func (c *Client) ValidateCommon(t *testing.T, err error) { if c.Error { if err == nil { t.Errorf("error expected for %#v, got none", c.Request) } return } if err != nil { t.Errorf("no error expected for %#v, got: %v", c.Request, err) } if c.handler.RequestReceived == nil { t.Errorf("handler had an empty request, %#v", c) return } requestBody := body(t, c.Request.Body, c.Request.RawBody) actualQuery := c.handler.RequestReceived.URL.Query() t.Logf("got query: %v", actualQuery) t.Logf("path: %v", c.Request.Path) // We check the query manually, so blank it out so that FakeHandler.ValidateRequest // won't check it. c.handler.RequestReceived.URL.RawQuery = "" c.handler.ValidateRequest(t, path.Join(c.Request.Path), c.Request.Method, requestBody) for key, values := range c.Request.Query { validator, ok := c.QueryValidator[key] if !ok { switch key { case unversioned.LabelSelectorQueryParam(testapi.Default.GroupVersion().String()): validator = ValidateLabels case unversioned.FieldSelectorQueryParam(testapi.Default.GroupVersion().String()): validator = validateFields default: validator = func(a, b string) bool { return a == b } } } observed := actualQuery.Get(key) wanted := strings.Join(values, "") if !validator(wanted, observed) { t.Errorf("Unexpected query arg for key: %s. Expected %s, Received %s", key, wanted, observed) } } if c.Request.Header != "" { if c.handler.RequestReceived.Header.Get(c.Request.Header) == "" { t.Errorf("header %q not found in request %#v", c.Request.Header, c.handler.RequestReceived) } } if expected, received := requestBody, c.handler.RequestBody; expected != nil && *expected != received { t.Errorf("bad body for request %#v: expected %s, got %s", c.Request, *expected, received) } }
// VersionedParams will take the provided object, serialize it to a map[string][]string using the // implicit RESTClient API version and the default parameter codec, and then add those as parameters // to the request. Use this to provide versioned query parameters from client libraries. func (r *Request) VersionedParams(obj runtime.Object, codec runtime.ParameterCodec) *Request { if r.err != nil { return r } params, err := codec.EncodeParameters(obj, *r.content.GroupVersion) if err != nil { r.err = err return r } for k, v := range params { for _, value := range v { // TODO: Move it to setParam method, once we get rid of // FieldSelectorParam & LabelSelectorParam methods. if k == unversioned.LabelSelectorQueryParam(r.content.GroupVersion.String()) && value == "" { // Don't set an empty selector for backward compatibility. // Since there is no way to get the difference between empty // and unspecified string, we don't set it to avoid having // labelSelector= param in every request. continue } if k == unversioned.FieldSelectorQueryParam(r.content.GroupVersion.String()) { if len(value) == 0 { // Don't set an empty selector for backward compatibility. // Since there is no way to get the difference between empty // and unspecified string, we don't set it to avoid having // fieldSelector= param in every request. continue } // TODO: Filtering should be handled somewhere else. selector, err := fields.ParseSelector(value) if err != nil { r.err = fmt.Errorf("unparsable field selector: %v", err) return r } filteredSelector, err := selector.Transform( func(field, value string) (newField, newValue string, err error) { return fieldMappings.filterField(r.content.GroupVersion, r.resource, field, value) }) if err != nil { r.err = fmt.Errorf("untransformable field selector: %v", err) return r } value = filteredSelector.String() } r.setParam(k, value) } } return r }
func TestListWatchesCanList(t *testing.T) { fieldSelectorQueryParamName := unversioned.FieldSelectorQueryParam(testapi.Default.GroupVersion().String()) table := []struct { location string resource string namespace string fieldSelector fields.Selector }{ // Node { location: testapi.Default.ResourcePath("nodes", api.NamespaceAll, ""), resource: "nodes", namespace: api.NamespaceAll, fieldSelector: parseSelectorOrDie(""), }, // pod with "assigned" field selector. { location: buildLocation( testapi.Default.ResourcePath("pods", api.NamespaceAll, ""), buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), resource: "pods", namespace: api.NamespaceAll, fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), }, // pod in namespace "foo" { location: buildLocation( testapi.Default.ResourcePath("pods", "foo", ""), buildQueryValues(url.Values{fieldSelectorQueryParamName: []string{"spec.host="}})), resource: "pods", namespace: "foo", fieldSelector: fields.Set{"spec.host": ""}.AsSelector(), }, } for _, item := range table { handler := utiltesting.FakeHandler{ StatusCode: 500, ResponseBody: "", T: t, } server := httptest.NewServer(&handler) // TODO: Uncomment when fix #19254 // defer server.Close() client := client.NewOrDie(&client.Config{Host: server.URL, ContentConfig: client.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}}) lw := NewListWatchFromClient(client, item.resource, item.namespace, item.fieldSelector) // This test merely tests that the correct request is made. lw.List(api.ListOptions{}) handler.ValidateRequest(t, item.location, "GET", nil) } }
// FieldsSelectorParam adds the given selector as a query parameter with the name paramName. func (r *Request) FieldsSelectorParam(s fields.Selector) *Request { if r.err != nil { return r } if s == nil { return r } if s.Empty() { return r } s2, err := s.Transform(func(field, value string) (newField, newValue string, err error) { return fieldMappings.filterField(r.content.GroupVersion, r.resource, field, value) }) if err != nil { r.err = err return r } return r.setParam(unversioned.FieldSelectorQueryParam(r.content.GroupVersion.String()), s2.String()) }