func TestSelector(t *testing.T) { pods, svc := testData() labelKey := metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String()) b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), }), testapi.Default.Codec()). SelectorParam("a=b"). NamespaceParam("test"). Flatten() test := &testVisitor{} singular := false if b.Do().Err() == nil { t.Errorf("unexpected non-error") } b.ResourceTypeOrNameArgs(true, "pods,service") err := b.Do().IntoSingular(&singular).Visit(test.Handle) if err != nil || singular || len(test.Infos) != 3 { t.Fatalf("unexpected response: %v %t %#v", err, singular, test.Infos) } if !api.Semantic.DeepDerivative([]runtime.Object{&pods.Items[0], &pods.Items[1], &svc.Items[0]}, test.Objects()) { t.Errorf("unexpected visited objects: %#v", test.Objects()) } if _, err := b.Do().ResourceMapping(); err == nil { t.Errorf("unexpected non-error") } }
func TestListObjectWithDifferentVersions(t *testing.T) { pods, svc := testData() labelKey := metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String()) obj, err := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), "/namespaces/test/services?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), svc), }), testapi.Default.Codec()). SelectorParam("a=b"). NamespaceParam("test"). ResourceTypeOrNameArgs(true, "pods,services"). Flatten(). Do().Object() if err != nil { t.Fatalf("unexpected error: %v", err) } list, ok := obj.(*api.List) if !ok { t.Fatalf("unexpected object: %#v", obj) } // resource version differs between type lists, so it's not possible to get a single version. if list.ResourceVersion != "" || len(list.Items) != 3 { t.Errorf("unexpected list: %#v", list) } }
func TestListObject(t *testing.T) { pods, _ := testData() labelKey := metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String()) b := NewBuilder(testapi.Default.RESTMapper(), api.Scheme, fakeClientWith("", t, map[string]string{ "/namespaces/test/pods?" + labelKey + "=a%3Db": runtime.EncodeOrDie(testapi.Default.Codec(), pods), }), testapi.Default.Codec()). SelectorParam("a=b"). NamespaceParam("test"). ResourceTypeOrNameArgs(true, "pods"). Flatten() obj, err := b.Do().Object() if err != nil { t.Fatalf("unexpected error: %v", err) } list, ok := obj.(*api.List) if !ok { t.Fatalf("unexpected object: %#v", obj) } if list.ResourceVersion != pods.ResourceVersion || len(list.Items) != 2 { t.Errorf("unexpected list: %#v", list) } mapping, err := b.Do().ResourceMapping() if err != nil { t.Fatalf("unexpected error: %v", err) } if mapping.Resource != "pods" { t.Errorf("unexpected resource mapping: %#v", mapping) } }
func TestDeleteMultipleSelector(t *testing.T) { pods, svc, _ := testData() f, tf, codec, _ := cmdtesting.NewAPIFactory() tf.Printer = &testPrinter{} tf.Client = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { switch p, m := req.URL.Path, req.Method; { case p == "/namespaces/test/pods" && m == "GET": if req.URL.Query().Get(metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())) != "a=b" { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) } return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil case p == "/namespaces/test/services" && m == "GET": if req.URL.Query().Get(metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())) != "a=b" { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) } return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil case strings.HasPrefix(p, "/namespaces/test/pods/") && m == "DELETE": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &pods.Items[0])}, nil case strings.HasPrefix(p, "/namespaces/test/services/") && m == "DELETE": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, &svc.Items[0])}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } tf.Namespace = "test" buf, errBuf := bytes.NewBuffer([]byte{}), bytes.NewBuffer([]byte{}) cmd := NewCmdDelete(f, buf, errBuf) cmd.Flags().Set("selector", "a=b") cmd.Flags().Set("cascade", "false") cmd.Flags().Set("output", "name") cmd.Run(cmd, []string{"pods,services"}) if buf.String() != "pod/foo\npod/bar\nservice/baz\n" { t.Errorf("unexpected output: %s", buf.String()) } }
// LabelsSelectorParam adds the given selector as a query parameter func (r *Request) LabelsSelectorParam(s labels.Selector) *Request { if r.err != nil { return r } if s == nil { return r } if s.Empty() { return r } return r.setParam(metav1.LabelSelectorQueryParam(r.content.GroupVersion.String()), s.String()) }
// 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 == metav1.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 == metav1.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 TestWatchSelector(t *testing.T) { pods, events := watchTestData() f, tf, codec, _ := cmdtesting.NewAPIFactory() tf.Printer = &testPrinter{} podList := &api.PodList{ Items: pods, ListMeta: metav1.ListMeta{ ResourceVersion: "10", }, } tf.Client = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { if req.URL.Query().Get(metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())) != "a=b" { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) } switch req.URL.Path { case "/namespaces/test/pods": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, podList)}, nil case "/watch/namespaces/test/pods": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: watchBody(codec, events[2:])}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) errBuf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf, errBuf) cmd.SetOutput(buf) cmd.Flags().Set("watch", "true") cmd.Flags().Set("selector", "a=b") cmd.Run(cmd, []string{"pods"}) expected := []runtime.Object{podList, events[2].Object, events[3].Object} verifyObjects(t, expected, tf.Printer.(*testPrinter).Objects) if len(buf.String()) == 0 { t.Errorf("unexpected empty output") } }
func TestGetMultipleTypeObjectsWithSelector(t *testing.T) { pods, svc, _ := testData() f, tf, codec, _ := cmdtesting.NewAPIFactory() tf.Printer = &testPrinter{} tf.Client = &fake.RESTClient{ NegotiatedSerializer: unstructuredSerializer, Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { if req.URL.Query().Get(metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())) != "a=b" { t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) } switch req.URL.Path { case "/namespaces/test/pods": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, pods)}, nil case "/namespaces/test/services": return &http.Response{StatusCode: 200, Header: defaultHeader(), Body: objBody(codec, svc)}, nil default: t.Fatalf("unexpected request: %#v\n%#v", req.URL, req) return nil, nil } }), } tf.Namespace = "test" buf := bytes.NewBuffer([]byte{}) errBuf := bytes.NewBuffer([]byte{}) cmd := NewCmdGet(f, buf, errBuf) cmd.SetOutput(buf) cmd.Flags().Set("selector", "a=b") cmd.Run(cmd, []string{"pods,services"}) expected, err := extractResourceList([]runtime.Object{pods, svc}) if err != nil { t.Fatal(err) } verifyObjects(t, expected, tf.Printer.(*testPrinter).Objects) if len(buf.String()) == 0 { t.Errorf("unexpected empty output") } }
func TestDoRequestNewWayObj(t *testing.T) { reqObj := &api.Pod{ObjectMeta: api.ObjectMeta{Name: "foo"}} reqBodyExpected, _ := runtime.Encode(testapi.Default.Codec(), reqObj) expectedObj := &api.Service{Spec: api.ServiceSpec{Ports: []api.ServicePort{{ Protocol: "TCP", Port: 12345, TargetPort: intstr.FromInt(12345), }}}} expectedBody, _ := runtime.Encode(testapi.Default.Codec(), expectedObj) fakeHandler := utiltesting.FakeHandler{ StatusCode: 200, ResponseBody: string(expectedBody), T: t, } testServer := httptest.NewServer(&fakeHandler) defer testServer.Close() c := testRESTClient(t, testServer) obj, err := c.Verb("POST"). Suffix("baz"). Name("bar"). Resource("foo"). LabelsSelectorParam(labels.Set{"name": "foo"}.AsSelector()). Timeout(time.Second). Body(reqObj). Do().Get() if err != nil { t.Errorf("Unexpected error: %v %#v", err, err) return } if obj == nil { t.Error("nil obj") } else if !api.Semantic.DeepDerivative(expectedObj, obj) { t.Errorf("Expected: %#v, got %#v", expectedObj, obj) } tmpStr := string(reqBodyExpected) requestURL := testapi.Default.ResourcePath("foo", "", "bar/baz") requestURL += "?" + metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String()) + "=name%3Dfoo&timeout=1s" fakeHandler.ValidateRequest(t, requestURL, "POST", &tmpStr) }
func TestHelperList(t *testing.T) { tests := []struct { Err bool Req func(*http.Request) bool Resp *http.Response HttpErr error }{ { HttpErr: errors.New("failure"), Err: true, }, { Resp: &http.Response{ StatusCode: http.StatusNotFound, Header: header(), Body: objBody(&metav1.Status{Status: metav1.StatusFailure}), }, Err: true, }, { Resp: &http.Response{ StatusCode: http.StatusOK, Header: header(), Body: objBody(&api.PodList{ Items: []api.Pod{{ ObjectMeta: api.ObjectMeta{Name: "foo"}, }, }, }), }, Req: func(req *http.Request) bool { if req.Method != "GET" { t.Errorf("unexpected method: %#v", req) return false } if req.URL.Path != "/namespaces/bar" { t.Errorf("url doesn't contain name: %#v", req.URL) return false } if req.URL.Query().Get(metav1.LabelSelectorQueryParam(registered.GroupOrDie(api.GroupName).GroupVersion.String())) != labels.SelectorFromSet(labels.Set{"foo": "baz"}).String() { t.Errorf("url doesn't contain query parameters: %#v", req.URL) return false } return true }, }, } for _, test := range tests { client := &fake.RESTClient{ NegotiatedSerializer: testapi.Default.NegotiatedSerializer(), Resp: test.Resp, Err: test.HttpErr, } modifier := &Helper{ RESTClient: client, NamespaceScoped: true, } obj, err := modifier.List("bar", registered.GroupOrDie(api.GroupName).GroupVersion.String(), labels.SelectorFromSet(labels.Set{"foo": "baz"}), false) if (err != nil) != test.Err { t.Errorf("unexpected error: %t %v", test.Err, err) } if err != nil { continue } if obj.(*api.PodList).Items[0].Name != "foo" { t.Errorf("unexpected object: %#v", obj) } if test.Req != nil && !test.Req(client.Req) { t.Errorf("unexpected request: %#v", client.Req) } } }